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 //
0015
0016
0017
0018
0019
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 //
0037
0038
0039
0040
0041
0042
0043
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])) {
0053 //
0054
0055 //
0056 //
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 //
0067
0068
0069
0070 // if (fsave_frame_format == $4060) {goto KILL_PROCESS}
0071 //
0072 // fsave_frame =
0073 // fsave_frame_format = $4060;
0074 //
0075 //
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 //
0082
0083
0084
0085
0086 //
0087 //
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])) {
0100 //
0101
0102 //
0103 //
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 //
0116
0117
0118
0119 // if (fsave_frame_format == $4060) {goto KILL_PROCESS}
0120 //
0121 // fsave_frame =
0122 // fsave_frame_format = $4060;
0123 //
0124 //
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 //
0132
0133
0134
0135
0136 //
0137 //
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