diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
commit | d6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch) | |
tree | ece253b876159b39c620e62b6c9b1174642e070e /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.sa | 520 |
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 |