Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:48

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