18c2ecf20Sopenharmony_ci|
28c2ecf20Sopenharmony_ci|	bugfix.sa 3.2 1/31/91
38c2ecf20Sopenharmony_ci|
48c2ecf20Sopenharmony_ci|
58c2ecf20Sopenharmony_ci|	This file contains workarounds for bugs in the 040
68c2ecf20Sopenharmony_ci|	relating to the Floating-Point Software Package (FPSP)
78c2ecf20Sopenharmony_ci|
88c2ecf20Sopenharmony_ci|	Fixes for bugs: 1238
98c2ecf20Sopenharmony_ci|
108c2ecf20Sopenharmony_ci|	Bug: 1238
118c2ecf20Sopenharmony_ci|
128c2ecf20Sopenharmony_ci|
138c2ecf20Sopenharmony_ci|    /* The following dirty_bit clear should be left in
148c2ecf20Sopenharmony_ci|     * the handler permanently to improve throughput.
158c2ecf20Sopenharmony_ci|     * The dirty_bits are located at bits [23:16] in
168c2ecf20Sopenharmony_ci|     * longword $08 in the busy frame $4x60.  Bit 16
178c2ecf20Sopenharmony_ci|     * corresponds to FP0, bit 17 corresponds to FP1,
188c2ecf20Sopenharmony_ci|     * and so on.
198c2ecf20Sopenharmony_ci|     */
208c2ecf20Sopenharmony_ci|    if  (E3_exception_just_serviced)   {
218c2ecf20Sopenharmony_ci|         dirty_bit[cmdreg3b[9:7]] = 0;
228c2ecf20Sopenharmony_ci|         }
238c2ecf20Sopenharmony_ci|
248c2ecf20Sopenharmony_ci|    if  (fsave_format_version != $40)  {goto NOFIX}
258c2ecf20Sopenharmony_ci|
268c2ecf20Sopenharmony_ci|    if !(E3_exception_just_serviced)   {goto NOFIX}
278c2ecf20Sopenharmony_ci|    if  (cupc == 0000000)              {goto NOFIX}
288c2ecf20Sopenharmony_ci|    if  ((cmdreg1b[15:13] != 000) &&
298c2ecf20Sopenharmony_ci|         (cmdreg1b[15:10] != 010001))  {goto NOFIX}
308c2ecf20Sopenharmony_ci|    if (((cmdreg1b[15:13] != 000) || ((cmdreg1b[12:10] != cmdreg2b[9:7]) &&
318c2ecf20Sopenharmony_ci|				      (cmdreg1b[12:10] != cmdreg3b[9:7]))  ) &&
328c2ecf20Sopenharmony_ci|	 ((cmdreg1b[ 9: 7] != cmdreg2b[9:7]) &&
338c2ecf20Sopenharmony_ci|	  (cmdreg1b[ 9: 7] != cmdreg3b[9:7])) )  {goto NOFIX}
348c2ecf20Sopenharmony_ci|
358c2ecf20Sopenharmony_ci|    /* Note: for 6d43b or 8d43b, you may want to add the following code
368c2ecf20Sopenharmony_ci|     * to get better coverage.  (If you do not insert this code, the part
378c2ecf20Sopenharmony_ci|     * won't lock up; it will simply get the wrong answer.)
388c2ecf20Sopenharmony_ci|     * Do NOT insert this code for 10d43b or later parts.
398c2ecf20Sopenharmony_ci|     *
408c2ecf20Sopenharmony_ci|     *  if (fpiarcu == integer stack return address) {
418c2ecf20Sopenharmony_ci|     *       cupc = 0000000;
428c2ecf20Sopenharmony_ci|     *       goto NOFIX;
438c2ecf20Sopenharmony_ci|     *       }
448c2ecf20Sopenharmony_ci|     */
458c2ecf20Sopenharmony_ci|
468c2ecf20Sopenharmony_ci|    if (cmdreg1b[15:13] != 000)   {goto FIX_OPCLASS2}
478c2ecf20Sopenharmony_ci|    FIX_OPCLASS0:
488c2ecf20Sopenharmony_ci|    if (((cmdreg1b[12:10] == cmdreg2b[9:7]) ||
498c2ecf20Sopenharmony_ci|	 (cmdreg1b[ 9: 7] == cmdreg2b[9:7])) &&
508c2ecf20Sopenharmony_ci|	(cmdreg1b[12:10] != cmdreg3b[9:7]) &&
518c2ecf20Sopenharmony_ci|	(cmdreg1b[ 9: 7] != cmdreg3b[9:7]))  {  /* xu conflict only */
528c2ecf20Sopenharmony_ci|	/* We execute the following code if there is an
538c2ecf20Sopenharmony_ci|	   xu conflict and NOT an nu conflict */
548c2ecf20Sopenharmony_ci|
558c2ecf20Sopenharmony_ci|	/* first save some values on the fsave frame */
568c2ecf20Sopenharmony_ci|	stag_temp     = STAG[fsave_frame];
578c2ecf20Sopenharmony_ci|	cmdreg1b_temp = CMDREG1B[fsave_frame];
588c2ecf20Sopenharmony_ci|	dtag_temp     = DTAG[fsave_frame];
598c2ecf20Sopenharmony_ci|	ete15_temp    = ETE15[fsave_frame];
608c2ecf20Sopenharmony_ci|
618c2ecf20Sopenharmony_ci|	CUPC[fsave_frame] = 0000000;
628c2ecf20Sopenharmony_ci|	FRESTORE
638c2ecf20Sopenharmony_ci|	FSAVE
648c2ecf20Sopenharmony_ci|
658c2ecf20Sopenharmony_ci|	/* If the xu instruction is exceptional, we punt.
668c2ecf20Sopenharmony_ci|	 * Otherwise, we would have to include OVFL/UNFL handler
678c2ecf20Sopenharmony_ci|	 * code here to get the correct answer.
688c2ecf20Sopenharmony_ci|	 */
698c2ecf20Sopenharmony_ci|	if (fsave_frame_format == $4060) {goto KILL_PROCESS}
708c2ecf20Sopenharmony_ci|
718c2ecf20Sopenharmony_ci|	fsave_frame = /* build a long frame of all zeros */
728c2ecf20Sopenharmony_ci|	fsave_frame_format = $4060;  /* label it as long frame */
738c2ecf20Sopenharmony_ci|
748c2ecf20Sopenharmony_ci|	/* load it with the temps we saved */
758c2ecf20Sopenharmony_ci|	STAG[fsave_frame]     =  stag_temp;
768c2ecf20Sopenharmony_ci|	CMDREG1B[fsave_frame] =  cmdreg1b_temp;
778c2ecf20Sopenharmony_ci|	DTAG[fsave_frame]     =  dtag_temp;
788c2ecf20Sopenharmony_ci|	ETE15[fsave_frame]    =  ete15_temp;
798c2ecf20Sopenharmony_ci|
808c2ecf20Sopenharmony_ci|	/* Make sure that the cmdreg3b dest reg is not going to
818c2ecf20Sopenharmony_ci|	 * be destroyed by a FMOVEM at the end of all this code.
828c2ecf20Sopenharmony_ci|	 * If it is, you should move the current value of the reg
838c2ecf20Sopenharmony_ci|	 * onto the stack so that the reg will loaded with that value.
848c2ecf20Sopenharmony_ci|	 */
858c2ecf20Sopenharmony_ci|
868c2ecf20Sopenharmony_ci|	/* All done.  Proceed with the code below */
878c2ecf20Sopenharmony_ci|    }
888c2ecf20Sopenharmony_ci|
898c2ecf20Sopenharmony_ci|    etemp  = FP_reg_[cmdreg1b[12:10]];
908c2ecf20Sopenharmony_ci|    ete15  = ~ete14;
918c2ecf20Sopenharmony_ci|    cmdreg1b[15:10] = 010010;
928c2ecf20Sopenharmony_ci|    clear(bug_flag_procIDxxxx);
938c2ecf20Sopenharmony_ci|    FRESTORE and return;
948c2ecf20Sopenharmony_ci|
958c2ecf20Sopenharmony_ci|
968c2ecf20Sopenharmony_ci|    FIX_OPCLASS2:
978c2ecf20Sopenharmony_ci|    if ((cmdreg1b[9:7] == cmdreg2b[9:7]) &&
988c2ecf20Sopenharmony_ci|	(cmdreg1b[9:7] != cmdreg3b[9:7]))  {  /* xu conflict only */
998c2ecf20Sopenharmony_ci|	/* We execute the following code if there is an
1008c2ecf20Sopenharmony_ci|	   xu conflict and NOT an nu conflict */
1018c2ecf20Sopenharmony_ci|
1028c2ecf20Sopenharmony_ci|	/* first save some values on the fsave frame */
1038c2ecf20Sopenharmony_ci|	stag_temp     = STAG[fsave_frame];
1048c2ecf20Sopenharmony_ci|	cmdreg1b_temp = CMDREG1B[fsave_frame];
1058c2ecf20Sopenharmony_ci|	dtag_temp     = DTAG[fsave_frame];
1068c2ecf20Sopenharmony_ci|	ete15_temp    = ETE15[fsave_frame];
1078c2ecf20Sopenharmony_ci|	etemp_temp    = ETEMP[fsave_frame];
1088c2ecf20Sopenharmony_ci|
1098c2ecf20Sopenharmony_ci|	CUPC[fsave_frame] = 0000000;
1108c2ecf20Sopenharmony_ci|	FRESTORE
1118c2ecf20Sopenharmony_ci|	FSAVE
1128c2ecf20Sopenharmony_ci|
1138c2ecf20Sopenharmony_ci|
1148c2ecf20Sopenharmony_ci|	/* If the xu instruction is exceptional, we punt.
1158c2ecf20Sopenharmony_ci|	 * Otherwise, we would have to include OVFL/UNFL handler
1168c2ecf20Sopenharmony_ci|	 * code here to get the correct answer.
1178c2ecf20Sopenharmony_ci|	 */
1188c2ecf20Sopenharmony_ci|	if (fsave_frame_format == $4060) {goto KILL_PROCESS}
1198c2ecf20Sopenharmony_ci|
1208c2ecf20Sopenharmony_ci|	fsave_frame = /* build a long frame of all zeros */
1218c2ecf20Sopenharmony_ci|	fsave_frame_format = $4060;  /* label it as long frame */
1228c2ecf20Sopenharmony_ci|
1238c2ecf20Sopenharmony_ci|	/* load it with the temps we saved */
1248c2ecf20Sopenharmony_ci|	STAG[fsave_frame]     =  stag_temp;
1258c2ecf20Sopenharmony_ci|	CMDREG1B[fsave_frame] =  cmdreg1b_temp;
1268c2ecf20Sopenharmony_ci|	DTAG[fsave_frame]     =  dtag_temp;
1278c2ecf20Sopenharmony_ci|	ETE15[fsave_frame]    =  ete15_temp;
1288c2ecf20Sopenharmony_ci|	ETEMP[fsave_frame]    =  etemp_temp;
1298c2ecf20Sopenharmony_ci|
1308c2ecf20Sopenharmony_ci|	/* Make sure that the cmdreg3b dest reg is not going to
1318c2ecf20Sopenharmony_ci|	 * be destroyed by a FMOVEM at the end of all this code.
1328c2ecf20Sopenharmony_ci|	 * If it is, you should move the current value of the reg
1338c2ecf20Sopenharmony_ci|	 * onto the stack so that the reg will loaded with that value.
1348c2ecf20Sopenharmony_ci|	 */
1358c2ecf20Sopenharmony_ci|
1368c2ecf20Sopenharmony_ci|	/* All done.  Proceed with the code below */
1378c2ecf20Sopenharmony_ci|    }
1388c2ecf20Sopenharmony_ci|
1398c2ecf20Sopenharmony_ci|    if (etemp_exponent == min_sgl)   etemp_exponent = min_dbl;
1408c2ecf20Sopenharmony_ci|    if (etemp_exponent == max_sgl)   etemp_exponent = max_dbl;
1418c2ecf20Sopenharmony_ci|    cmdreg1b[15:10] = 010101;
1428c2ecf20Sopenharmony_ci|    clear(bug_flag_procIDxxxx);
1438c2ecf20Sopenharmony_ci|    FRESTORE and return;
1448c2ecf20Sopenharmony_ci|
1458c2ecf20Sopenharmony_ci|
1468c2ecf20Sopenharmony_ci|    NOFIX:
1478c2ecf20Sopenharmony_ci|    clear(bug_flag_procIDxxxx);
1488c2ecf20Sopenharmony_ci|    FRESTORE and return;
1498c2ecf20Sopenharmony_ci|
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci|		Copyright (C) Motorola, Inc. 1990
1538c2ecf20Sopenharmony_ci|			All Rights Reserved
1548c2ecf20Sopenharmony_ci|
1558c2ecf20Sopenharmony_ci|       For details on the license for this file, please see the
1568c2ecf20Sopenharmony_ci|       file, README, in this same directory.
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci|BUGFIX    idnt    2,1 | Motorola 040 Floating Point Software Package
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	|section	8
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci#include "fpsp.h"
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci	|xref	fpsp_fmt_error
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	.global	b1238_fix
1678c2ecf20Sopenharmony_cib1238_fix:
1688c2ecf20Sopenharmony_ci|
1698c2ecf20Sopenharmony_ci| This code is entered only on completion of the handling of an
1708c2ecf20Sopenharmony_ci| nu-generated ovfl, unfl, or inex exception.  If the version
1718c2ecf20Sopenharmony_ci| number of the fsave is not $40, this handler is not necessary.
1728c2ecf20Sopenharmony_ci| Simply branch to fix_done and exit normally.
1738c2ecf20Sopenharmony_ci|
1748c2ecf20Sopenharmony_ci	cmpib	#VER_40,4(%a7)
1758c2ecf20Sopenharmony_ci	bne	fix_done
1768c2ecf20Sopenharmony_ci|
1778c2ecf20Sopenharmony_ci| Test for cu_savepc equal to zero.  If not, this is not a bug
1788c2ecf20Sopenharmony_ci| #1238 case.
1798c2ecf20Sopenharmony_ci|
1808c2ecf20Sopenharmony_ci	moveb	CU_SAVEPC(%a6),%d0
1818c2ecf20Sopenharmony_ci	andib	#0xFE,%d0
1828c2ecf20Sopenharmony_ci	beq	fix_done	|if zero, this is not bug #1238
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci|
1858c2ecf20Sopenharmony_ci| Test the register conflict aspect.  If opclass0, check for
1868c2ecf20Sopenharmony_ci| cu src equal to xu dest or equal to nu dest.  If so, go to
1878c2ecf20Sopenharmony_ci| op0.  Else, or if opclass2, check for cu dest equal to
1888c2ecf20Sopenharmony_ci| xu dest or equal to nu dest.  If so, go to tst_opcl.  Else,
1898c2ecf20Sopenharmony_ci| exit, it is not the bug case.
1908c2ecf20Sopenharmony_ci|
1918c2ecf20Sopenharmony_ci| Check for opclass 0.  If not, go and check for opclass 2 and sgl.
1928c2ecf20Sopenharmony_ci|
1938c2ecf20Sopenharmony_ci	movew	CMDREG1B(%a6),%d0
1948c2ecf20Sopenharmony_ci	andiw	#0xE000,%d0		|strip all but opclass
1958c2ecf20Sopenharmony_ci	bne	op2sgl			|not opclass 0, check op2
1968c2ecf20Sopenharmony_ci|
1978c2ecf20Sopenharmony_ci| Check for cu and nu register conflict.  If one exists, this takes
1988c2ecf20Sopenharmony_ci| priority over a cu and xu conflict.
1998c2ecf20Sopenharmony_ci|
2008c2ecf20Sopenharmony_ci	bfextu	CMDREG1B(%a6){#3:#3},%d0	|get 1st src
2018c2ecf20Sopenharmony_ci	bfextu	CMDREG3B(%a6){#6:#3},%d1	|get 3rd dest
2028c2ecf20Sopenharmony_ci	cmpb	%d0,%d1
2038c2ecf20Sopenharmony_ci	beqs	op0			|if equal, continue bugfix
2048c2ecf20Sopenharmony_ci|
2058c2ecf20Sopenharmony_ci| Check for cu dest equal to nu dest.  If so, go and fix the
2068c2ecf20Sopenharmony_ci| bug condition.  Otherwise, exit.
2078c2ecf20Sopenharmony_ci|
2088c2ecf20Sopenharmony_ci	bfextu	CMDREG1B(%a6){#6:#3},%d0	|get 1st dest
2098c2ecf20Sopenharmony_ci	cmpb	%d0,%d1			|cmp 1st dest with 3rd dest
2108c2ecf20Sopenharmony_ci	beqs	op0			|if equal, continue bugfix
2118c2ecf20Sopenharmony_ci|
2128c2ecf20Sopenharmony_ci| Check for cu and xu register conflict.
2138c2ecf20Sopenharmony_ci|
2148c2ecf20Sopenharmony_ci	bfextu	CMDREG2B(%a6){#6:#3},%d1	|get 2nd dest
2158c2ecf20Sopenharmony_ci	cmpb	%d0,%d1			|cmp 1st dest with 2nd dest
2168c2ecf20Sopenharmony_ci	beqs	op0_xu			|if equal, continue bugfix
2178c2ecf20Sopenharmony_ci	bfextu	CMDREG1B(%a6){#3:#3},%d0	|get 1st src
2188c2ecf20Sopenharmony_ci	cmpb	%d0,%d1			|cmp 1st src with 2nd dest
2198c2ecf20Sopenharmony_ci	beq	op0_xu
2208c2ecf20Sopenharmony_ci	bne	fix_done		|if the reg checks fail, exit
2218c2ecf20Sopenharmony_ci|
2228c2ecf20Sopenharmony_ci| We have the opclass 0 situation.
2238c2ecf20Sopenharmony_ci|
2248c2ecf20Sopenharmony_ciop0:
2258c2ecf20Sopenharmony_ci	bfextu	CMDREG1B(%a6){#3:#3},%d0	|get source register no
2268c2ecf20Sopenharmony_ci	movel	#7,%d1
2278c2ecf20Sopenharmony_ci	subl	%d0,%d1
2288c2ecf20Sopenharmony_ci	clrl	%d0
2298c2ecf20Sopenharmony_ci	bsetl	%d1,%d0
2308c2ecf20Sopenharmony_ci	fmovemx %d0,ETEMP(%a6)		|load source to ETEMP
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	moveb	#0x12,%d0
2338c2ecf20Sopenharmony_ci	bfins	%d0,CMDREG1B(%a6){#0:#6}	|opclass 2, extended
2348c2ecf20Sopenharmony_ci|
2358c2ecf20Sopenharmony_ci|	Set ETEMP exponent bit 15 as the opposite of ete14
2368c2ecf20Sopenharmony_ci|
2378c2ecf20Sopenharmony_ci	btst	#6,ETEMP_EX(%a6)		|check etemp exponent bit 14
2388c2ecf20Sopenharmony_ci	beq	setete15
2398c2ecf20Sopenharmony_ci	bclr	#etemp15_bit,STAG(%a6)
2408c2ecf20Sopenharmony_ci	bra	finish
2418c2ecf20Sopenharmony_cisetete15:
2428c2ecf20Sopenharmony_ci	bset	#etemp15_bit,STAG(%a6)
2438c2ecf20Sopenharmony_ci	bra	finish
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci|
2468c2ecf20Sopenharmony_ci| We have the case in which a conflict exists between the cu src or
2478c2ecf20Sopenharmony_ci| dest and the dest of the xu.  We must clear the instruction in
2488c2ecf20Sopenharmony_ci| the cu and restore the state, allowing the instruction in the
2498c2ecf20Sopenharmony_ci| xu to complete.  Remember, the instruction in the nu
2508c2ecf20Sopenharmony_ci| was exceptional, and was completed by the appropriate handler.
2518c2ecf20Sopenharmony_ci| If the result of the xu instruction is not exceptional, we can
2528c2ecf20Sopenharmony_ci| restore the instruction from the cu to the frame and continue
2538c2ecf20Sopenharmony_ci| processing the original exception.  If the result is also
2548c2ecf20Sopenharmony_ci| exceptional, we choose to kill the process.
2558c2ecf20Sopenharmony_ci|
2568c2ecf20Sopenharmony_ci|	Items saved from the stack:
2578c2ecf20Sopenharmony_ci|
2588c2ecf20Sopenharmony_ci|		$3c stag     - L_SCR1
2598c2ecf20Sopenharmony_ci|		$40 cmdreg1b - L_SCR2
2608c2ecf20Sopenharmony_ci|		$44 dtag     - L_SCR3
2618c2ecf20Sopenharmony_ci|
2628c2ecf20Sopenharmony_ci| The cu savepc is set to zero, and the frame is restored to the
2638c2ecf20Sopenharmony_ci| fpu.
2648c2ecf20Sopenharmony_ci|
2658c2ecf20Sopenharmony_ciop0_xu:
2668c2ecf20Sopenharmony_ci	movel	STAG(%a6),L_SCR1(%a6)
2678c2ecf20Sopenharmony_ci	movel	CMDREG1B(%a6),L_SCR2(%a6)
2688c2ecf20Sopenharmony_ci	movel	DTAG(%a6),L_SCR3(%a6)
2698c2ecf20Sopenharmony_ci	andil	#0xe0000000,L_SCR3(%a6)
2708c2ecf20Sopenharmony_ci	moveb	#0,CU_SAVEPC(%a6)
2718c2ecf20Sopenharmony_ci	movel	(%a7)+,%d1		|save return address from bsr
2728c2ecf20Sopenharmony_ci	frestore (%a7)+
2738c2ecf20Sopenharmony_ci	fsave	-(%a7)
2748c2ecf20Sopenharmony_ci|
2758c2ecf20Sopenharmony_ci| Check if the instruction which just completed was exceptional.
2768c2ecf20Sopenharmony_ci|
2778c2ecf20Sopenharmony_ci	cmpw	#0x4060,(%a7)
2788c2ecf20Sopenharmony_ci	beq	op0_xb
2798c2ecf20Sopenharmony_ci|
2808c2ecf20Sopenharmony_ci| It is necessary to isolate the result of the instruction in the
2818c2ecf20Sopenharmony_ci| xu if it is to fp0 - fp3 and write that value to the USER_FPn
2828c2ecf20Sopenharmony_ci| locations on the stack.  The correct destination register is in
2838c2ecf20Sopenharmony_ci| cmdreg2b.
2848c2ecf20Sopenharmony_ci|
2858c2ecf20Sopenharmony_ci	bfextu	CMDREG2B(%a6){#6:#3},%d0	|get dest register no
2868c2ecf20Sopenharmony_ci	cmpil	#3,%d0
2878c2ecf20Sopenharmony_ci	bgts	op0_xi
2888c2ecf20Sopenharmony_ci	beqs	op0_fp3
2898c2ecf20Sopenharmony_ci	cmpil	#1,%d0
2908c2ecf20Sopenharmony_ci	blts	op0_fp0
2918c2ecf20Sopenharmony_ci	beqs	op0_fp1
2928c2ecf20Sopenharmony_ciop0_fp2:
2938c2ecf20Sopenharmony_ci	fmovemx %fp2-%fp2,USER_FP2(%a6)
2948c2ecf20Sopenharmony_ci	bras	op0_xi
2958c2ecf20Sopenharmony_ciop0_fp1:
2968c2ecf20Sopenharmony_ci	fmovemx %fp1-%fp1,USER_FP1(%a6)
2978c2ecf20Sopenharmony_ci	bras	op0_xi
2988c2ecf20Sopenharmony_ciop0_fp0:
2998c2ecf20Sopenharmony_ci	fmovemx %fp0-%fp0,USER_FP0(%a6)
3008c2ecf20Sopenharmony_ci	bras	op0_xi
3018c2ecf20Sopenharmony_ciop0_fp3:
3028c2ecf20Sopenharmony_ci	fmovemx %fp3-%fp3,USER_FP3(%a6)
3038c2ecf20Sopenharmony_ci|
3048c2ecf20Sopenharmony_ci| The frame returned is idle.  We must build a busy frame to hold
3058c2ecf20Sopenharmony_ci| the cu state information and setup etemp.
3068c2ecf20Sopenharmony_ci|
3078c2ecf20Sopenharmony_ciop0_xi:
3088c2ecf20Sopenharmony_ci	movel	#22,%d0		|clear 23 lwords
3098c2ecf20Sopenharmony_ci	clrl	(%a7)
3108c2ecf20Sopenharmony_ciop0_loop:
3118c2ecf20Sopenharmony_ci	clrl	-(%a7)
3128c2ecf20Sopenharmony_ci	dbf	%d0,op0_loop
3138c2ecf20Sopenharmony_ci	movel	#0x40600000,-(%a7)
3148c2ecf20Sopenharmony_ci	movel	L_SCR1(%a6),STAG(%a6)
3158c2ecf20Sopenharmony_ci	movel	L_SCR2(%a6),CMDREG1B(%a6)
3168c2ecf20Sopenharmony_ci	movel	L_SCR3(%a6),DTAG(%a6)
3178c2ecf20Sopenharmony_ci	moveb	#0x6,CU_SAVEPC(%a6)
3188c2ecf20Sopenharmony_ci	movel	%d1,-(%a7)		|return bsr return address
3198c2ecf20Sopenharmony_ci	bfextu	CMDREG1B(%a6){#3:#3},%d0	|get source register no
3208c2ecf20Sopenharmony_ci	movel	#7,%d1
3218c2ecf20Sopenharmony_ci	subl	%d0,%d1
3228c2ecf20Sopenharmony_ci	clrl	%d0
3238c2ecf20Sopenharmony_ci	bsetl	%d1,%d0
3248c2ecf20Sopenharmony_ci	fmovemx %d0,ETEMP(%a6)		|load source to ETEMP
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	moveb	#0x12,%d0
3278c2ecf20Sopenharmony_ci	bfins	%d0,CMDREG1B(%a6){#0:#6}	|opclass 2, extended
3288c2ecf20Sopenharmony_ci|
3298c2ecf20Sopenharmony_ci|	Set ETEMP exponent bit 15 as the opposite of ete14
3308c2ecf20Sopenharmony_ci|
3318c2ecf20Sopenharmony_ci	btst	#6,ETEMP_EX(%a6)		|check etemp exponent bit 14
3328c2ecf20Sopenharmony_ci	beq	op0_sete15
3338c2ecf20Sopenharmony_ci	bclr	#etemp15_bit,STAG(%a6)
3348c2ecf20Sopenharmony_ci	bra	finish
3358c2ecf20Sopenharmony_ciop0_sete15:
3368c2ecf20Sopenharmony_ci	bset	#etemp15_bit,STAG(%a6)
3378c2ecf20Sopenharmony_ci	bra	finish
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci|
3408c2ecf20Sopenharmony_ci| The frame returned is busy.  It is not possible to reconstruct
3418c2ecf20Sopenharmony_ci| the code sequence to allow completion.  We will jump to
3428c2ecf20Sopenharmony_ci| fpsp_fmt_error and allow the kernel to kill the process.
3438c2ecf20Sopenharmony_ci|
3448c2ecf20Sopenharmony_ciop0_xb:
3458c2ecf20Sopenharmony_ci	jmp	fpsp_fmt_error
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci|
3488c2ecf20Sopenharmony_ci| Check for opclass 2 and single size.  If not both, exit.
3498c2ecf20Sopenharmony_ci|
3508c2ecf20Sopenharmony_ciop2sgl:
3518c2ecf20Sopenharmony_ci	movew	CMDREG1B(%a6),%d0
3528c2ecf20Sopenharmony_ci	andiw	#0xFC00,%d0		|strip all but opclass and size
3538c2ecf20Sopenharmony_ci	cmpiw	#0x4400,%d0		|test for opclass 2 and size=sgl
3548c2ecf20Sopenharmony_ci	bne	fix_done		|if not, it is not bug 1238
3558c2ecf20Sopenharmony_ci|
3568c2ecf20Sopenharmony_ci| Check for cu dest equal to nu dest or equal to xu dest, with
3578c2ecf20Sopenharmony_ci| a cu and nu conflict taking priority an nu conflict.  If either,
3588c2ecf20Sopenharmony_ci| go and fix the bug condition.  Otherwise, exit.
3598c2ecf20Sopenharmony_ci|
3608c2ecf20Sopenharmony_ci	bfextu	CMDREG1B(%a6){#6:#3},%d0	|get 1st dest
3618c2ecf20Sopenharmony_ci	bfextu	CMDREG3B(%a6){#6:#3},%d1	|get 3rd dest
3628c2ecf20Sopenharmony_ci	cmpb	%d0,%d1			|cmp 1st dest with 3rd dest
3638c2ecf20Sopenharmony_ci	beq	op2_com			|if equal, continue bugfix
3648c2ecf20Sopenharmony_ci	bfextu	CMDREG2B(%a6){#6:#3},%d1	|get 2nd dest
3658c2ecf20Sopenharmony_ci	cmpb	%d0,%d1			|cmp 1st dest with 2nd dest
3668c2ecf20Sopenharmony_ci	bne	fix_done		|if the reg checks fail, exit
3678c2ecf20Sopenharmony_ci|
3688c2ecf20Sopenharmony_ci| We have the case in which a conflict exists between the cu src or
3698c2ecf20Sopenharmony_ci| dest and the dest of the xu.  We must clear the instruction in
3708c2ecf20Sopenharmony_ci| the cu and restore the state, allowing the instruction in the
3718c2ecf20Sopenharmony_ci| xu to complete.  Remember, the instruction in the nu
3728c2ecf20Sopenharmony_ci| was exceptional, and was completed by the appropriate handler.
3738c2ecf20Sopenharmony_ci| If the result of the xu instruction is not exceptional, we can
3748c2ecf20Sopenharmony_ci| restore the instruction from the cu to the frame and continue
3758c2ecf20Sopenharmony_ci| processing the original exception.  If the result is also
3768c2ecf20Sopenharmony_ci| exceptional, we choose to kill the process.
3778c2ecf20Sopenharmony_ci|
3788c2ecf20Sopenharmony_ci|	Items saved from the stack:
3798c2ecf20Sopenharmony_ci|
3808c2ecf20Sopenharmony_ci|		$3c stag     - L_SCR1
3818c2ecf20Sopenharmony_ci|		$40 cmdreg1b - L_SCR2
3828c2ecf20Sopenharmony_ci|		$44 dtag     - L_SCR3
3838c2ecf20Sopenharmony_ci|		etemp        - FP_SCR2
3848c2ecf20Sopenharmony_ci|
3858c2ecf20Sopenharmony_ci| The cu savepc is set to zero, and the frame is restored to the
3868c2ecf20Sopenharmony_ci| fpu.
3878c2ecf20Sopenharmony_ci|
3888c2ecf20Sopenharmony_ciop2_xu:
3898c2ecf20Sopenharmony_ci	movel	STAG(%a6),L_SCR1(%a6)
3908c2ecf20Sopenharmony_ci	movel	CMDREG1B(%a6),L_SCR2(%a6)
3918c2ecf20Sopenharmony_ci	movel	DTAG(%a6),L_SCR3(%a6)
3928c2ecf20Sopenharmony_ci	andil	#0xe0000000,L_SCR3(%a6)
3938c2ecf20Sopenharmony_ci	moveb	#0,CU_SAVEPC(%a6)
3948c2ecf20Sopenharmony_ci	movel	ETEMP(%a6),FP_SCR2(%a6)
3958c2ecf20Sopenharmony_ci	movel	ETEMP_HI(%a6),FP_SCR2+4(%a6)
3968c2ecf20Sopenharmony_ci	movel	ETEMP_LO(%a6),FP_SCR2+8(%a6)
3978c2ecf20Sopenharmony_ci	movel	(%a7)+,%d1		|save return address from bsr
3988c2ecf20Sopenharmony_ci	frestore (%a7)+
3998c2ecf20Sopenharmony_ci	fsave	-(%a7)
4008c2ecf20Sopenharmony_ci|
4018c2ecf20Sopenharmony_ci| Check if the instruction which just completed was exceptional.
4028c2ecf20Sopenharmony_ci|
4038c2ecf20Sopenharmony_ci	cmpw	#0x4060,(%a7)
4048c2ecf20Sopenharmony_ci	beq	op2_xb
4058c2ecf20Sopenharmony_ci|
4068c2ecf20Sopenharmony_ci| It is necessary to isolate the result of the instruction in the
4078c2ecf20Sopenharmony_ci| xu if it is to fp0 - fp3 and write that value to the USER_FPn
4088c2ecf20Sopenharmony_ci| locations on the stack.  The correct destination register is in
4098c2ecf20Sopenharmony_ci| cmdreg2b.
4108c2ecf20Sopenharmony_ci|
4118c2ecf20Sopenharmony_ci	bfextu	CMDREG2B(%a6){#6:#3},%d0	|get dest register no
4128c2ecf20Sopenharmony_ci	cmpil	#3,%d0
4138c2ecf20Sopenharmony_ci	bgts	op2_xi
4148c2ecf20Sopenharmony_ci	beqs	op2_fp3
4158c2ecf20Sopenharmony_ci	cmpil	#1,%d0
4168c2ecf20Sopenharmony_ci	blts	op2_fp0
4178c2ecf20Sopenharmony_ci	beqs	op2_fp1
4188c2ecf20Sopenharmony_ciop2_fp2:
4198c2ecf20Sopenharmony_ci	fmovemx %fp2-%fp2,USER_FP2(%a6)
4208c2ecf20Sopenharmony_ci	bras	op2_xi
4218c2ecf20Sopenharmony_ciop2_fp1:
4228c2ecf20Sopenharmony_ci	fmovemx %fp1-%fp1,USER_FP1(%a6)
4238c2ecf20Sopenharmony_ci	bras	op2_xi
4248c2ecf20Sopenharmony_ciop2_fp0:
4258c2ecf20Sopenharmony_ci	fmovemx %fp0-%fp0,USER_FP0(%a6)
4268c2ecf20Sopenharmony_ci	bras	op2_xi
4278c2ecf20Sopenharmony_ciop2_fp3:
4288c2ecf20Sopenharmony_ci	fmovemx %fp3-%fp3,USER_FP3(%a6)
4298c2ecf20Sopenharmony_ci|
4308c2ecf20Sopenharmony_ci| The frame returned is idle.  We must build a busy frame to hold
4318c2ecf20Sopenharmony_ci| the cu state information and fix up etemp.
4328c2ecf20Sopenharmony_ci|
4338c2ecf20Sopenharmony_ciop2_xi:
4348c2ecf20Sopenharmony_ci	movel	#22,%d0		|clear 23 lwords
4358c2ecf20Sopenharmony_ci	clrl	(%a7)
4368c2ecf20Sopenharmony_ciop2_loop:
4378c2ecf20Sopenharmony_ci	clrl	-(%a7)
4388c2ecf20Sopenharmony_ci	dbf	%d0,op2_loop
4398c2ecf20Sopenharmony_ci	movel	#0x40600000,-(%a7)
4408c2ecf20Sopenharmony_ci	movel	L_SCR1(%a6),STAG(%a6)
4418c2ecf20Sopenharmony_ci	movel	L_SCR2(%a6),CMDREG1B(%a6)
4428c2ecf20Sopenharmony_ci	movel	L_SCR3(%a6),DTAG(%a6)
4438c2ecf20Sopenharmony_ci	moveb	#0x6,CU_SAVEPC(%a6)
4448c2ecf20Sopenharmony_ci	movel	FP_SCR2(%a6),ETEMP(%a6)
4458c2ecf20Sopenharmony_ci	movel	FP_SCR2+4(%a6),ETEMP_HI(%a6)
4468c2ecf20Sopenharmony_ci	movel	FP_SCR2+8(%a6),ETEMP_LO(%a6)
4478c2ecf20Sopenharmony_ci	movel	%d1,-(%a7)
4488c2ecf20Sopenharmony_ci	bra	op2_com
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci|
4518c2ecf20Sopenharmony_ci| We have the opclass 2 single source situation.
4528c2ecf20Sopenharmony_ci|
4538c2ecf20Sopenharmony_ciop2_com:
4548c2ecf20Sopenharmony_ci	moveb	#0x15,%d0
4558c2ecf20Sopenharmony_ci	bfins	%d0,CMDREG1B(%a6){#0:#6}	|opclass 2, double
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	cmpw	#0x407F,ETEMP_EX(%a6)	|single +max
4588c2ecf20Sopenharmony_ci	bnes	case2
4598c2ecf20Sopenharmony_ci	movew	#0x43FF,ETEMP_EX(%a6)	|to double +max
4608c2ecf20Sopenharmony_ci	bra	finish
4618c2ecf20Sopenharmony_cicase2:
4628c2ecf20Sopenharmony_ci	cmpw	#0xC07F,ETEMP_EX(%a6)	|single -max
4638c2ecf20Sopenharmony_ci	bnes	case3
4648c2ecf20Sopenharmony_ci	movew	#0xC3FF,ETEMP_EX(%a6)	|to double -max
4658c2ecf20Sopenharmony_ci	bra	finish
4668c2ecf20Sopenharmony_cicase3:
4678c2ecf20Sopenharmony_ci	cmpw	#0x3F80,ETEMP_EX(%a6)	|single +min
4688c2ecf20Sopenharmony_ci	bnes	case4
4698c2ecf20Sopenharmony_ci	movew	#0x3C00,ETEMP_EX(%a6)	|to double +min
4708c2ecf20Sopenharmony_ci	bra	finish
4718c2ecf20Sopenharmony_cicase4:
4728c2ecf20Sopenharmony_ci	cmpw	#0xBF80,ETEMP_EX(%a6)	|single -min
4738c2ecf20Sopenharmony_ci	bne	fix_done
4748c2ecf20Sopenharmony_ci	movew	#0xBC00,ETEMP_EX(%a6)	|to double -min
4758c2ecf20Sopenharmony_ci	bra	finish
4768c2ecf20Sopenharmony_ci|
4778c2ecf20Sopenharmony_ci| The frame returned is busy.  It is not possible to reconstruct
4788c2ecf20Sopenharmony_ci| the code sequence to allow completion.  fpsp_fmt_error causes
4798c2ecf20Sopenharmony_ci| an fline illegal instruction to be executed.
4808c2ecf20Sopenharmony_ci|
4818c2ecf20Sopenharmony_ci| You should replace the jump to fpsp_fmt_error with a jump
4828c2ecf20Sopenharmony_ci| to the entry point used to kill a process.
4838c2ecf20Sopenharmony_ci|
4848c2ecf20Sopenharmony_ciop2_xb:
4858c2ecf20Sopenharmony_ci	jmp	fpsp_fmt_error
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci|
4888c2ecf20Sopenharmony_ci| Enter here if the case is not of the situations affected by
4898c2ecf20Sopenharmony_ci| bug #1238, or if the fix is completed, and exit.
4908c2ecf20Sopenharmony_ci|
4918c2ecf20Sopenharmony_cifinish:
4928c2ecf20Sopenharmony_cifix_done:
4938c2ecf20Sopenharmony_ci	rts
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci	|end
496