162306a36Sopenharmony_ci|
262306a36Sopenharmony_ci|	setox.sa 3.1 12/10/90
362306a36Sopenharmony_ci|
462306a36Sopenharmony_ci|	The entry point setox computes the exponential of a value.
562306a36Sopenharmony_ci|	setoxd does the same except the input value is a denormalized
662306a36Sopenharmony_ci|	number.	setoxm1 computes exp(X)-1, and setoxm1d computes
762306a36Sopenharmony_ci|	exp(X)-1 for denormalized X.
862306a36Sopenharmony_ci|
962306a36Sopenharmony_ci|	INPUT
1062306a36Sopenharmony_ci|	-----
1162306a36Sopenharmony_ci|	Double-extended value in memory location pointed to by address
1262306a36Sopenharmony_ci|	register a0.
1362306a36Sopenharmony_ci|
1462306a36Sopenharmony_ci|	OUTPUT
1562306a36Sopenharmony_ci|	------
1662306a36Sopenharmony_ci|	exp(X) or exp(X)-1 returned in floating-point register fp0.
1762306a36Sopenharmony_ci|
1862306a36Sopenharmony_ci|	ACCURACY and MONOTONICITY
1962306a36Sopenharmony_ci|	-------------------------
2062306a36Sopenharmony_ci|	The returned result is within 0.85 ulps in 64 significant bit, i.e.
2162306a36Sopenharmony_ci|	within 0.5001 ulp to 53 bits if the result is subsequently rounded
2262306a36Sopenharmony_ci|	to double precision. The result is provably monotonic in double
2362306a36Sopenharmony_ci|	precision.
2462306a36Sopenharmony_ci|
2562306a36Sopenharmony_ci|	SPEED
2662306a36Sopenharmony_ci|	-----
2762306a36Sopenharmony_ci|	Two timings are measured, both in the copy-back mode. The
2862306a36Sopenharmony_ci|	first one is measured when the function is invoked the first time
2962306a36Sopenharmony_ci|	(so the instructions and data are not in cache), and the
3062306a36Sopenharmony_ci|	second one is measured when the function is reinvoked at the same
3162306a36Sopenharmony_ci|	input argument.
3262306a36Sopenharmony_ci|
3362306a36Sopenharmony_ci|	The program setox takes approximately 210/190 cycles for input
3462306a36Sopenharmony_ci|	argument X whose magnitude is less than 16380 log2, which
3562306a36Sopenharmony_ci|	is the usual situation.	For the less common arguments,
3662306a36Sopenharmony_ci|	depending on their values, the program may run faster or slower --
3762306a36Sopenharmony_ci|	but no worse than 10% slower even in the extreme cases.
3862306a36Sopenharmony_ci|
3962306a36Sopenharmony_ci|	The program setoxm1 takes approximately ??? / ??? cycles for input
4062306a36Sopenharmony_ci|	argument X, 0.25 <= |X| < 70log2. For |X| < 0.25, it takes
4162306a36Sopenharmony_ci|	approximately ??? / ??? cycles. For the less common arguments,
4262306a36Sopenharmony_ci|	depending on their values, the program may run faster or slower --
4362306a36Sopenharmony_ci|	but no worse than 10% slower even in the extreme cases.
4462306a36Sopenharmony_ci|
4562306a36Sopenharmony_ci|	ALGORITHM and IMPLEMENTATION NOTES
4662306a36Sopenharmony_ci|	----------------------------------
4762306a36Sopenharmony_ci|
4862306a36Sopenharmony_ci|	setoxd
4962306a36Sopenharmony_ci|	------
5062306a36Sopenharmony_ci|	Step 1.	Set ans := 1.0
5162306a36Sopenharmony_ci|
5262306a36Sopenharmony_ci|	Step 2.	Return	ans := ans + sign(X)*2^(-126). Exit.
5362306a36Sopenharmony_ci|	Notes:	This will always generate one exception -- inexact.
5462306a36Sopenharmony_ci|
5562306a36Sopenharmony_ci|
5662306a36Sopenharmony_ci|	setox
5762306a36Sopenharmony_ci|	-----
5862306a36Sopenharmony_ci|
5962306a36Sopenharmony_ci|	Step 1.	Filter out extreme cases of input argument.
6062306a36Sopenharmony_ci|		1.1	If |X| >= 2^(-65), go to Step 1.3.
6162306a36Sopenharmony_ci|		1.2	Go to Step 7.
6262306a36Sopenharmony_ci|		1.3	If |X| < 16380 log(2), go to Step 2.
6362306a36Sopenharmony_ci|		1.4	Go to Step 8.
6462306a36Sopenharmony_ci|	Notes:	The usual case should take the branches 1.1 -> 1.3 -> 2.
6562306a36Sopenharmony_ci|		 To avoid the use of floating-point comparisons, a
6662306a36Sopenharmony_ci|		 compact representation of |X| is used. This format is a
6762306a36Sopenharmony_ci|		 32-bit integer, the upper (more significant) 16 bits are
6862306a36Sopenharmony_ci|		 the sign and biased exponent field of |X|; the lower 16
6962306a36Sopenharmony_ci|		 bits are the 16 most significant fraction (including the
7062306a36Sopenharmony_ci|		 explicit bit) bits of |X|. Consequently, the comparisons
7162306a36Sopenharmony_ci|		 in Steps 1.1 and 1.3 can be performed by integer comparison.
7262306a36Sopenharmony_ci|		 Note also that the constant 16380 log(2) used in Step 1.3
7362306a36Sopenharmony_ci|		 is also in the compact form. Thus taking the branch
7462306a36Sopenharmony_ci|		 to Step 2 guarantees |X| < 16380 log(2). There is no harm
7562306a36Sopenharmony_ci|		 to have a small number of cases where |X| is less than,
7662306a36Sopenharmony_ci|		 but close to, 16380 log(2) and the branch to Step 9 is
7762306a36Sopenharmony_ci|		 taken.
7862306a36Sopenharmony_ci|
7962306a36Sopenharmony_ci|	Step 2.	Calculate N = round-to-nearest-int( X * 64/log2 ).
8062306a36Sopenharmony_ci|		2.1	Set AdjFlag := 0 (indicates the branch 1.3 -> 2 was taken)
8162306a36Sopenharmony_ci|		2.2	N := round-to-nearest-integer( X * 64/log2 ).
8262306a36Sopenharmony_ci|		2.3	Calculate	J = N mod 64; so J = 0,1,2,..., or 63.
8362306a36Sopenharmony_ci|		2.4	Calculate	M = (N - J)/64; so N = 64M + J.
8462306a36Sopenharmony_ci|		2.5	Calculate the address of the stored value of 2^(J/64).
8562306a36Sopenharmony_ci|		2.6	Create the value Scale = 2^M.
8662306a36Sopenharmony_ci|	Notes:	The calculation in 2.2 is really performed by
8762306a36Sopenharmony_ci|
8862306a36Sopenharmony_ci|			Z := X * constant
8962306a36Sopenharmony_ci|			N := round-to-nearest-integer(Z)
9062306a36Sopenharmony_ci|
9162306a36Sopenharmony_ci|		 where
9262306a36Sopenharmony_ci|
9362306a36Sopenharmony_ci|			constant := single-precision( 64/log 2 ).
9462306a36Sopenharmony_ci|
9562306a36Sopenharmony_ci|		 Using a single-precision constant avoids memory access.
9662306a36Sopenharmony_ci|		 Another effect of using a single-precision "constant" is
9762306a36Sopenharmony_ci|		 that the calculated value Z is
9862306a36Sopenharmony_ci|
9962306a36Sopenharmony_ci|			Z = X*(64/log2)*(1+eps), |eps| <= 2^(-24).
10062306a36Sopenharmony_ci|
10162306a36Sopenharmony_ci|		 This error has to be considered later in Steps 3 and 4.
10262306a36Sopenharmony_ci|
10362306a36Sopenharmony_ci|	Step 3.	Calculate X - N*log2/64.
10462306a36Sopenharmony_ci|		3.1	R := X + N*L1, where L1 := single-precision(-log2/64).
10562306a36Sopenharmony_ci|		3.2	R := R + N*L2, L2 := extended-precision(-log2/64 - L1).
10662306a36Sopenharmony_ci|	Notes:	a) The way L1 and L2 are chosen ensures L1+L2 approximate
10762306a36Sopenharmony_ci|		 the value	-log2/64	to 88 bits of accuracy.
10862306a36Sopenharmony_ci|		 b) N*L1 is exact because N is no longer than 22 bits and
10962306a36Sopenharmony_ci|		 L1 is no longer than 24 bits.
11062306a36Sopenharmony_ci|		 c) The calculation X+N*L1 is also exact due to cancellation.
11162306a36Sopenharmony_ci|		 Thus, R is practically X+N(L1+L2) to full 64 bits.
11262306a36Sopenharmony_ci|		 d) It is important to estimate how large can |R| be after
11362306a36Sopenharmony_ci|		 Step 3.2.
11462306a36Sopenharmony_ci|
11562306a36Sopenharmony_ci|			N = rnd-to-int( X*64/log2 (1+eps) ), |eps|<=2^(-24)
11662306a36Sopenharmony_ci|			X*64/log2 (1+eps)	=	N + f,	|f| <= 0.5
11762306a36Sopenharmony_ci|			X*64/log2 - N	=	f - eps*X 64/log2
11862306a36Sopenharmony_ci|			X - N*log2/64	=	f*log2/64 - eps*X
11962306a36Sopenharmony_ci|
12062306a36Sopenharmony_ci|
12162306a36Sopenharmony_ci|		 Now |X| <= 16446 log2, thus
12262306a36Sopenharmony_ci|
12362306a36Sopenharmony_ci|			|X - N*log2/64| <= (0.5 + 16446/2^(18))*log2/64
12462306a36Sopenharmony_ci|					<= 0.57 log2/64.
12562306a36Sopenharmony_ci|		 This bound will be used in Step 4.
12662306a36Sopenharmony_ci|
12762306a36Sopenharmony_ci|	Step 4.	Approximate exp(R)-1 by a polynomial
12862306a36Sopenharmony_ci|			p = R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5))))
12962306a36Sopenharmony_ci|	Notes:	a) In order to reduce memory access, the coefficients are
13062306a36Sopenharmony_ci|		 made as "short" as possible: A1 (which is 1/2), A4 and A5
13162306a36Sopenharmony_ci|		 are single precision; A2 and A3 are double precision.
13262306a36Sopenharmony_ci|		 b) Even with the restrictions above,
13362306a36Sopenharmony_ci|			|p - (exp(R)-1)| < 2^(-68.8) for all |R| <= 0.0062.
13462306a36Sopenharmony_ci|		 Note that 0.0062 is slightly bigger than 0.57 log2/64.
13562306a36Sopenharmony_ci|		 c) To fully utilize the pipeline, p is separated into
13662306a36Sopenharmony_ci|		 two independent pieces of roughly equal complexities
13762306a36Sopenharmony_ci|			p = [ R + R*S*(A2 + S*A4) ]	+
13862306a36Sopenharmony_ci|				[ S*(A1 + S*(A3 + S*A5)) ]
13962306a36Sopenharmony_ci|		 where S = R*R.
14062306a36Sopenharmony_ci|
14162306a36Sopenharmony_ci|	Step 5.	Compute 2^(J/64)*exp(R) = 2^(J/64)*(1+p) by
14262306a36Sopenharmony_ci|				ans := T + ( T*p + t)
14362306a36Sopenharmony_ci|		 where T and t are the stored values for 2^(J/64).
14462306a36Sopenharmony_ci|	Notes:	2^(J/64) is stored as T and t where T+t approximates
14562306a36Sopenharmony_ci|		 2^(J/64) to roughly 85 bits; T is in extended precision
14662306a36Sopenharmony_ci|		 and t is in single precision. Note also that T is rounded
14762306a36Sopenharmony_ci|		 to 62 bits so that the last two bits of T are zero. The
14862306a36Sopenharmony_ci|		 reason for such a special form is that T-1, T-2, and T-8
14962306a36Sopenharmony_ci|		 will all be exact --- a property that will give much
15062306a36Sopenharmony_ci|		 more accurate computation of the function EXPM1.
15162306a36Sopenharmony_ci|
15262306a36Sopenharmony_ci|	Step 6.	Reconstruction of exp(X)
15362306a36Sopenharmony_ci|			exp(X) = 2^M * 2^(J/64) * exp(R).
15462306a36Sopenharmony_ci|		6.1	If AdjFlag = 0, go to 6.3
15562306a36Sopenharmony_ci|		6.2	ans := ans * AdjScale
15662306a36Sopenharmony_ci|		6.3	Restore the user FPCR
15762306a36Sopenharmony_ci|		6.4	Return ans := ans * Scale. Exit.
15862306a36Sopenharmony_ci|	Notes:	If AdjFlag = 0, we have X = Mlog2 + Jlog2/64 + R,
15962306a36Sopenharmony_ci|		 |M| <= 16380, and Scale = 2^M. Moreover, exp(X) will
16062306a36Sopenharmony_ci|		 neither overflow nor underflow. If AdjFlag = 1, that
16162306a36Sopenharmony_ci|		 means that
16262306a36Sopenharmony_ci|			X = (M1+M)log2 + Jlog2/64 + R, |M1+M| >= 16380.
16362306a36Sopenharmony_ci|		 Hence, exp(X) may overflow or underflow or neither.
16462306a36Sopenharmony_ci|		 When that is the case, AdjScale = 2^(M1) where M1 is
16562306a36Sopenharmony_ci|		 approximately M. Thus 6.2 will never cause over/underflow.
16662306a36Sopenharmony_ci|		 Possible exception in 6.4 is overflow or underflow.
16762306a36Sopenharmony_ci|		 The inexact exception is not generated in 6.4. Although
16862306a36Sopenharmony_ci|		 one can argue that the inexact flag should always be
16962306a36Sopenharmony_ci|		 raised, to simulate that exception cost to much than the
17062306a36Sopenharmony_ci|		 flag is worth in practical uses.
17162306a36Sopenharmony_ci|
17262306a36Sopenharmony_ci|	Step 7.	Return 1 + X.
17362306a36Sopenharmony_ci|		7.1	ans := X
17462306a36Sopenharmony_ci|		7.2	Restore user FPCR.
17562306a36Sopenharmony_ci|		7.3	Return ans := 1 + ans. Exit
17662306a36Sopenharmony_ci|	Notes:	For non-zero X, the inexact exception will always be
17762306a36Sopenharmony_ci|		 raised by 7.3. That is the only exception raised by 7.3.
17862306a36Sopenharmony_ci|		 Note also that we use the FMOVEM instruction to move X
17962306a36Sopenharmony_ci|		 in Step 7.1 to avoid unnecessary trapping. (Although
18062306a36Sopenharmony_ci|		 the FMOVEM may not seem relevant since X is normalized,
18162306a36Sopenharmony_ci|		 the precaution will be useful in the library version of
18262306a36Sopenharmony_ci|		 this code where the separate entry for denormalized inputs
18362306a36Sopenharmony_ci|		 will be done away with.)
18462306a36Sopenharmony_ci|
18562306a36Sopenharmony_ci|	Step 8.	Handle exp(X) where |X| >= 16380log2.
18662306a36Sopenharmony_ci|		8.1	If |X| > 16480 log2, go to Step 9.
18762306a36Sopenharmony_ci|		(mimic 2.2 - 2.6)
18862306a36Sopenharmony_ci|		8.2	N := round-to-integer( X * 64/log2 )
18962306a36Sopenharmony_ci|		8.3	Calculate J = N mod 64, J = 0,1,...,63
19062306a36Sopenharmony_ci|		8.4	K := (N-J)/64, M1 := truncate(K/2), M = K-M1, AdjFlag := 1.
19162306a36Sopenharmony_ci|		8.5	Calculate the address of the stored value 2^(J/64).
19262306a36Sopenharmony_ci|		8.6	Create the values Scale = 2^M, AdjScale = 2^M1.
19362306a36Sopenharmony_ci|		8.7	Go to Step 3.
19462306a36Sopenharmony_ci|	Notes:	Refer to notes for 2.2 - 2.6.
19562306a36Sopenharmony_ci|
19662306a36Sopenharmony_ci|	Step 9.	Handle exp(X), |X| > 16480 log2.
19762306a36Sopenharmony_ci|		9.1	If X < 0, go to 9.3
19862306a36Sopenharmony_ci|		9.2	ans := Huge, go to 9.4
19962306a36Sopenharmony_ci|		9.3	ans := Tiny.
20062306a36Sopenharmony_ci|		9.4	Restore user FPCR.
20162306a36Sopenharmony_ci|		9.5	Return ans := ans * ans. Exit.
20262306a36Sopenharmony_ci|	Notes:	Exp(X) will surely overflow or underflow, depending on
20362306a36Sopenharmony_ci|		 X's sign. "Huge" and "Tiny" are respectively large/tiny
20462306a36Sopenharmony_ci|		 extended-precision numbers whose square over/underflow
20562306a36Sopenharmony_ci|		 with an inexact result. Thus, 9.5 always raises the
20662306a36Sopenharmony_ci|		 inexact together with either overflow or underflow.
20762306a36Sopenharmony_ci|
20862306a36Sopenharmony_ci|
20962306a36Sopenharmony_ci|	setoxm1d
21062306a36Sopenharmony_ci|	--------
21162306a36Sopenharmony_ci|
21262306a36Sopenharmony_ci|	Step 1.	Set ans := 0
21362306a36Sopenharmony_ci|
21462306a36Sopenharmony_ci|	Step 2.	Return	ans := X + ans. Exit.
21562306a36Sopenharmony_ci|	Notes:	This will return X with the appropriate rounding
21662306a36Sopenharmony_ci|		 precision prescribed by the user FPCR.
21762306a36Sopenharmony_ci|
21862306a36Sopenharmony_ci|	setoxm1
21962306a36Sopenharmony_ci|	-------
22062306a36Sopenharmony_ci|
22162306a36Sopenharmony_ci|	Step 1.	Check |X|
22262306a36Sopenharmony_ci|		1.1	If |X| >= 1/4, go to Step 1.3.
22362306a36Sopenharmony_ci|		1.2	Go to Step 7.
22462306a36Sopenharmony_ci|		1.3	If |X| < 70 log(2), go to Step 2.
22562306a36Sopenharmony_ci|		1.4	Go to Step 10.
22662306a36Sopenharmony_ci|	Notes:	The usual case should take the branches 1.1 -> 1.3 -> 2.
22762306a36Sopenharmony_ci|		 However, it is conceivable |X| can be small very often
22862306a36Sopenharmony_ci|		 because EXPM1 is intended to evaluate exp(X)-1 accurately
22962306a36Sopenharmony_ci|		 when |X| is small. For further details on the comparisons,
23062306a36Sopenharmony_ci|		 see the notes on Step 1 of setox.
23162306a36Sopenharmony_ci|
23262306a36Sopenharmony_ci|	Step 2.	Calculate N = round-to-nearest-int( X * 64/log2 ).
23362306a36Sopenharmony_ci|		2.1	N := round-to-nearest-integer( X * 64/log2 ).
23462306a36Sopenharmony_ci|		2.2	Calculate	J = N mod 64; so J = 0,1,2,..., or 63.
23562306a36Sopenharmony_ci|		2.3	Calculate	M = (N - J)/64; so N = 64M + J.
23662306a36Sopenharmony_ci|		2.4	Calculate the address of the stored value of 2^(J/64).
23762306a36Sopenharmony_ci|		2.5	Create the values Sc = 2^M and OnebySc := -2^(-M).
23862306a36Sopenharmony_ci|	Notes:	See the notes on Step 2 of setox.
23962306a36Sopenharmony_ci|
24062306a36Sopenharmony_ci|	Step 3.	Calculate X - N*log2/64.
24162306a36Sopenharmony_ci|		3.1	R := X + N*L1, where L1 := single-precision(-log2/64).
24262306a36Sopenharmony_ci|		3.2	R := R + N*L2, L2 := extended-precision(-log2/64 - L1).
24362306a36Sopenharmony_ci|	Notes:	Applying the analysis of Step 3 of setox in this case
24462306a36Sopenharmony_ci|		 shows that |R| <= 0.0055 (note that |X| <= 70 log2 in
24562306a36Sopenharmony_ci|		 this case).
24662306a36Sopenharmony_ci|
24762306a36Sopenharmony_ci|	Step 4.	Approximate exp(R)-1 by a polynomial
24862306a36Sopenharmony_ci|			p = R+R*R*(A1+R*(A2+R*(A3+R*(A4+R*(A5+R*A6)))))
24962306a36Sopenharmony_ci|	Notes:	a) In order to reduce memory access, the coefficients are
25062306a36Sopenharmony_ci|		 made as "short" as possible: A1 (which is 1/2), A5 and A6
25162306a36Sopenharmony_ci|		 are single precision; A2, A3 and A4 are double precision.
25262306a36Sopenharmony_ci|		 b) Even with the restriction above,
25362306a36Sopenharmony_ci|			|p - (exp(R)-1)| <	|R| * 2^(-72.7)
25462306a36Sopenharmony_ci|		 for all |R| <= 0.0055.
25562306a36Sopenharmony_ci|		 c) To fully utilize the pipeline, p is separated into
25662306a36Sopenharmony_ci|		 two independent pieces of roughly equal complexity
25762306a36Sopenharmony_ci|			p = [ R*S*(A2 + S*(A4 + S*A6)) ]	+
25862306a36Sopenharmony_ci|				[ R + S*(A1 + S*(A3 + S*A5)) ]
25962306a36Sopenharmony_ci|		 where S = R*R.
26062306a36Sopenharmony_ci|
26162306a36Sopenharmony_ci|	Step 5.	Compute 2^(J/64)*p by
26262306a36Sopenharmony_ci|				p := T*p
26362306a36Sopenharmony_ci|		 where T and t are the stored values for 2^(J/64).
26462306a36Sopenharmony_ci|	Notes:	2^(J/64) is stored as T and t where T+t approximates
26562306a36Sopenharmony_ci|		 2^(J/64) to roughly 85 bits; T is in extended precision
26662306a36Sopenharmony_ci|		 and t is in single precision. Note also that T is rounded
26762306a36Sopenharmony_ci|		 to 62 bits so that the last two bits of T are zero. The
26862306a36Sopenharmony_ci|		 reason for such a special form is that T-1, T-2, and T-8
26962306a36Sopenharmony_ci|		 will all be exact --- a property that will be exploited
27062306a36Sopenharmony_ci|		 in Step 6 below. The total relative error in p is no
27162306a36Sopenharmony_ci|		 bigger than 2^(-67.7) compared to the final result.
27262306a36Sopenharmony_ci|
27362306a36Sopenharmony_ci|	Step 6.	Reconstruction of exp(X)-1
27462306a36Sopenharmony_ci|			exp(X)-1 = 2^M * ( 2^(J/64) + p - 2^(-M) ).
27562306a36Sopenharmony_ci|		6.1	If M <= 63, go to Step 6.3.
27662306a36Sopenharmony_ci|		6.2	ans := T + (p + (t + OnebySc)). Go to 6.6
27762306a36Sopenharmony_ci|		6.3	If M >= -3, go to 6.5.
27862306a36Sopenharmony_ci|		6.4	ans := (T + (p + t)) + OnebySc. Go to 6.6
27962306a36Sopenharmony_ci|		6.5	ans := (T + OnebySc) + (p + t).
28062306a36Sopenharmony_ci|		6.6	Restore user FPCR.
28162306a36Sopenharmony_ci|		6.7	Return ans := Sc * ans. Exit.
28262306a36Sopenharmony_ci|	Notes:	The various arrangements of the expressions give accurate
28362306a36Sopenharmony_ci|		 evaluations.
28462306a36Sopenharmony_ci|
28562306a36Sopenharmony_ci|	Step 7.	exp(X)-1 for |X| < 1/4.
28662306a36Sopenharmony_ci|		7.1	If |X| >= 2^(-65), go to Step 9.
28762306a36Sopenharmony_ci|		7.2	Go to Step 8.
28862306a36Sopenharmony_ci|
28962306a36Sopenharmony_ci|	Step 8.	Calculate exp(X)-1, |X| < 2^(-65).
29062306a36Sopenharmony_ci|		8.1	If |X| < 2^(-16312), goto 8.3
29162306a36Sopenharmony_ci|		8.2	Restore FPCR; return ans := X - 2^(-16382). Exit.
29262306a36Sopenharmony_ci|		8.3	X := X * 2^(140).
29362306a36Sopenharmony_ci|		8.4	Restore FPCR; ans := ans - 2^(-16382).
29462306a36Sopenharmony_ci|		 Return ans := ans*2^(140). Exit
29562306a36Sopenharmony_ci|	Notes:	The idea is to return "X - tiny" under the user
29662306a36Sopenharmony_ci|		 precision and rounding modes. To avoid unnecessary
29762306a36Sopenharmony_ci|		 inefficiency, we stay away from denormalized numbers the
29862306a36Sopenharmony_ci|		 best we can. For |X| >= 2^(-16312), the straightforward
29962306a36Sopenharmony_ci|		 8.2 generates the inexact exception as the case warrants.
30062306a36Sopenharmony_ci|
30162306a36Sopenharmony_ci|	Step 9.	Calculate exp(X)-1, |X| < 1/4, by a polynomial
30262306a36Sopenharmony_ci|			p = X + X*X*(B1 + X*(B2 + ... + X*B12))
30362306a36Sopenharmony_ci|	Notes:	a) In order to reduce memory access, the coefficients are
30462306a36Sopenharmony_ci|		 made as "short" as possible: B1 (which is 1/2), B9 to B12
30562306a36Sopenharmony_ci|		 are single precision; B3 to B8 are double precision; and
30662306a36Sopenharmony_ci|		 B2 is double extended.
30762306a36Sopenharmony_ci|		 b) Even with the restriction above,
30862306a36Sopenharmony_ci|			|p - (exp(X)-1)| < |X| 2^(-70.6)
30962306a36Sopenharmony_ci|		 for all |X| <= 0.251.
31062306a36Sopenharmony_ci|		 Note that 0.251 is slightly bigger than 1/4.
31162306a36Sopenharmony_ci|		 c) To fully preserve accuracy, the polynomial is computed
31262306a36Sopenharmony_ci|		 as	X + ( S*B1 +	Q ) where S = X*X and
31362306a36Sopenharmony_ci|			Q	=	X*S*(B2 + X*(B3 + ... + X*B12))
31462306a36Sopenharmony_ci|		 d) To fully utilize the pipeline, Q is separated into
31562306a36Sopenharmony_ci|		 two independent pieces of roughly equal complexity
31662306a36Sopenharmony_ci|			Q = [ X*S*(B2 + S*(B4 + ... + S*B12)) ] +
31762306a36Sopenharmony_ci|				[ S*S*(B3 + S*(B5 + ... + S*B11)) ]
31862306a36Sopenharmony_ci|
31962306a36Sopenharmony_ci|	Step 10.	Calculate exp(X)-1 for |X| >= 70 log 2.
32062306a36Sopenharmony_ci|		10.1 If X >= 70log2 , exp(X) - 1 = exp(X) for all practical
32162306a36Sopenharmony_ci|		 purposes. Therefore, go to Step 1 of setox.
32262306a36Sopenharmony_ci|		10.2 If X <= -70log2, exp(X) - 1 = -1 for all practical purposes.
32362306a36Sopenharmony_ci|		 ans := -1
32462306a36Sopenharmony_ci|		 Restore user FPCR
32562306a36Sopenharmony_ci|		 Return ans := ans + 2^(-126). Exit.
32662306a36Sopenharmony_ci|	Notes:	10.2 will always create an inexact and return -1 + tiny
32762306a36Sopenharmony_ci|		 in the user rounding precision and mode.
32862306a36Sopenharmony_ci|
32962306a36Sopenharmony_ci|
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci|		Copyright (C) Motorola, Inc. 1990
33262306a36Sopenharmony_ci|			All Rights Reserved
33362306a36Sopenharmony_ci|
33462306a36Sopenharmony_ci|       For details on the license for this file, please see the
33562306a36Sopenharmony_ci|       file, README, in this same directory.
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci|setox	idnt	2,1 | Motorola 040 Floating Point Software Package
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	|section	8
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci#include "fpsp.h"
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ciL2:	.long	0x3FDC0000,0x82E30865,0x4361C4C6,0x00000000
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ciEXPA3:	.long	0x3FA55555,0x55554431
34662306a36Sopenharmony_ciEXPA2:	.long	0x3FC55555,0x55554018
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ciHUGE:	.long	0x7FFE0000,0xFFFFFFFF,0xFFFFFFFF,0x00000000
34962306a36Sopenharmony_ciTINY:	.long	0x00010000,0xFFFFFFFF,0xFFFFFFFF,0x00000000
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ciEM1A4:	.long	0x3F811111,0x11174385
35262306a36Sopenharmony_ciEM1A3:	.long	0x3FA55555,0x55554F5A
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ciEM1A2:	.long	0x3FC55555,0x55555555,0x00000000,0x00000000
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ciEM1B8:	.long	0x3EC71DE3,0xA5774682
35762306a36Sopenharmony_ciEM1B7:	.long	0x3EFA01A0,0x19D7CB68
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ciEM1B6:	.long	0x3F2A01A0,0x1A019DF3
36062306a36Sopenharmony_ciEM1B5:	.long	0x3F56C16C,0x16C170E2
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ciEM1B4:	.long	0x3F811111,0x11111111
36362306a36Sopenharmony_ciEM1B3:	.long	0x3FA55555,0x55555555
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ciEM1B2:	.long	0x3FFC0000,0xAAAAAAAA,0xAAAAAAAB
36662306a36Sopenharmony_ci	.long	0x00000000
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ciTWO140:	.long	0x48B00000,0x00000000
36962306a36Sopenharmony_ciTWON140:	.long	0x37300000,0x00000000
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ciEXPTBL:
37262306a36Sopenharmony_ci	.long	0x3FFF0000,0x80000000,0x00000000,0x00000000
37362306a36Sopenharmony_ci	.long	0x3FFF0000,0x8164D1F3,0xBC030774,0x9F841A9B
37462306a36Sopenharmony_ci	.long	0x3FFF0000,0x82CD8698,0xAC2BA1D8,0x9FC1D5B9
37562306a36Sopenharmony_ci	.long	0x3FFF0000,0x843A28C3,0xACDE4048,0xA0728369
37662306a36Sopenharmony_ci	.long	0x3FFF0000,0x85AAC367,0xCC487B14,0x1FC5C95C
37762306a36Sopenharmony_ci	.long	0x3FFF0000,0x871F6196,0x9E8D1010,0x1EE85C9F
37862306a36Sopenharmony_ci	.long	0x3FFF0000,0x88980E80,0x92DA8528,0x9FA20729
37962306a36Sopenharmony_ci	.long	0x3FFF0000,0x8A14D575,0x496EFD9C,0xA07BF9AF
38062306a36Sopenharmony_ci	.long	0x3FFF0000,0x8B95C1E3,0xEA8BD6E8,0xA0020DCF
38162306a36Sopenharmony_ci	.long	0x3FFF0000,0x8D1ADF5B,0x7E5BA9E4,0x205A63DA
38262306a36Sopenharmony_ci	.long	0x3FFF0000,0x8EA4398B,0x45CD53C0,0x1EB70051
38362306a36Sopenharmony_ci	.long	0x3FFF0000,0x9031DC43,0x1466B1DC,0x1F6EB029
38462306a36Sopenharmony_ci	.long	0x3FFF0000,0x91C3D373,0xAB11C338,0xA0781494
38562306a36Sopenharmony_ci	.long	0x3FFF0000,0x935A2B2F,0x13E6E92C,0x9EB319B0
38662306a36Sopenharmony_ci	.long	0x3FFF0000,0x94F4EFA8,0xFEF70960,0x2017457D
38762306a36Sopenharmony_ci	.long	0x3FFF0000,0x96942D37,0x20185A00,0x1F11D537
38862306a36Sopenharmony_ci	.long	0x3FFF0000,0x9837F051,0x8DB8A970,0x9FB952DD
38962306a36Sopenharmony_ci	.long	0x3FFF0000,0x99E04593,0x20B7FA64,0x1FE43087
39062306a36Sopenharmony_ci	.long	0x3FFF0000,0x9B8D39B9,0xD54E5538,0x1FA2A818
39162306a36Sopenharmony_ci	.long	0x3FFF0000,0x9D3ED9A7,0x2CFFB750,0x1FDE494D
39262306a36Sopenharmony_ci	.long	0x3FFF0000,0x9EF53260,0x91A111AC,0x20504890
39362306a36Sopenharmony_ci	.long	0x3FFF0000,0xA0B0510F,0xB9714FC4,0xA073691C
39462306a36Sopenharmony_ci	.long	0x3FFF0000,0xA2704303,0x0C496818,0x1F9B7A05
39562306a36Sopenharmony_ci	.long	0x3FFF0000,0xA43515AE,0x09E680A0,0xA0797126
39662306a36Sopenharmony_ci	.long	0x3FFF0000,0xA5FED6A9,0xB15138EC,0xA071A140
39762306a36Sopenharmony_ci	.long	0x3FFF0000,0xA7CD93B4,0xE9653568,0x204F62DA
39862306a36Sopenharmony_ci	.long	0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x1F283C4A
39962306a36Sopenharmony_ci	.long	0x3FFF0000,0xAB7A39B5,0xA93ED338,0x9F9A7FDC
40062306a36Sopenharmony_ci	.long	0x3FFF0000,0xAD583EEA,0x42A14AC8,0xA05B3FAC
40162306a36Sopenharmony_ci	.long	0x3FFF0000,0xAF3B78AD,0x690A4374,0x1FDF2610
40262306a36Sopenharmony_ci	.long	0x3FFF0000,0xB123F581,0xD2AC2590,0x9F705F90
40362306a36Sopenharmony_ci	.long	0x3FFF0000,0xB311C412,0xA9112488,0x201F678A
40462306a36Sopenharmony_ci	.long	0x3FFF0000,0xB504F333,0xF9DE6484,0x1F32FB13
40562306a36Sopenharmony_ci	.long	0x3FFF0000,0xB6FD91E3,0x28D17790,0x20038B30
40662306a36Sopenharmony_ci	.long	0x3FFF0000,0xB8FBAF47,0x62FB9EE8,0x200DC3CC
40762306a36Sopenharmony_ci	.long	0x3FFF0000,0xBAFF5AB2,0x133E45FC,0x9F8B2AE6
40862306a36Sopenharmony_ci	.long	0x3FFF0000,0xBD08A39F,0x580C36C0,0xA02BBF70
40962306a36Sopenharmony_ci	.long	0x3FFF0000,0xBF1799B6,0x7A731084,0xA00BF518
41062306a36Sopenharmony_ci	.long	0x3FFF0000,0xC12C4CCA,0x66709458,0xA041DD41
41162306a36Sopenharmony_ci	.long	0x3FFF0000,0xC346CCDA,0x24976408,0x9FDF137B
41262306a36Sopenharmony_ci	.long	0x3FFF0000,0xC5672A11,0x5506DADC,0x201F1568
41362306a36Sopenharmony_ci	.long	0x3FFF0000,0xC78D74C8,0xABB9B15C,0x1FC13A2E
41462306a36Sopenharmony_ci	.long	0x3FFF0000,0xC9B9BD86,0x6E2F27A4,0xA03F8F03
41562306a36Sopenharmony_ci	.long	0x3FFF0000,0xCBEC14FE,0xF2727C5C,0x1FF4907D
41662306a36Sopenharmony_ci	.long	0x3FFF0000,0xCE248C15,0x1F8480E4,0x9E6E53E4
41762306a36Sopenharmony_ci	.long	0x3FFF0000,0xD06333DA,0xEF2B2594,0x1FD6D45C
41862306a36Sopenharmony_ci	.long	0x3FFF0000,0xD2A81D91,0xF12AE45C,0xA076EDB9
41962306a36Sopenharmony_ci	.long	0x3FFF0000,0xD4F35AAB,0xCFEDFA20,0x9FA6DE21
42062306a36Sopenharmony_ci	.long	0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x1EE69A2F
42162306a36Sopenharmony_ci	.long	0x3FFF0000,0xD99D15C2,0x78AFD7B4,0x207F439F
42262306a36Sopenharmony_ci	.long	0x3FFF0000,0xDBFBB797,0xDAF23754,0x201EC207
42362306a36Sopenharmony_ci	.long	0x3FFF0000,0xDE60F482,0x5E0E9124,0x9E8BE175
42462306a36Sopenharmony_ci	.long	0x3FFF0000,0xE0CCDEEC,0x2A94E110,0x20032C4B
42562306a36Sopenharmony_ci	.long	0x3FFF0000,0xE33F8972,0xBE8A5A50,0x2004DFF5
42662306a36Sopenharmony_ci	.long	0x3FFF0000,0xE5B906E7,0x7C8348A8,0x1E72F47A
42762306a36Sopenharmony_ci	.long	0x3FFF0000,0xE8396A50,0x3C4BDC68,0x1F722F22
42862306a36Sopenharmony_ci	.long	0x3FFF0000,0xEAC0C6E7,0xDD243930,0xA017E945
42962306a36Sopenharmony_ci	.long	0x3FFF0000,0xED4F301E,0xD9942B84,0x1F401A5B
43062306a36Sopenharmony_ci	.long	0x3FFF0000,0xEFE4B99B,0xDCDAF5CC,0x9FB9A9E3
43162306a36Sopenharmony_ci	.long	0x3FFF0000,0xF281773C,0x59FFB138,0x20744C05
43262306a36Sopenharmony_ci	.long	0x3FFF0000,0xF5257D15,0x2486CC2C,0x1F773A19
43362306a36Sopenharmony_ci	.long	0x3FFF0000,0xF7D0DF73,0x0AD13BB8,0x1FFE90D5
43462306a36Sopenharmony_ci	.long	0x3FFF0000,0xFA83B2DB,0x722A033C,0xA041ED22
43562306a36Sopenharmony_ci	.long	0x3FFF0000,0xFD3E0C0C,0xF486C174,0x1F853F3A
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	.set	ADJFLAG,L_SCR2
43862306a36Sopenharmony_ci	.set	SCALE,FP_SCR1
43962306a36Sopenharmony_ci	.set	ADJSCALE,FP_SCR2
44062306a36Sopenharmony_ci	.set	SC,FP_SCR3
44162306a36Sopenharmony_ci	.set	ONEBYSC,FP_SCR4
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci	| xref	t_frcinx
44462306a36Sopenharmony_ci	|xref	t_extdnrm
44562306a36Sopenharmony_ci	|xref	t_unfl
44662306a36Sopenharmony_ci	|xref	t_ovfl
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci	.global	setoxd
44962306a36Sopenharmony_cisetoxd:
45062306a36Sopenharmony_ci|--entry point for EXP(X), X is denormalized
45162306a36Sopenharmony_ci	movel		(%a0),%d0
45262306a36Sopenharmony_ci	andil		#0x80000000,%d0
45362306a36Sopenharmony_ci	oril		#0x00800000,%d0		| ...sign(X)*2^(-126)
45462306a36Sopenharmony_ci	movel		%d0,-(%sp)
45562306a36Sopenharmony_ci	fmoves		#0x3F800000,%fp0
45662306a36Sopenharmony_ci	fmovel		%d1,%fpcr
45762306a36Sopenharmony_ci	fadds		(%sp)+,%fp0
45862306a36Sopenharmony_ci	bra		t_frcinx
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	.global	setox
46162306a36Sopenharmony_cisetox:
46262306a36Sopenharmony_ci|--entry point for EXP(X), here X is finite, non-zero, and not NaN's
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci|--Step 1.
46562306a36Sopenharmony_ci	movel		(%a0),%d0	 | ...load part of input X
46662306a36Sopenharmony_ci	andil		#0x7FFF0000,%d0	| ...biased expo. of X
46762306a36Sopenharmony_ci	cmpil		#0x3FBE0000,%d0	| ...2^(-65)
46862306a36Sopenharmony_ci	bges		EXPC1		| ...normal case
46962306a36Sopenharmony_ci	bra		EXPSM
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ciEXPC1:
47262306a36Sopenharmony_ci|--The case |X| >= 2^(-65)
47362306a36Sopenharmony_ci	movew		4(%a0),%d0	| ...expo. and partial sig. of |X|
47462306a36Sopenharmony_ci	cmpil		#0x400CB167,%d0	| ...16380 log2 trunc. 16 bits
47562306a36Sopenharmony_ci	blts		EXPMAIN	 | ...normal case
47662306a36Sopenharmony_ci	bra		EXPBIG
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ciEXPMAIN:
47962306a36Sopenharmony_ci|--Step 2.
48062306a36Sopenharmony_ci|--This is the normal branch:	2^(-65) <= |X| < 16380 log2.
48162306a36Sopenharmony_ci	fmovex		(%a0),%fp0	| ...load input from (a0)
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_ci	fmovex		%fp0,%fp1
48462306a36Sopenharmony_ci	fmuls		#0x42B8AA3B,%fp0	| ...64/log2 * X
48562306a36Sopenharmony_ci	fmovemx	%fp2-%fp2/%fp3,-(%a7)		| ...save fp2
48662306a36Sopenharmony_ci	movel		#0,ADJFLAG(%a6)
48762306a36Sopenharmony_ci	fmovel		%fp0,%d0		| ...N = int( X * 64/log2 )
48862306a36Sopenharmony_ci	lea		EXPTBL,%a1
48962306a36Sopenharmony_ci	fmovel		%d0,%fp0		| ...convert to floating-format
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci	movel		%d0,L_SCR1(%a6)	| ...save N temporarily
49262306a36Sopenharmony_ci	andil		#0x3F,%d0		| ...D0 is J = N mod 64
49362306a36Sopenharmony_ci	lsll		#4,%d0
49462306a36Sopenharmony_ci	addal		%d0,%a1		| ...address of 2^(J/64)
49562306a36Sopenharmony_ci	movel		L_SCR1(%a6),%d0
49662306a36Sopenharmony_ci	asrl		#6,%d0		| ...D0 is M
49762306a36Sopenharmony_ci	addiw		#0x3FFF,%d0	| ...biased expo. of 2^(M)
49862306a36Sopenharmony_ci	movew		L2,L_SCR1(%a6)	| ...prefetch L2, no need in CB
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ciEXPCONT1:
50162306a36Sopenharmony_ci|--Step 3.
50262306a36Sopenharmony_ci|--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,
50362306a36Sopenharmony_ci|--a0 points to 2^(J/64), D0 is biased expo. of 2^(M)
50462306a36Sopenharmony_ci	fmovex		%fp0,%fp2
50562306a36Sopenharmony_ci	fmuls		#0xBC317218,%fp0	| ...N * L1, L1 = lead(-log2/64)
50662306a36Sopenharmony_ci	fmulx		L2,%fp2		| ...N * L2, L1+L2 = -log2/64
50762306a36Sopenharmony_ci	faddx		%fp1,%fp0		| ...X + N*L1
50862306a36Sopenharmony_ci	faddx		%fp2,%fp0		| ...fp0 is R, reduced arg.
50962306a36Sopenharmony_ci|	MOVE.W		#$3FA5,EXPA3	...load EXPA3 in cache
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci|--Step 4.
51262306a36Sopenharmony_ci|--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL
51362306a36Sopenharmony_ci|-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5))))
51462306a36Sopenharmony_ci|--TO FULLY UTILIZE THE PIPELINE, WE COMPUTE S = R*R
51562306a36Sopenharmony_ci|--[R+R*S*(A2+S*A4)] + [S*(A1+S*(A3+S*A5))]
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci	fmovex		%fp0,%fp1
51862306a36Sopenharmony_ci	fmulx		%fp1,%fp1		| ...fp1 IS S = R*R
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	fmoves		#0x3AB60B70,%fp2	| ...fp2 IS A5
52162306a36Sopenharmony_ci|	MOVE.W		#0,2(%a1)	...load 2^(J/64) in cache
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	fmulx		%fp1,%fp2		| ...fp2 IS S*A5
52462306a36Sopenharmony_ci	fmovex		%fp1,%fp3
52562306a36Sopenharmony_ci	fmuls		#0x3C088895,%fp3	| ...fp3 IS S*A4
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	faddd		EXPA3,%fp2	| ...fp2 IS A3+S*A5
52862306a36Sopenharmony_ci	faddd		EXPA2,%fp3	| ...fp3 IS A2+S*A4
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	fmulx		%fp1,%fp2		| ...fp2 IS S*(A3+S*A5)
53162306a36Sopenharmony_ci	movew		%d0,SCALE(%a6)	| ...SCALE is 2^(M) in extended
53262306a36Sopenharmony_ci	clrw		SCALE+2(%a6)
53362306a36Sopenharmony_ci	movel		#0x80000000,SCALE+4(%a6)
53462306a36Sopenharmony_ci	clrl		SCALE+8(%a6)
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	fmulx		%fp1,%fp3		| ...fp3 IS S*(A2+S*A4)
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	fadds		#0x3F000000,%fp2	| ...fp2 IS A1+S*(A3+S*A5)
53962306a36Sopenharmony_ci	fmulx		%fp0,%fp3		| ...fp3 IS R*S*(A2+S*A4)
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	fmulx		%fp1,%fp2		| ...fp2 IS S*(A1+S*(A3+S*A5))
54262306a36Sopenharmony_ci	faddx		%fp3,%fp0		| ...fp0 IS R+R*S*(A2+S*A4),
54362306a36Sopenharmony_ci|					...fp3 released
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci	fmovex		(%a1)+,%fp1	| ...fp1 is lead. pt. of 2^(J/64)
54662306a36Sopenharmony_ci	faddx		%fp2,%fp0		| ...fp0 is EXP(R) - 1
54762306a36Sopenharmony_ci|					...fp2 released
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci|--Step 5
55062306a36Sopenharmony_ci|--final reconstruction process
55162306a36Sopenharmony_ci|--EXP(X) = 2^M * ( 2^(J/64) + 2^(J/64)*(EXP(R)-1) )
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci	fmulx		%fp1,%fp0		| ...2^(J/64)*(Exp(R)-1)
55462306a36Sopenharmony_ci	fmovemx	(%a7)+,%fp2-%fp2/%fp3	| ...fp2 restored
55562306a36Sopenharmony_ci	fadds		(%a1),%fp0	| ...accurate 2^(J/64)
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	faddx		%fp1,%fp0		| ...2^(J/64) + 2^(J/64)*...
55862306a36Sopenharmony_ci	movel		ADJFLAG(%a6),%d0
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci|--Step 6
56162306a36Sopenharmony_ci	tstl		%d0
56262306a36Sopenharmony_ci	beqs		NORMAL
56362306a36Sopenharmony_ciADJUST:
56462306a36Sopenharmony_ci	fmulx		ADJSCALE(%a6),%fp0
56562306a36Sopenharmony_ciNORMAL:
56662306a36Sopenharmony_ci	fmovel		%d1,%FPCR		| ...restore user FPCR
56762306a36Sopenharmony_ci	fmulx		SCALE(%a6),%fp0	| ...multiply 2^(M)
56862306a36Sopenharmony_ci	bra		t_frcinx
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ciEXPSM:
57162306a36Sopenharmony_ci|--Step 7
57262306a36Sopenharmony_ci	fmovemx	(%a0),%fp0-%fp0	| ...in case X is denormalized
57362306a36Sopenharmony_ci	fmovel		%d1,%FPCR
57462306a36Sopenharmony_ci	fadds		#0x3F800000,%fp0	| ...1+X in user mode
57562306a36Sopenharmony_ci	bra		t_frcinx
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ciEXPBIG:
57862306a36Sopenharmony_ci|--Step 8
57962306a36Sopenharmony_ci	cmpil		#0x400CB27C,%d0	| ...16480 log2
58062306a36Sopenharmony_ci	bgts		EXP2BIG
58162306a36Sopenharmony_ci|--Steps 8.2 -- 8.6
58262306a36Sopenharmony_ci	fmovex		(%a0),%fp0	| ...load input from (a0)
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci	fmovex		%fp0,%fp1
58562306a36Sopenharmony_ci	fmuls		#0x42B8AA3B,%fp0	| ...64/log2 * X
58662306a36Sopenharmony_ci	fmovemx	 %fp2-%fp2/%fp3,-(%a7)		| ...save fp2
58762306a36Sopenharmony_ci	movel		#1,ADJFLAG(%a6)
58862306a36Sopenharmony_ci	fmovel		%fp0,%d0		| ...N = int( X * 64/log2 )
58962306a36Sopenharmony_ci	lea		EXPTBL,%a1
59062306a36Sopenharmony_ci	fmovel		%d0,%fp0		| ...convert to floating-format
59162306a36Sopenharmony_ci	movel		%d0,L_SCR1(%a6)			| ...save N temporarily
59262306a36Sopenharmony_ci	andil		#0x3F,%d0		 | ...D0 is J = N mod 64
59362306a36Sopenharmony_ci	lsll		#4,%d0
59462306a36Sopenharmony_ci	addal		%d0,%a1			| ...address of 2^(J/64)
59562306a36Sopenharmony_ci	movel		L_SCR1(%a6),%d0
59662306a36Sopenharmony_ci	asrl		#6,%d0			| ...D0 is K
59762306a36Sopenharmony_ci	movel		%d0,L_SCR1(%a6)			| ...save K temporarily
59862306a36Sopenharmony_ci	asrl		#1,%d0			| ...D0 is M1
59962306a36Sopenharmony_ci	subl		%d0,L_SCR1(%a6)			| ...a1 is M
60062306a36Sopenharmony_ci	addiw		#0x3FFF,%d0		| ...biased expo. of 2^(M1)
60162306a36Sopenharmony_ci	movew		%d0,ADJSCALE(%a6)		| ...ADJSCALE := 2^(M1)
60262306a36Sopenharmony_ci	clrw		ADJSCALE+2(%a6)
60362306a36Sopenharmony_ci	movel		#0x80000000,ADJSCALE+4(%a6)
60462306a36Sopenharmony_ci	clrl		ADJSCALE+8(%a6)
60562306a36Sopenharmony_ci	movel		L_SCR1(%a6),%d0			| ...D0 is M
60662306a36Sopenharmony_ci	addiw		#0x3FFF,%d0		| ...biased expo. of 2^(M)
60762306a36Sopenharmony_ci	bra		EXPCONT1		| ...go back to Step 3
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ciEXP2BIG:
61062306a36Sopenharmony_ci|--Step 9
61162306a36Sopenharmony_ci	fmovel		%d1,%FPCR
61262306a36Sopenharmony_ci	movel		(%a0),%d0
61362306a36Sopenharmony_ci	bclrb		#sign_bit,(%a0)		| ...setox always returns positive
61462306a36Sopenharmony_ci	cmpil		#0,%d0
61562306a36Sopenharmony_ci	blt		t_unfl
61662306a36Sopenharmony_ci	bra		t_ovfl
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci	.global	setoxm1d
61962306a36Sopenharmony_cisetoxm1d:
62062306a36Sopenharmony_ci|--entry point for EXPM1(X), here X is denormalized
62162306a36Sopenharmony_ci|--Step 0.
62262306a36Sopenharmony_ci	bra		t_extdnrm
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ci	.global	setoxm1
62662306a36Sopenharmony_cisetoxm1:
62762306a36Sopenharmony_ci|--entry point for EXPM1(X), here X is finite, non-zero, non-NaN
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci|--Step 1.
63062306a36Sopenharmony_ci|--Step 1.1
63162306a36Sopenharmony_ci	movel		(%a0),%d0	 | ...load part of input X
63262306a36Sopenharmony_ci	andil		#0x7FFF0000,%d0	| ...biased expo. of X
63362306a36Sopenharmony_ci	cmpil		#0x3FFD0000,%d0	| ...1/4
63462306a36Sopenharmony_ci	bges		EM1CON1	 | ...|X| >= 1/4
63562306a36Sopenharmony_ci	bra		EM1SM
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_ciEM1CON1:
63862306a36Sopenharmony_ci|--Step 1.3
63962306a36Sopenharmony_ci|--The case |X| >= 1/4
64062306a36Sopenharmony_ci	movew		4(%a0),%d0	| ...expo. and partial sig. of |X|
64162306a36Sopenharmony_ci	cmpil		#0x4004C215,%d0	| ...70log2 rounded up to 16 bits
64262306a36Sopenharmony_ci	bles		EM1MAIN	 | ...1/4 <= |X| <= 70log2
64362306a36Sopenharmony_ci	bra		EM1BIG
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ciEM1MAIN:
64662306a36Sopenharmony_ci|--Step 2.
64762306a36Sopenharmony_ci|--This is the case:	1/4 <= |X| <= 70 log2.
64862306a36Sopenharmony_ci	fmovex		(%a0),%fp0	| ...load input from (a0)
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	fmovex		%fp0,%fp1
65162306a36Sopenharmony_ci	fmuls		#0x42B8AA3B,%fp0	| ...64/log2 * X
65262306a36Sopenharmony_ci	fmovemx	%fp2-%fp2/%fp3,-(%a7)		| ...save fp2
65362306a36Sopenharmony_ci|	MOVE.W		#$3F81,EM1A4		...prefetch in CB mode
65462306a36Sopenharmony_ci	fmovel		%fp0,%d0		| ...N = int( X * 64/log2 )
65562306a36Sopenharmony_ci	lea		EXPTBL,%a1
65662306a36Sopenharmony_ci	fmovel		%d0,%fp0		| ...convert to floating-format
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci	movel		%d0,L_SCR1(%a6)			| ...save N temporarily
65962306a36Sopenharmony_ci	andil		#0x3F,%d0		 | ...D0 is J = N mod 64
66062306a36Sopenharmony_ci	lsll		#4,%d0
66162306a36Sopenharmony_ci	addal		%d0,%a1			| ...address of 2^(J/64)
66262306a36Sopenharmony_ci	movel		L_SCR1(%a6),%d0
66362306a36Sopenharmony_ci	asrl		#6,%d0			| ...D0 is M
66462306a36Sopenharmony_ci	movel		%d0,L_SCR1(%a6)			| ...save a copy of M
66562306a36Sopenharmony_ci|	MOVE.W		#$3FDC,L2		...prefetch L2 in CB mode
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci|--Step 3.
66862306a36Sopenharmony_ci|--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,
66962306a36Sopenharmony_ci|--a0 points to 2^(J/64), D0 and a1 both contain M
67062306a36Sopenharmony_ci	fmovex		%fp0,%fp2
67162306a36Sopenharmony_ci	fmuls		#0xBC317218,%fp0	| ...N * L1, L1 = lead(-log2/64)
67262306a36Sopenharmony_ci	fmulx		L2,%fp2		| ...N * L2, L1+L2 = -log2/64
67362306a36Sopenharmony_ci	faddx		%fp1,%fp0	 | ...X + N*L1
67462306a36Sopenharmony_ci	faddx		%fp2,%fp0	 | ...fp0 is R, reduced arg.
67562306a36Sopenharmony_ci|	MOVE.W		#$3FC5,EM1A2		...load EM1A2 in cache
67662306a36Sopenharmony_ci	addiw		#0x3FFF,%d0		| ...D0 is biased expo. of 2^M
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_ci|--Step 4.
67962306a36Sopenharmony_ci|--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL
68062306a36Sopenharmony_ci|-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*(A5 + R*A6)))))
68162306a36Sopenharmony_ci|--TO FULLY UTILIZE THE PIPELINE, WE COMPUTE S = R*R
68262306a36Sopenharmony_ci|--[R*S*(A2+S*(A4+S*A6))] + [R+S*(A1+S*(A3+S*A5))]
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ci	fmovex		%fp0,%fp1
68562306a36Sopenharmony_ci	fmulx		%fp1,%fp1		| ...fp1 IS S = R*R
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ci	fmoves		#0x3950097B,%fp2	| ...fp2 IS a6
68862306a36Sopenharmony_ci|	MOVE.W		#0,2(%a1)	...load 2^(J/64) in cache
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ci	fmulx		%fp1,%fp2		| ...fp2 IS S*A6
69162306a36Sopenharmony_ci	fmovex		%fp1,%fp3
69262306a36Sopenharmony_ci	fmuls		#0x3AB60B6A,%fp3	| ...fp3 IS S*A5
69362306a36Sopenharmony_ci
69462306a36Sopenharmony_ci	faddd		EM1A4,%fp2	| ...fp2 IS A4+S*A6
69562306a36Sopenharmony_ci	faddd		EM1A3,%fp3	| ...fp3 IS A3+S*A5
69662306a36Sopenharmony_ci	movew		%d0,SC(%a6)		| ...SC is 2^(M) in extended
69762306a36Sopenharmony_ci	clrw		SC+2(%a6)
69862306a36Sopenharmony_ci	movel		#0x80000000,SC+4(%a6)
69962306a36Sopenharmony_ci	clrl		SC+8(%a6)
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ci	fmulx		%fp1,%fp2		| ...fp2 IS S*(A4+S*A6)
70262306a36Sopenharmony_ci	movel		L_SCR1(%a6),%d0		| ...D0 is	M
70362306a36Sopenharmony_ci	negw		%d0		| ...D0 is -M
70462306a36Sopenharmony_ci	fmulx		%fp1,%fp3		| ...fp3 IS S*(A3+S*A5)
70562306a36Sopenharmony_ci	addiw		#0x3FFF,%d0	| ...biased expo. of 2^(-M)
70662306a36Sopenharmony_ci	faddd		EM1A2,%fp2	| ...fp2 IS A2+S*(A4+S*A6)
70762306a36Sopenharmony_ci	fadds		#0x3F000000,%fp3	| ...fp3 IS A1+S*(A3+S*A5)
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci	fmulx		%fp1,%fp2		| ...fp2 IS S*(A2+S*(A4+S*A6))
71062306a36Sopenharmony_ci	oriw		#0x8000,%d0	| ...signed/expo. of -2^(-M)
71162306a36Sopenharmony_ci	movew		%d0,ONEBYSC(%a6)	| ...OnebySc is -2^(-M)
71262306a36Sopenharmony_ci	clrw		ONEBYSC+2(%a6)
71362306a36Sopenharmony_ci	movel		#0x80000000,ONEBYSC+4(%a6)
71462306a36Sopenharmony_ci	clrl		ONEBYSC+8(%a6)
71562306a36Sopenharmony_ci	fmulx		%fp3,%fp1		| ...fp1 IS S*(A1+S*(A3+S*A5))
71662306a36Sopenharmony_ci|					...fp3 released
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	fmulx		%fp0,%fp2		| ...fp2 IS R*S*(A2+S*(A4+S*A6))
71962306a36Sopenharmony_ci	faddx		%fp1,%fp0		| ...fp0 IS R+S*(A1+S*(A3+S*A5))
72062306a36Sopenharmony_ci|					...fp1 released
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_ci	faddx		%fp2,%fp0		| ...fp0 IS EXP(R)-1
72362306a36Sopenharmony_ci|					...fp2 released
72462306a36Sopenharmony_ci	fmovemx	(%a7)+,%fp2-%fp2/%fp3	| ...fp2 restored
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci|--Step 5
72762306a36Sopenharmony_ci|--Compute 2^(J/64)*p
72862306a36Sopenharmony_ci
72962306a36Sopenharmony_ci	fmulx		(%a1),%fp0	| ...2^(J/64)*(Exp(R)-1)
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci|--Step 6
73262306a36Sopenharmony_ci|--Step 6.1
73362306a36Sopenharmony_ci	movel		L_SCR1(%a6),%d0		| ...retrieve M
73462306a36Sopenharmony_ci	cmpil		#63,%d0
73562306a36Sopenharmony_ci	bles		MLE63
73662306a36Sopenharmony_ci|--Step 6.2	M >= 64
73762306a36Sopenharmony_ci	fmoves		12(%a1),%fp1	| ...fp1 is t
73862306a36Sopenharmony_ci	faddx		ONEBYSC(%a6),%fp1	| ...fp1 is t+OnebySc
73962306a36Sopenharmony_ci	faddx		%fp1,%fp0		| ...p+(t+OnebySc), fp1 released
74062306a36Sopenharmony_ci	faddx		(%a1),%fp0	| ...T+(p+(t+OnebySc))
74162306a36Sopenharmony_ci	bras		EM1SCALE
74262306a36Sopenharmony_ciMLE63:
74362306a36Sopenharmony_ci|--Step 6.3	M <= 63
74462306a36Sopenharmony_ci	cmpil		#-3,%d0
74562306a36Sopenharmony_ci	bges		MGEN3
74662306a36Sopenharmony_ciMLTN3:
74762306a36Sopenharmony_ci|--Step 6.4	M <= -4
74862306a36Sopenharmony_ci	fadds		12(%a1),%fp0	| ...p+t
74962306a36Sopenharmony_ci	faddx		(%a1),%fp0	| ...T+(p+t)
75062306a36Sopenharmony_ci	faddx		ONEBYSC(%a6),%fp0	| ...OnebySc + (T+(p+t))
75162306a36Sopenharmony_ci	bras		EM1SCALE
75262306a36Sopenharmony_ciMGEN3:
75362306a36Sopenharmony_ci|--Step 6.5	-3 <= M <= 63
75462306a36Sopenharmony_ci	fmovex		(%a1)+,%fp1	| ...fp1 is T
75562306a36Sopenharmony_ci	fadds		(%a1),%fp0	| ...fp0 is p+t
75662306a36Sopenharmony_ci	faddx		ONEBYSC(%a6),%fp1	| ...fp1 is T+OnebySc
75762306a36Sopenharmony_ci	faddx		%fp1,%fp0		| ...(T+OnebySc)+(p+t)
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_ciEM1SCALE:
76062306a36Sopenharmony_ci|--Step 6.6
76162306a36Sopenharmony_ci	fmovel		%d1,%FPCR
76262306a36Sopenharmony_ci	fmulx		SC(%a6),%fp0
76362306a36Sopenharmony_ci
76462306a36Sopenharmony_ci	bra		t_frcinx
76562306a36Sopenharmony_ci
76662306a36Sopenharmony_ciEM1SM:
76762306a36Sopenharmony_ci|--Step 7	|X| < 1/4.
76862306a36Sopenharmony_ci	cmpil		#0x3FBE0000,%d0	| ...2^(-65)
76962306a36Sopenharmony_ci	bges		EM1POLY
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ciEM1TINY:
77262306a36Sopenharmony_ci|--Step 8	|X| < 2^(-65)
77362306a36Sopenharmony_ci	cmpil		#0x00330000,%d0	| ...2^(-16312)
77462306a36Sopenharmony_ci	blts		EM12TINY
77562306a36Sopenharmony_ci|--Step 8.2
77662306a36Sopenharmony_ci	movel		#0x80010000,SC(%a6)	| ...SC is -2^(-16382)
77762306a36Sopenharmony_ci	movel		#0x80000000,SC+4(%a6)
77862306a36Sopenharmony_ci	clrl		SC+8(%a6)
77962306a36Sopenharmony_ci	fmovex		(%a0),%fp0
78062306a36Sopenharmony_ci	fmovel		%d1,%FPCR
78162306a36Sopenharmony_ci	faddx		SC(%a6),%fp0
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_ci	bra		t_frcinx
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ciEM12TINY:
78662306a36Sopenharmony_ci|--Step 8.3
78762306a36Sopenharmony_ci	fmovex		(%a0),%fp0
78862306a36Sopenharmony_ci	fmuld		TWO140,%fp0
78962306a36Sopenharmony_ci	movel		#0x80010000,SC(%a6)
79062306a36Sopenharmony_ci	movel		#0x80000000,SC+4(%a6)
79162306a36Sopenharmony_ci	clrl		SC+8(%a6)
79262306a36Sopenharmony_ci	faddx		SC(%a6),%fp0
79362306a36Sopenharmony_ci	fmovel		%d1,%FPCR
79462306a36Sopenharmony_ci	fmuld		TWON140,%fp0
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_ci	bra		t_frcinx
79762306a36Sopenharmony_ci
79862306a36Sopenharmony_ciEM1POLY:
79962306a36Sopenharmony_ci|--Step 9	exp(X)-1 by a simple polynomial
80062306a36Sopenharmony_ci	fmovex		(%a0),%fp0	| ...fp0 is X
80162306a36Sopenharmony_ci	fmulx		%fp0,%fp0		| ...fp0 is S := X*X
80262306a36Sopenharmony_ci	fmovemx	%fp2-%fp2/%fp3,-(%a7)	| ...save fp2
80362306a36Sopenharmony_ci	fmoves		#0x2F30CAA8,%fp1	| ...fp1 is B12
80462306a36Sopenharmony_ci	fmulx		%fp0,%fp1		| ...fp1 is S*B12
80562306a36Sopenharmony_ci	fmoves		#0x310F8290,%fp2	| ...fp2 is B11
80662306a36Sopenharmony_ci	fadds		#0x32D73220,%fp1	| ...fp1 is B10+S*B12
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci	fmulx		%fp0,%fp2		| ...fp2 is S*B11
80962306a36Sopenharmony_ci	fmulx		%fp0,%fp1		| ...fp1 is S*(B10 + ...
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci	fadds		#0x3493F281,%fp2	| ...fp2 is B9+S*...
81262306a36Sopenharmony_ci	faddd		EM1B8,%fp1	| ...fp1 is B8+S*...
81362306a36Sopenharmony_ci
81462306a36Sopenharmony_ci	fmulx		%fp0,%fp2		| ...fp2 is S*(B9+...
81562306a36Sopenharmony_ci	fmulx		%fp0,%fp1		| ...fp1 is S*(B8+...
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_ci	faddd		EM1B7,%fp2	| ...fp2 is B7+S*...
81862306a36Sopenharmony_ci	faddd		EM1B6,%fp1	| ...fp1 is B6+S*...
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_ci	fmulx		%fp0,%fp2		| ...fp2 is S*(B7+...
82162306a36Sopenharmony_ci	fmulx		%fp0,%fp1		| ...fp1 is S*(B6+...
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_ci	faddd		EM1B5,%fp2	| ...fp2 is B5+S*...
82462306a36Sopenharmony_ci	faddd		EM1B4,%fp1	| ...fp1 is B4+S*...
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci	fmulx		%fp0,%fp2		| ...fp2 is S*(B5+...
82762306a36Sopenharmony_ci	fmulx		%fp0,%fp1		| ...fp1 is S*(B4+...
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_ci	faddd		EM1B3,%fp2	| ...fp2 is B3+S*...
83062306a36Sopenharmony_ci	faddx		EM1B2,%fp1	| ...fp1 is B2+S*...
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci	fmulx		%fp0,%fp2		| ...fp2 is S*(B3+...
83362306a36Sopenharmony_ci	fmulx		%fp0,%fp1		| ...fp1 is S*(B2+...
83462306a36Sopenharmony_ci
83562306a36Sopenharmony_ci	fmulx		%fp0,%fp2		| ...fp2 is S*S*(B3+...)
83662306a36Sopenharmony_ci	fmulx		(%a0),%fp1	| ...fp1 is X*S*(B2...
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ci	fmuls		#0x3F000000,%fp0	| ...fp0 is S*B1
83962306a36Sopenharmony_ci	faddx		%fp2,%fp1		| ...fp1 is Q
84062306a36Sopenharmony_ci|					...fp2 released
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_ci	fmovemx	(%a7)+,%fp2-%fp2/%fp3	| ...fp2 restored
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_ci	faddx		%fp1,%fp0		| ...fp0 is S*B1+Q
84562306a36Sopenharmony_ci|					...fp1 released
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ci	fmovel		%d1,%FPCR
84862306a36Sopenharmony_ci	faddx		(%a0),%fp0
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_ci	bra		t_frcinx
85162306a36Sopenharmony_ci
85262306a36Sopenharmony_ciEM1BIG:
85362306a36Sopenharmony_ci|--Step 10	|X| > 70 log2
85462306a36Sopenharmony_ci	movel		(%a0),%d0
85562306a36Sopenharmony_ci	cmpil		#0,%d0
85662306a36Sopenharmony_ci	bgt		EXPC1
85762306a36Sopenharmony_ci|--Step 10.2
85862306a36Sopenharmony_ci	fmoves		#0xBF800000,%fp0	| ...fp0 is -1
85962306a36Sopenharmony_ci	fmovel		%d1,%FPCR
86062306a36Sopenharmony_ci	fadds		#0x00800000,%fp0	| ...-1 + 2^(-126)
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_ci	bra		t_frcinx
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_ci	|end
865