Back to home page

LXR

 
 

    


0001 |
0002 |   bugfix.sa 3.2 1/31/91
0003 |
0004 |
0005 |   This file contains workarounds for bugs in the 040
0006 |   relating to the Floating-Point Software Package (FPSP)
0007 |
0008 |   Fixes for bugs: 1238
0009 |
0010 |   Bug: 1238
0011 |
0012 |
0013 |    /* The following dirty_bit clear should be left in
0014 |     * the handler permanently to improve throughput.
0015 |     * The dirty_bits are located at bits [23:16] in
0016 |     * longword $08 in the busy frame $4x60.  Bit 16
0017 |     * corresponds to FP0, bit 17 corresponds to FP1,
0018 |     * and so on.
0019 |     */
0020 |    if  (E3_exception_just_serviced)   {
0021 |         dirty_bit[cmdreg3b[9:7]] = 0;
0022 |         }
0023 |
0024 |    if  (fsave_format_version != $40)  {goto NOFIX}
0025 |
0026 |    if !(E3_exception_just_serviced)   {goto NOFIX}
0027 |    if  (cupc == 0000000)              {goto NOFIX}
0028 |    if  ((cmdreg1b[15:13] != 000) &&
0029 |         (cmdreg1b[15:10] != 010001))  {goto NOFIX}
0030 |    if (((cmdreg1b[15:13] != 000) || ((cmdreg1b[12:10] != cmdreg2b[9:7]) &&
0031 |                     (cmdreg1b[12:10] != cmdreg3b[9:7]))  ) &&
0032 |    ((cmdreg1b[ 9: 7] != cmdreg2b[9:7]) &&
0033 |     (cmdreg1b[ 9: 7] != cmdreg3b[9:7])) )  {goto NOFIX}
0034 |
0035 |    /* Note: for 6d43b or 8d43b, you may want to add the following code
0036 |     * to get better coverage.  (If you do not insert this code, the part
0037 |     * won't lock up; it will simply get the wrong answer.)
0038 |     * Do NOT insert this code for 10d43b or later parts.
0039 |     *
0040 |     *  if (fpiarcu == integer stack return address) {
0041 |     *       cupc = 0000000;
0042 |     *       goto NOFIX;
0043 |     *       }
0044 |     */
0045 |
0046 |    if (cmdreg1b[15:13] != 000)   {goto FIX_OPCLASS2}
0047 |    FIX_OPCLASS0:
0048 |    if (((cmdreg1b[12:10] == cmdreg2b[9:7]) ||
0049 |    (cmdreg1b[ 9: 7] == cmdreg2b[9:7])) &&
0050 |   (cmdreg1b[12:10] != cmdreg3b[9:7]) &&
0051 |   (cmdreg1b[ 9: 7] != cmdreg3b[9:7]))  {  /* xu conflict only */
0052 |   /* We execute the following code if there is an
0053 |      xu conflict and NOT an nu conflict */
0054 |
0055 |   /* first save some values on the fsave frame */
0056 |   stag_temp     = STAG[fsave_frame];
0057 |   cmdreg1b_temp = CMDREG1B[fsave_frame];
0058 |   dtag_temp     = DTAG[fsave_frame];
0059 |   ete15_temp    = ETE15[fsave_frame];
0060 |
0061 |   CUPC[fsave_frame] = 0000000;
0062 |   FRESTORE
0063 |   FSAVE
0064 |
0065 |   /* If the xu instruction is exceptional, we punt.
0066 |    * Otherwise, we would have to include OVFL/UNFL handler
0067 |    * code here to get the correct answer.
0068 |    */
0069 |   if (fsave_frame_format == $4060) {goto KILL_PROCESS}
0070 |
0071 |   fsave_frame = /* build a long frame of all zeros */
0072 |   fsave_frame_format = $4060;  /* label it as long frame */
0073 |
0074 |   /* load it with the temps we saved */
0075 |   STAG[fsave_frame]     =  stag_temp;
0076 |   CMDREG1B[fsave_frame] =  cmdreg1b_temp;
0077 |   DTAG[fsave_frame]     =  dtag_temp;
0078 |   ETE15[fsave_frame]    =  ete15_temp;
0079 |
0080 |   /* Make sure that the cmdreg3b dest reg is not going to
0081 |    * be destroyed by a FMOVEM at the end of all this code.
0082 |    * If it is, you should move the current value of the reg
0083 |    * onto the stack so that the reg will loaded with that value.
0084 |    */
0085 |
0086 |   /* All done.  Proceed with the code below */
0087 |    }
0088 |
0089 |    etemp  = FP_reg_[cmdreg1b[12:10]];
0090 |    ete15  = ~ete14;
0091 |    cmdreg1b[15:10] = 010010;
0092 |    clear(bug_flag_procIDxxxx);
0093 |    FRESTORE and return;
0094 |
0095 |
0096 |    FIX_OPCLASS2:
0097 |    if ((cmdreg1b[9:7] == cmdreg2b[9:7]) &&
0098 |   (cmdreg1b[9:7] != cmdreg3b[9:7]))  {  /* xu conflict only */
0099 |   /* We execute the following code if there is an
0100 |      xu conflict and NOT an nu conflict */
0101 |
0102 |   /* first save some values on the fsave frame */
0103 |   stag_temp     = STAG[fsave_frame];
0104 |   cmdreg1b_temp = CMDREG1B[fsave_frame];
0105 |   dtag_temp     = DTAG[fsave_frame];
0106 |   ete15_temp    = ETE15[fsave_frame];
0107 |   etemp_temp    = ETEMP[fsave_frame];
0108 |
0109 |   CUPC[fsave_frame] = 0000000;
0110 |   FRESTORE
0111 |   FSAVE
0112 |
0113 |
0114 |   /* If the xu instruction is exceptional, we punt.
0115 |    * Otherwise, we would have to include OVFL/UNFL handler
0116 |    * code here to get the correct answer.
0117 |    */
0118 |   if (fsave_frame_format == $4060) {goto KILL_PROCESS}
0119 |
0120 |   fsave_frame = /* build a long frame of all zeros */
0121 |   fsave_frame_format = $4060;  /* label it as long frame */
0122 |
0123 |   /* load it with the temps we saved */
0124 |   STAG[fsave_frame]     =  stag_temp;
0125 |   CMDREG1B[fsave_frame] =  cmdreg1b_temp;
0126 |   DTAG[fsave_frame]     =  dtag_temp;
0127 |   ETE15[fsave_frame]    =  ete15_temp;
0128 |   ETEMP[fsave_frame]    =  etemp_temp;
0129 |
0130 |   /* Make sure that the cmdreg3b dest reg is not going to
0131 |    * be destroyed by a FMOVEM at the end of all this code.
0132 |    * If it is, you should move the current value of the reg
0133 |    * onto the stack so that the reg will loaded with that value.
0134 |    */
0135 |
0136 |   /* All done.  Proceed with the code below */
0137 |    }
0138 |
0139 |    if (etemp_exponent == min_sgl)   etemp_exponent = min_dbl;
0140 |    if (etemp_exponent == max_sgl)   etemp_exponent = max_dbl;
0141 |    cmdreg1b[15:10] = 010101;
0142 |    clear(bug_flag_procIDxxxx);
0143 |    FRESTORE and return;
0144 |
0145 |
0146 |    NOFIX:
0147 |    clear(bug_flag_procIDxxxx);
0148 |    FRESTORE and return;
0149 |
0150 
0151 
0152 |       Copyright (C) Motorola, Inc. 1990
0153 |           All Rights Reserved
0154 |
0155 |       For details on the license for this file, please see the
0156 |       file, README, in this same directory.
0157 
0158 |BUGFIX    idnt    2,1 | Motorola 040 Floating Point Software Package
0159 
0160     |section    8
0161 
0162 #include "fpsp.h"
0163 
0164     |xref   fpsp_fmt_error
0165 
0166     .global b1238_fix
0167 b1238_fix:
0168 |
0169 | This code is entered only on completion of the handling of an
0170 | nu-generated ovfl, unfl, or inex exception.  If the version
0171 | number of the fsave is not $40, this handler is not necessary.
0172 | Simply branch to fix_done and exit normally.
0173 |
0174     cmpib   #VER_40,4(%a7)
0175     bne fix_done
0176 |
0177 | Test for cu_savepc equal to zero.  If not, this is not a bug
0178 | #1238 case.
0179 |
0180     moveb   CU_SAVEPC(%a6),%d0
0181     andib   #0xFE,%d0
0182     beq fix_done    |if zero, this is not bug #1238
0183 
0184 |
0185 | Test the register conflict aspect.  If opclass0, check for
0186 | cu src equal to xu dest or equal to nu dest.  If so, go to
0187 | op0.  Else, or if opclass2, check for cu dest equal to
0188 | xu dest or equal to nu dest.  If so, go to tst_opcl.  Else,
0189 | exit, it is not the bug case.
0190 |
0191 | Check for opclass 0.  If not, go and check for opclass 2 and sgl.
0192 |
0193     movew   CMDREG1B(%a6),%d0
0194     andiw   #0xE000,%d0     |strip all but opclass
0195     bne op2sgl          |not opclass 0, check op2
0196 |
0197 | Check for cu and nu register conflict.  If one exists, this takes
0198 | priority over a cu and xu conflict.
0199 |
0200     bfextu  CMDREG1B(%a6){#3:#3},%d0    |get 1st src
0201     bfextu  CMDREG3B(%a6){#6:#3},%d1    |get 3rd dest
0202     cmpb    %d0,%d1
0203     beqs    op0         |if equal, continue bugfix
0204 |
0205 | Check for cu dest equal to nu dest.  If so, go and fix the
0206 | bug condition.  Otherwise, exit.
0207 |
0208     bfextu  CMDREG1B(%a6){#6:#3},%d0    |get 1st dest
0209     cmpb    %d0,%d1         |cmp 1st dest with 3rd dest
0210     beqs    op0         |if equal, continue bugfix
0211 |
0212 | Check for cu and xu register conflict.
0213 |
0214     bfextu  CMDREG2B(%a6){#6:#3},%d1    |get 2nd dest
0215     cmpb    %d0,%d1         |cmp 1st dest with 2nd dest
0216     beqs    op0_xu          |if equal, continue bugfix
0217     bfextu  CMDREG1B(%a6){#3:#3},%d0    |get 1st src
0218     cmpb    %d0,%d1         |cmp 1st src with 2nd dest
0219     beq op0_xu
0220     bne fix_done        |if the reg checks fail, exit
0221 |
0222 | We have the opclass 0 situation.
0223 |
0224 op0:
0225     bfextu  CMDREG1B(%a6){#3:#3},%d0    |get source register no
0226     movel   #7,%d1
0227     subl    %d0,%d1
0228     clrl    %d0
0229     bsetl   %d1,%d0
0230     fmovemx %d0,ETEMP(%a6)      |load source to ETEMP
0231 
0232     moveb   #0x12,%d0
0233     bfins   %d0,CMDREG1B(%a6){#0:#6}    |opclass 2, extended
0234 |
0235 |   Set ETEMP exponent bit 15 as the opposite of ete14
0236 |
0237     btst    #6,ETEMP_EX(%a6)        |check etemp exponent bit 14
0238     beq setete15
0239     bclr    #etemp15_bit,STAG(%a6)
0240     bra finish
0241 setete15:
0242     bset    #etemp15_bit,STAG(%a6)
0243     bra finish
0244 
0245 |
0246 | We have the case in which a conflict exists between the cu src or
0247 | dest and the dest of the xu.  We must clear the instruction in
0248 | the cu and restore the state, allowing the instruction in the
0249 | xu to complete.  Remember, the instruction in the nu
0250 | was exceptional, and was completed by the appropriate handler.
0251 | If the result of the xu instruction is not exceptional, we can
0252 | restore the instruction from the cu to the frame and continue
0253 | processing the original exception.  If the result is also
0254 | exceptional, we choose to kill the process.
0255 |
0256 |   Items saved from the stack:
0257 |
0258 |       $3c stag     - L_SCR1
0259 |       $40 cmdreg1b - L_SCR2
0260 |       $44 dtag     - L_SCR3
0261 |
0262 | The cu savepc is set to zero, and the frame is restored to the
0263 | fpu.
0264 |
0265 op0_xu:
0266     movel   STAG(%a6),L_SCR1(%a6)
0267     movel   CMDREG1B(%a6),L_SCR2(%a6)
0268     movel   DTAG(%a6),L_SCR3(%a6)
0269     andil   #0xe0000000,L_SCR3(%a6)
0270     moveb   #0,CU_SAVEPC(%a6)
0271     movel   (%a7)+,%d1      |save return address from bsr
0272     frestore (%a7)+
0273     fsave   -(%a7)
0274 |
0275 | Check if the instruction which just completed was exceptional.
0276 |
0277     cmpw    #0x4060,(%a7)
0278     beq op0_xb
0279 |
0280 | It is necessary to isolate the result of the instruction in the
0281 | xu if it is to fp0 - fp3 and write that value to the USER_FPn
0282 | locations on the stack.  The correct destination register is in
0283 | cmdreg2b.
0284 |
0285     bfextu  CMDREG2B(%a6){#6:#3},%d0    |get dest register no
0286     cmpil   #3,%d0
0287     bgts    op0_xi
0288     beqs    op0_fp3
0289     cmpil   #1,%d0
0290     blts    op0_fp0
0291     beqs    op0_fp1
0292 op0_fp2:
0293     fmovemx %fp2-%fp2,USER_FP2(%a6)
0294     bras    op0_xi
0295 op0_fp1:
0296     fmovemx %fp1-%fp1,USER_FP1(%a6)
0297     bras    op0_xi
0298 op0_fp0:
0299     fmovemx %fp0-%fp0,USER_FP0(%a6)
0300     bras    op0_xi
0301 op0_fp3:
0302     fmovemx %fp3-%fp3,USER_FP3(%a6)
0303 |
0304 | The frame returned is idle.  We must build a busy frame to hold
0305 | the cu state information and setup etemp.
0306 |
0307 op0_xi:
0308     movel   #22,%d0     |clear 23 lwords
0309     clrl    (%a7)
0310 op0_loop:
0311     clrl    -(%a7)
0312     dbf %d0,op0_loop
0313     movel   #0x40600000,-(%a7)
0314     movel   L_SCR1(%a6),STAG(%a6)
0315     movel   L_SCR2(%a6),CMDREG1B(%a6)
0316     movel   L_SCR3(%a6),DTAG(%a6)
0317     moveb   #0x6,CU_SAVEPC(%a6)
0318     movel   %d1,-(%a7)      |return bsr return address
0319     bfextu  CMDREG1B(%a6){#3:#3},%d0    |get source register no
0320     movel   #7,%d1
0321     subl    %d0,%d1
0322     clrl    %d0
0323     bsetl   %d1,%d0
0324     fmovemx %d0,ETEMP(%a6)      |load source to ETEMP
0325 
0326     moveb   #0x12,%d0
0327     bfins   %d0,CMDREG1B(%a6){#0:#6}    |opclass 2, extended
0328 |
0329 |   Set ETEMP exponent bit 15 as the opposite of ete14
0330 |
0331     btst    #6,ETEMP_EX(%a6)        |check etemp exponent bit 14
0332     beq op0_sete15
0333     bclr    #etemp15_bit,STAG(%a6)
0334     bra finish
0335 op0_sete15:
0336     bset    #etemp15_bit,STAG(%a6)
0337     bra finish
0338 
0339 |
0340 | The frame returned is busy.  It is not possible to reconstruct
0341 | the code sequence to allow completion.  We will jump to
0342 | fpsp_fmt_error and allow the kernel to kill the process.
0343 |
0344 op0_xb:
0345     jmp fpsp_fmt_error
0346 
0347 |
0348 | Check for opclass 2 and single size.  If not both, exit.
0349 |
0350 op2sgl:
0351     movew   CMDREG1B(%a6),%d0
0352     andiw   #0xFC00,%d0     |strip all but opclass and size
0353     cmpiw   #0x4400,%d0     |test for opclass 2 and size=sgl
0354     bne fix_done        |if not, it is not bug 1238
0355 |
0356 | Check for cu dest equal to nu dest or equal to xu dest, with
0357 | a cu and nu conflict taking priority an nu conflict.  If either,
0358 | go and fix the bug condition.  Otherwise, exit.
0359 |
0360     bfextu  CMDREG1B(%a6){#6:#3},%d0    |get 1st dest
0361     bfextu  CMDREG3B(%a6){#6:#3},%d1    |get 3rd dest
0362     cmpb    %d0,%d1         |cmp 1st dest with 3rd dest
0363     beq op2_com         |if equal, continue bugfix
0364     bfextu  CMDREG2B(%a6){#6:#3},%d1    |get 2nd dest
0365     cmpb    %d0,%d1         |cmp 1st dest with 2nd dest
0366     bne fix_done        |if the reg checks fail, exit
0367 |
0368 | We have the case in which a conflict exists between the cu src or
0369 | dest and the dest of the xu.  We must clear the instruction in
0370 | the cu and restore the state, allowing the instruction in the
0371 | xu to complete.  Remember, the instruction in the nu
0372 | was exceptional, and was completed by the appropriate handler.
0373 | If the result of the xu instruction is not exceptional, we can
0374 | restore the instruction from the cu to the frame and continue
0375 | processing the original exception.  If the result is also
0376 | exceptional, we choose to kill the process.
0377 |
0378 |   Items saved from the stack:
0379 |
0380 |       $3c stag     - L_SCR1
0381 |       $40 cmdreg1b - L_SCR2
0382 |       $44 dtag     - L_SCR3
0383 |       etemp        - FP_SCR2
0384 |
0385 | The cu savepc is set to zero, and the frame is restored to the
0386 | fpu.
0387 |
0388 op2_xu:
0389     movel   STAG(%a6),L_SCR1(%a6)
0390     movel   CMDREG1B(%a6),L_SCR2(%a6)
0391     movel   DTAG(%a6),L_SCR3(%a6)
0392     andil   #0xe0000000,L_SCR3(%a6)
0393     moveb   #0,CU_SAVEPC(%a6)
0394     movel   ETEMP(%a6),FP_SCR2(%a6)
0395     movel   ETEMP_HI(%a6),FP_SCR2+4(%a6)
0396     movel   ETEMP_LO(%a6),FP_SCR2+8(%a6)
0397     movel   (%a7)+,%d1      |save return address from bsr
0398     frestore (%a7)+
0399     fsave   -(%a7)
0400 |
0401 | Check if the instruction which just completed was exceptional.
0402 |
0403     cmpw    #0x4060,(%a7)
0404     beq op2_xb
0405 |
0406 | It is necessary to isolate the result of the instruction in the
0407 | xu if it is to fp0 - fp3 and write that value to the USER_FPn
0408 | locations on the stack.  The correct destination register is in
0409 | cmdreg2b.
0410 |
0411     bfextu  CMDREG2B(%a6){#6:#3},%d0    |get dest register no
0412     cmpil   #3,%d0
0413     bgts    op2_xi
0414     beqs    op2_fp3
0415     cmpil   #1,%d0
0416     blts    op2_fp0
0417     beqs    op2_fp1
0418 op2_fp2:
0419     fmovemx %fp2-%fp2,USER_FP2(%a6)
0420     bras    op2_xi
0421 op2_fp1:
0422     fmovemx %fp1-%fp1,USER_FP1(%a6)
0423     bras    op2_xi
0424 op2_fp0:
0425     fmovemx %fp0-%fp0,USER_FP0(%a6)
0426     bras    op2_xi
0427 op2_fp3:
0428     fmovemx %fp3-%fp3,USER_FP3(%a6)
0429 |
0430 | The frame returned is idle.  We must build a busy frame to hold
0431 | the cu state information and fix up etemp.
0432 |
0433 op2_xi:
0434     movel   #22,%d0     |clear 23 lwords
0435     clrl    (%a7)
0436 op2_loop:
0437     clrl    -(%a7)
0438     dbf %d0,op2_loop
0439     movel   #0x40600000,-(%a7)
0440     movel   L_SCR1(%a6),STAG(%a6)
0441     movel   L_SCR2(%a6),CMDREG1B(%a6)
0442     movel   L_SCR3(%a6),DTAG(%a6)
0443     moveb   #0x6,CU_SAVEPC(%a6)
0444     movel   FP_SCR2(%a6),ETEMP(%a6)
0445     movel   FP_SCR2+4(%a6),ETEMP_HI(%a6)
0446     movel   FP_SCR2+8(%a6),ETEMP_LO(%a6)
0447     movel   %d1,-(%a7)
0448     bra op2_com
0449 
0450 |
0451 | We have the opclass 2 single source situation.
0452 |
0453 op2_com:
0454     moveb   #0x15,%d0
0455     bfins   %d0,CMDREG1B(%a6){#0:#6}    |opclass 2, double
0456 
0457     cmpw    #0x407F,ETEMP_EX(%a6)   |single +max
0458     bnes    case2
0459     movew   #0x43FF,ETEMP_EX(%a6)   |to double +max
0460     bra finish
0461 case2:
0462     cmpw    #0xC07F,ETEMP_EX(%a6)   |single -max
0463     bnes    case3
0464     movew   #0xC3FF,ETEMP_EX(%a6)   |to double -max
0465     bra finish
0466 case3:
0467     cmpw    #0x3F80,ETEMP_EX(%a6)   |single +min
0468     bnes    case4
0469     movew   #0x3C00,ETEMP_EX(%a6)   |to double +min
0470     bra finish
0471 case4:
0472     cmpw    #0xBF80,ETEMP_EX(%a6)   |single -min
0473     bne fix_done
0474     movew   #0xBC00,ETEMP_EX(%a6)   |to double -min
0475     bra finish
0476 |
0477 | The frame returned is busy.  It is not possible to reconstruct
0478 | the code sequence to allow completion.  fpsp_fmt_error causes
0479 | an fline illegal instruction to be executed.
0480 |
0481 | You should replace the jump to fpsp_fmt_error with a jump
0482 | to the entry point used to kill a process.
0483 |
0484 op2_xb:
0485     jmp fpsp_fmt_error
0486 
0487 |
0488 | Enter here if the case is not of the situations affected by
0489 | bug #1238, or if the fix is completed, and exit.
0490 |
0491 finish:
0492 fix_done:
0493     rts
0494 
0495     |end