summaryrefslogtreecommitdiff
path: root/sys/arch/m68k/fpsp/bugfix.sa
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
commitd6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch)
treeece253b876159b39c620e62b6c9b1174642e070e /sys/arch/m68k/fpsp/bugfix.sa
initial import of NetBSD tree
Diffstat (limited to 'sys/arch/m68k/fpsp/bugfix.sa')
-rw-r--r--sys/arch/m68k/fpsp/bugfix.sa520
1 files changed, 520 insertions, 0 deletions
diff --git a/sys/arch/m68k/fpsp/bugfix.sa b/sys/arch/m68k/fpsp/bugfix.sa
new file mode 100644
index 00000000000..d38f81656b0
--- /dev/null
+++ b/sys/arch/m68k/fpsp/bugfix.sa
@@ -0,0 +1,520 @@
+* $NetBSD: bugfix.sa,v 1.3 1994/10/26 07:48:55 cgd Exp $
+
+* MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
+* M68000 Hi-Performance Microprocessor Division
+* M68040 Software Package
+*
+* M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
+* All rights reserved.
+*
+* THE SOFTWARE is provided on an "AS IS" basis and without warranty.
+* To the maximum extent permitted by applicable law,
+* MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
+* INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
+* PARTICULAR PURPOSE and any warranty against infringement with
+* regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
+* and any accompanying written materials.
+*
+* To the maximum extent permitted by applicable law,
+* IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
+* (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
+* PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
+* OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
+* SOFTWARE. Motorola assumes no responsibility for the maintenance
+* and support of the SOFTWARE.
+*
+* You are hereby granted a copyright license to use, modify, and
+* distribute the SOFTWARE so long as this entire notice is retained
+* without alteration in any modified and/or redistributed versions,
+* and that such modified versions are clearly identified as such.
+* No licenses are granted by implication, estoppel or otherwise
+* under any patents or trademarks of Motorola, Inc.
+
+*
+* bugfix.sa 3.2 1/31/91
+*
+*
+* This file contains workarounds for bugs in the 040
+* relating to the Floating-Point Software Package (FPSP)
+*
+* Fixes for bugs: 1238
+*
+* Bug: 1238
+*
+*
+* /* The following dirty_bit clear should be left in
+* * the handler permanently to improve throughput.
+* * The dirty_bits are located at bits [23:16] in
+* * longword $08 in the busy frame $4x60. Bit 16
+* * corresponds to FP0, bit 17 corresponds to FP1,
+* * and so on.
+* */
+* if (E3_exception_just_serviced) {
+* dirty_bit[cmdreg3b[9:7]] = 0;
+* }
+*
+* if (fsave_format_version != $40) {goto NOFIX}
+*
+* if !(E3_exception_just_serviced) {goto NOFIX}
+* if (cupc == 0000000) {goto NOFIX}
+* if ((cmdreg1b[15:13] != 000) &&
+* (cmdreg1b[15:10] != 010001)) {goto NOFIX}
+* if (((cmdreg1b[15:13] != 000) || ((cmdreg1b[12:10] != cmdreg2b[9:7]) &&
+* (cmdreg1b[12:10] != cmdreg3b[9:7])) ) &&
+* ((cmdreg1b[ 9: 7] != cmdreg2b[9:7]) &&
+* (cmdreg1b[ 9: 7] != cmdreg3b[9:7])) ) {goto NOFIX}
+*
+* /* Note: for 6d43b or 8d43b, you may want to add the following code
+* * to get better coverage. (If you do not insert this code, the part
+* * won't lock up; it will simply get the wrong answer.)
+* * Do NOT insert this code for 10d43b or later parts.
+* *
+* * if (fpiarcu == integer stack return address) {
+* * cupc = 0000000;
+* * goto NOFIX;
+* * }
+* */
+*
+* if (cmdreg1b[15:13] != 000) {goto FIX_OPCLASS2}
+* FIX_OPCLASS0:
+* if (((cmdreg1b[12:10] == cmdreg2b[9:7]) ||
+* (cmdreg1b[ 9: 7] == cmdreg2b[9:7])) &&
+* (cmdreg1b[12:10] != cmdreg3b[9:7]) &&
+* (cmdreg1b[ 9: 7] != cmdreg3b[9:7])) { /* xu conflict only */
+* /* We execute the following code if there is an
+* xu conflict and NOT an nu conflict */
+*
+* /* first save some values on the fsave frame */
+* stag_temp = STAG[fsave_frame];
+* cmdreg1b_temp = CMDREG1B[fsave_frame];
+* dtag_temp = DTAG[fsave_frame];
+* ete15_temp = ETE15[fsave_frame];
+*
+* CUPC[fsave_frame] = 0000000;
+* FRESTORE
+* FSAVE
+*
+* /* If the xu instruction is exceptional, we punt.
+* * Otherwise, we would have to include OVFL/UNFL handler
+* * code here to get the correct answer.
+* */
+* if (fsave_frame_format == $4060) {goto KILL_PROCESS}
+*
+* fsave_frame = /* build a long frame of all zeros */
+* fsave_frame_format = $4060; /* label it as long frame */
+*
+* /* load it with the temps we saved */
+* STAG[fsave_frame] = stag_temp;
+* CMDREG1B[fsave_frame] = cmdreg1b_temp;
+* DTAG[fsave_frame] = dtag_temp;
+* ETE15[fsave_frame] = ete15_temp;
+*
+* /* Make sure that the cmdreg3b dest reg is not going to
+* * be destroyed by a FMOVEM at the end of all this code.
+* * If it is, you should move the current value of the reg
+* * onto the stack so that the reg will loaded with that value.
+* */
+*
+* /* All done. Proceed with the code below */
+* }
+*
+* etemp = FP_reg_[cmdreg1b[12:10]];
+* ete15 = ~ete14;
+* cmdreg1b[15:10] = 010010;
+* clear(bug_flag_procIDxxxx);
+* FRESTORE and return;
+*
+*
+* FIX_OPCLASS2:
+* if ((cmdreg1b[9:7] == cmdreg2b[9:7]) &&
+* (cmdreg1b[9:7] != cmdreg3b[9:7])) { /* xu conflict only */
+* /* We execute the following code if there is an
+* xu conflict and NOT an nu conflict */
+*
+* /* first save some values on the fsave frame */
+* stag_temp = STAG[fsave_frame];
+* cmdreg1b_temp = CMDREG1B[fsave_frame];
+* dtag_temp = DTAG[fsave_frame];
+* ete15_temp = ETE15[fsave_frame];
+* etemp_temp = ETEMP[fsave_frame];
+*
+* CUPC[fsave_frame] = 0000000;
+* FRESTORE
+* FSAVE
+*
+*
+* /* If the xu instruction is exceptional, we punt.
+* * Otherwise, we would have to include OVFL/UNFL handler
+* * code here to get the correct answer.
+* */
+* if (fsave_frame_format == $4060) {goto KILL_PROCESS}
+*
+* fsave_frame = /* build a long frame of all zeros */
+* fsave_frame_format = $4060; /* label it as long frame */
+*
+* /* load it with the temps we saved */
+* STAG[fsave_frame] = stag_temp;
+* CMDREG1B[fsave_frame] = cmdreg1b_temp;
+* DTAG[fsave_frame] = dtag_temp;
+* ETE15[fsave_frame] = ete15_temp;
+* ETEMP[fsave_frame] = etemp_temp;
+*
+* /* Make sure that the cmdreg3b dest reg is not going to
+* * be destroyed by a FMOVEM at the end of all this code.
+* * If it is, you should move the current value of the reg
+* * onto the stack so that the reg will loaded with that value.
+* */
+*
+* /* All done. Proceed with the code below */
+* }
+*
+* if (etemp_exponent == min_sgl) etemp_exponent = min_dbl;
+* if (etemp_exponent == max_sgl) etemp_exponent = max_dbl;
+* cmdreg1b[15:10] = 010101;
+* clear(bug_flag_procIDxxxx);
+* FRESTORE and return;
+*
+*
+* NOFIX:
+* clear(bug_flag_procIDxxxx);
+* FRESTORE and return;
+*
+
+BUGFIX IDNT 2,1 Motorola 040 Floating Point Software Package
+
+ section 8
+
+ include fpsp.h
+
+ xref fpsp_fmt_error
+
+ xdef b1238_fix
+b1238_fix:
+*
+* This code is entered only on completion of the handling of an
+* nu-generated ovfl, unfl, or inex exception. If the version
+* number of the fsave is not $40, this handler is not necessary.
+* Simply branch to fix_done and exit normally.
+*
+ cmpi.b #VER_40,4(a7)
+ bne.w fix_done
+*
+* Test for cu_savepc equal to zero. If not, this is not a bug
+* #1238 case.
+*
+ move.b CU_SAVEPC(a6),d0
+ andi.b #$FE,d0
+ beq fix_done ;if zero, this is not bug #1238
+
+*
+* Test the register conflict aspect. If opclass0, check for
+* cu src equal to xu dest or equal to nu dest. If so, go to
+* op0. Else, or if opclass2, check for cu dest equal to
+* xu dest or equal to nu dest. If so, go to tst_opcl. Else,
+* exit, it is not the bug case.
+*
+* Check for opclass 0. If not, go and check for opclass 2 and sgl.
+*
+ move.w CMDREG1B(a6),d0
+ andi.w #$E000,d0 ;strip all but opclass
+ bne op2sgl ;not opclass 0, check op2
+*
+* Check for cu and nu register conflict. If one exists, this takes
+* priority over a cu and xu conflict.
+*
+ bfextu CMDREG1B(a6){3:3},d0 ;get 1st src
+ bfextu CMDREG3B(a6){6:3},d1 ;get 3rd dest
+ cmp.b d0,d1
+ beq.b op0 ;if equal, continue bugfix
+*
+* Check for cu dest equal to nu dest. If so, go and fix the
+* bug condition. Otherwise, exit.
+*
+ bfextu CMDREG1B(a6){6:3},d0 ;get 1st dest
+ cmp.b d0,d1 ;cmp 1st dest with 3rd dest
+ beq.b op0 ;if equal, continue bugfix
+*
+* Check for cu and xu register conflict.
+*
+ bfextu CMDREG2B(a6){6:3},d1 ;get 2nd dest
+ cmp.b d0,d1 ;cmp 1st dest with 2nd dest
+ beq.b op0_xu ;if equal, continue bugfix
+ bfextu CMDREG1B(a6){3:3},d0 ;get 1st src
+ cmp.b d0,d1 ;cmp 1st src with 2nd dest
+ beq op0_xu
+ bne fix_done ;if the reg checks fail, exit
+*
+* We have the opclass 0 situation.
+*
+op0:
+ bfextu CMDREG1B(a6){3:3},d0 ;get source register no
+ move.l #7,d1
+ sub.l d0,d1
+ clr.l d0
+ bset.l d1,d0
+ fmovem.x d0,ETEMP(a6) ;load source to ETEMP
+
+ move.b #$12,d0
+ bfins d0,CMDREG1B(a6){0:6} ;opclass 2, extended
+*
+* Set ETEMP exponent bit 15 as the opposite of ete14
+*
+ btst #6,ETEMP_EX(a6) ;check etemp exponent bit 14
+ beq setete15
+ bclr #etemp15_bit,STAG(a6)
+ bra finish
+setete15:
+ bset #etemp15_bit,STAG(a6)
+ bra finish
+
+*
+* We have the case in which a conflict exists between the cu src or
+* dest and the dest of the xu. We must clear the instruction in
+* the cu and restore the state, allowing the instruction in the
+* xu to complete. Remember, the instruction in the nu
+* was exceptional, and was completed by the appropriate handler.
+* If the result of the xu instruction is not exceptional, we can
+* restore the instruction from the cu to the frame and continue
+* processing the original exception. If the result is also
+* exceptional, we choose to kill the process.
+*
+* Items saved from the stack:
+*
+* $3c stag - L_SCR1
+* $40 cmdreg1b - L_SCR2
+* $44 dtag - L_SCR3
+*
+* The cu savepc is set to zero, and the frame is restored to the
+* fpu.
+*
+op0_xu:
+ move.l STAG(a6),L_SCR1(a6)
+ move.l CMDREG1B(a6),L_SCR2(a6)
+ move.l DTAG(a6),L_SCR3(a6)
+ andi.l #$e0000000,L_SCR3(a6)
+ clr.b CU_SAVEPC(a6)
+ move.l (a7)+,d1 ;save return address from bsr
+ frestore (a7)+
+ fsave -(a7)
+*
+* Check if the instruction which just completed was exceptional.
+*
+ cmp.w #$4060,(a7)
+ beq op0_xb
+*
+* It is necessary to isolate the result of the instruction in the
+* xu if it is to fp0 - fp3 and write that value to the USER_FPn
+* locations on the stack. The correct destination register is in
+* cmdreg2b.
+*
+ bfextu CMDREG2B(a6){6:3},d0 ;get dest register no
+ cmpi.l #3,d0
+ bgt.b op0_xi
+ beq.b op0_fp3
+ cmpi.l #1,d0
+ blt.b op0_fp0
+ beq.b op0_fp1
+op0_fp2:
+ fmovem.x fp2,USER_FP2(a6)
+ bra.b op0_xi
+op0_fp1:
+ fmovem.x fp1,USER_FP1(a6)
+ bra.b op0_xi
+op0_fp0:
+ fmovem.x fp0,USER_FP0(a6)
+ bra.b op0_xi
+op0_fp3:
+ fmovem.x fp3,USER_FP3(a6)
+*
+* The frame returned is idle. We must build a busy frame to hold
+* the cu state information and setup etemp.
+*
+op0_xi:
+ move.l #22,d0 ;clear 23 lwords
+ clr.l (a7)
+op0_loop:
+ clr.l -(a7)
+ dbf d0,op0_loop
+ move.l #$40600000,-(a7)
+ move.l L_SCR1(a6),STAG(a6)
+ move.l L_SCR2(a6),CMDREG1B(a6)
+ move.l L_SCR3(a6),DTAG(a6)
+ move.b #$6,CU_SAVEPC(a6)
+ move.l d1,-(a7) ;return bsr return address
+ bfextu CMDREG1B(a6){3:3},d0 ;get source register no
+ move.l #7,d1
+ sub.l d0,d1
+ clr.l d0
+ bset.l d1,d0
+ fmovem.x d0,ETEMP(a6) ;load source to ETEMP
+
+ move.b #$12,d0
+ bfins d0,CMDREG1B(a6){0:6} ;opclass 2, extended
+*
+* Set ETEMP exponent bit 15 as the opposite of ete14
+*
+ btst #6,ETEMP_EX(a6) ;check etemp exponent bit 14
+ beq op0_sete15
+ bclr #etemp15_bit,STAG(a6)
+ bra finish
+op0_sete15:
+ bset #etemp15_bit,STAG(a6)
+ bra finish
+
+*
+* The frame returned is busy. It is not possible to reconstruct
+* the code sequence to allow completion. We will jump to
+* fpsp_fmt_error and allow the kernel to kill the process.
+*
+op0_xb:
+ jmp fpsp_fmt_error
+
+*
+* Check for opclass 2 and single size. If not both, exit.
+*
+op2sgl:
+ move.w CMDREG1B(a6),d0
+ andi.w #$FC00,d0 ;strip all but opclass and size
+ cmpi.w #$4400,d0 ;test for opclass 2 and size=sgl
+ bne fix_done ;if not, it is not bug 1238
+*
+* Check for cu dest equal to nu dest or equal to xu dest, with
+* a cu and nu conflict taking priority an nu conflict. If either,
+* go and fix the bug condition. Otherwise, exit.
+*
+ bfextu CMDREG1B(a6){6:3},d0 ;get 1st dest
+ bfextu CMDREG3B(a6){6:3},d1 ;get 3rd dest
+ cmp.b d0,d1 ;cmp 1st dest with 3rd dest
+ beq op2_com ;if equal, continue bugfix
+ bfextu CMDREG2B(a6){6:3},d1 ;get 2nd dest
+ cmp.b d0,d1 ;cmp 1st dest with 2nd dest
+ bne fix_done ;if the reg checks fail, exit
+*
+* We have the case in which a conflict exists between the cu src or
+* dest and the dest of the xu. We must clear the instruction in
+* the cu and restore the state, allowing the instruction in the
+* xu to complete. Remember, the instruction in the nu
+* was exceptional, and was completed by the appropriate handler.
+* If the result of the xu instruction is not exceptional, we can
+* restore the instruction from the cu to the frame and continue
+* processing the original exception. If the result is also
+* exceptional, we choose to kill the process.
+*
+* Items saved from the stack:
+*
+* $3c stag - L_SCR1
+* $40 cmdreg1b - L_SCR2
+* $44 dtag - L_SCR3
+* etemp - FP_SCR2
+*
+* The cu savepc is set to zero, and the frame is restored to the
+* fpu.
+*
+op2_xu:
+ move.l STAG(a6),L_SCR1(a6)
+ move.l CMDREG1B(a6),L_SCR2(a6)
+ move.l DTAG(a6),L_SCR3(a6)
+ andi.l #$e0000000,L_SCR3(a6)
+ clr.b CU_SAVEPC(a6)
+ move.l ETEMP(a6),FP_SCR2(a6)
+ move.l ETEMP_HI(a6),FP_SCR2+4(a6)
+ move.l ETEMP_LO(a6),FP_SCR2+8(a6)
+ move.l (a7)+,d1 ;save return address from bsr
+ frestore (a7)+
+ fsave -(a7)
+*
+* Check if the instruction which just completed was exceptional.
+*
+ cmp.w #$4060,(a7)
+ beq op2_xb
+*
+* It is necessary to isolate the result of the instruction in the
+* xu if it is to fp0 - fp3 and write that value to the USER_FPn
+* locations on the stack. The correct destination register is in
+* cmdreg2b.
+*
+ bfextu CMDREG2B(a6){6:3},d0 ;get dest register no
+ cmpi.l #3,d0
+ bgt.b op2_xi
+ beq.b op2_fp3
+ cmpi.l #1,d0
+ blt.b op2_fp0
+ beq.b op2_fp1
+op2_fp2:
+ fmovem.x fp2,USER_FP2(a6)
+ bra.b op2_xi
+op2_fp1:
+ fmovem.x fp1,USER_FP1(a6)
+ bra.b op2_xi
+op2_fp0:
+ fmovem.x fp0,USER_FP0(a6)
+ bra.b op2_xi
+op2_fp3:
+ fmovem.x fp3,USER_FP3(a6)
+*
+* The frame returned is idle. We must build a busy frame to hold
+* the cu state information and fix up etemp.
+*
+op2_xi:
+ move.l #22,d0 ;clear 23 lwords
+ clr.l (a7)
+op2_loop:
+ clr.l -(a7)
+ dbf d0,op2_loop
+ move.l #$40600000,-(a7)
+ move.l L_SCR1(a6),STAG(a6)
+ move.l L_SCR2(a6),CMDREG1B(a6)
+ move.l L_SCR3(a6),DTAG(a6)
+ move.b #$6,CU_SAVEPC(a6)
+ move.l FP_SCR2(a6),ETEMP(a6)
+ move.l FP_SCR2+4(a6),ETEMP_HI(a6)
+ move.l FP_SCR2+8(a6),ETEMP_LO(a6)
+ move.l d1,-(a7)
+ bra op2_com
+
+*
+* We have the opclass 2 single source situation.
+*
+op2_com:
+ move.b #$15,d0
+ bfins d0,CMDREG1B(a6){0:6} ;opclass 2, double
+
+ cmp.w #$407F,ETEMP_EX(a6) ;single +max
+ bne.b case2
+ move.w #$43FF,ETEMP_EX(a6) ;to double +max
+ bra finish
+case2:
+ cmp.w #$C07F,ETEMP_EX(a6) ;single -max
+ bne.b case3
+ move.w #$C3FF,ETEMP_EX(a6) ;to double -max
+ bra finish
+case3:
+ cmp.w #$3F80,ETEMP_EX(a6) ;single +min
+ bne.b case4
+ move.w #$3C00,ETEMP_EX(a6) ;to double +min
+ bra finish
+case4:
+ cmp.w #$BF80,ETEMP_EX(a6) ;single -min
+ bne fix_done
+ move.w #$BC00,ETEMP_EX(a6) ;to double -min
+ bra finish
+*
+* The frame returned is busy. It is not possible to reconstruct
+* the code sequence to allow completion. fpsp_fmt_error causes
+* an fline illegal instruction to be executed.
+*
+* You should replace the jump to fpsp_fmt_error with a jump
+* to the entry point used to kill a process.
+*
+op2_xb:
+ jmp fpsp_fmt_error
+
+*
+* Enter here if the case is not of the situations affected by
+* bug #1238, or if the fix is completed, and exit.
+*
+finish:
+fix_done:
+ rts
+
+ end