162306a36Sopenharmony_ci| 262306a36Sopenharmony_ci| bugfix.sa 3.2 1/31/91 362306a36Sopenharmony_ci| 462306a36Sopenharmony_ci| 562306a36Sopenharmony_ci| This file contains workarounds for bugs in the 040 662306a36Sopenharmony_ci| relating to the Floating-Point Software Package (FPSP) 762306a36Sopenharmony_ci| 862306a36Sopenharmony_ci| Fixes for bugs: 1238 962306a36Sopenharmony_ci| 1062306a36Sopenharmony_ci| Bug: 1238 1162306a36Sopenharmony_ci| 1262306a36Sopenharmony_ci| 1362306a36Sopenharmony_ci| /* The following dirty_bit clear should be left in 1462306a36Sopenharmony_ci| * the handler permanently to improve throughput. 1562306a36Sopenharmony_ci| * The dirty_bits are located at bits [23:16] in 1662306a36Sopenharmony_ci| * longword $08 in the busy frame $4x60. Bit 16 1762306a36Sopenharmony_ci| * corresponds to FP0, bit 17 corresponds to FP1, 1862306a36Sopenharmony_ci| * and so on. 1962306a36Sopenharmony_ci| */ 2062306a36Sopenharmony_ci| if (E3_exception_just_serviced) { 2162306a36Sopenharmony_ci| dirty_bit[cmdreg3b[9:7]] = 0; 2262306a36Sopenharmony_ci| } 2362306a36Sopenharmony_ci| 2462306a36Sopenharmony_ci| if (fsave_format_version != $40) {goto NOFIX} 2562306a36Sopenharmony_ci| 2662306a36Sopenharmony_ci| if !(E3_exception_just_serviced) {goto NOFIX} 2762306a36Sopenharmony_ci| if (cupc == 0000000) {goto NOFIX} 2862306a36Sopenharmony_ci| if ((cmdreg1b[15:13] != 000) && 2962306a36Sopenharmony_ci| (cmdreg1b[15:10] != 010001)) {goto NOFIX} 3062306a36Sopenharmony_ci| if (((cmdreg1b[15:13] != 000) || ((cmdreg1b[12:10] != cmdreg2b[9:7]) && 3162306a36Sopenharmony_ci| (cmdreg1b[12:10] != cmdreg3b[9:7])) ) && 3262306a36Sopenharmony_ci| ((cmdreg1b[ 9: 7] != cmdreg2b[9:7]) && 3362306a36Sopenharmony_ci| (cmdreg1b[ 9: 7] != cmdreg3b[9:7])) ) {goto NOFIX} 3462306a36Sopenharmony_ci| 3562306a36Sopenharmony_ci| /* Note: for 6d43b or 8d43b, you may want to add the following code 3662306a36Sopenharmony_ci| * to get better coverage. (If you do not insert this code, the part 3762306a36Sopenharmony_ci| * won't lock up; it will simply get the wrong answer.) 3862306a36Sopenharmony_ci| * Do NOT insert this code for 10d43b or later parts. 3962306a36Sopenharmony_ci| * 4062306a36Sopenharmony_ci| * if (fpiarcu == integer stack return address) { 4162306a36Sopenharmony_ci| * cupc = 0000000; 4262306a36Sopenharmony_ci| * goto NOFIX; 4362306a36Sopenharmony_ci| * } 4462306a36Sopenharmony_ci| */ 4562306a36Sopenharmony_ci| 4662306a36Sopenharmony_ci| if (cmdreg1b[15:13] != 000) {goto FIX_OPCLASS2} 4762306a36Sopenharmony_ci| FIX_OPCLASS0: 4862306a36Sopenharmony_ci| if (((cmdreg1b[12:10] == cmdreg2b[9:7]) || 4962306a36Sopenharmony_ci| (cmdreg1b[ 9: 7] == cmdreg2b[9:7])) && 5062306a36Sopenharmony_ci| (cmdreg1b[12:10] != cmdreg3b[9:7]) && 5162306a36Sopenharmony_ci| (cmdreg1b[ 9: 7] != cmdreg3b[9:7])) { /* xu conflict only */ 5262306a36Sopenharmony_ci| /* We execute the following code if there is an 5362306a36Sopenharmony_ci| xu conflict and NOT an nu conflict */ 5462306a36Sopenharmony_ci| 5562306a36Sopenharmony_ci| /* first save some values on the fsave frame */ 5662306a36Sopenharmony_ci| stag_temp = STAG[fsave_frame]; 5762306a36Sopenharmony_ci| cmdreg1b_temp = CMDREG1B[fsave_frame]; 5862306a36Sopenharmony_ci| dtag_temp = DTAG[fsave_frame]; 5962306a36Sopenharmony_ci| ete15_temp = ETE15[fsave_frame]; 6062306a36Sopenharmony_ci| 6162306a36Sopenharmony_ci| CUPC[fsave_frame] = 0000000; 6262306a36Sopenharmony_ci| FRESTORE 6362306a36Sopenharmony_ci| FSAVE 6462306a36Sopenharmony_ci| 6562306a36Sopenharmony_ci| /* If the xu instruction is exceptional, we punt. 6662306a36Sopenharmony_ci| * Otherwise, we would have to include OVFL/UNFL handler 6762306a36Sopenharmony_ci| * code here to get the correct answer. 6862306a36Sopenharmony_ci| */ 6962306a36Sopenharmony_ci| if (fsave_frame_format == $4060) {goto KILL_PROCESS} 7062306a36Sopenharmony_ci| 7162306a36Sopenharmony_ci| fsave_frame = /* build a long frame of all zeros */ 7262306a36Sopenharmony_ci| fsave_frame_format = $4060; /* label it as long frame */ 7362306a36Sopenharmony_ci| 7462306a36Sopenharmony_ci| /* load it with the temps we saved */ 7562306a36Sopenharmony_ci| STAG[fsave_frame] = stag_temp; 7662306a36Sopenharmony_ci| CMDREG1B[fsave_frame] = cmdreg1b_temp; 7762306a36Sopenharmony_ci| DTAG[fsave_frame] = dtag_temp; 7862306a36Sopenharmony_ci| ETE15[fsave_frame] = ete15_temp; 7962306a36Sopenharmony_ci| 8062306a36Sopenharmony_ci| /* Make sure that the cmdreg3b dest reg is not going to 8162306a36Sopenharmony_ci| * be destroyed by a FMOVEM at the end of all this code. 8262306a36Sopenharmony_ci| * If it is, you should move the current value of the reg 8362306a36Sopenharmony_ci| * onto the stack so that the reg will loaded with that value. 8462306a36Sopenharmony_ci| */ 8562306a36Sopenharmony_ci| 8662306a36Sopenharmony_ci| /* All done. Proceed with the code below */ 8762306a36Sopenharmony_ci| } 8862306a36Sopenharmony_ci| 8962306a36Sopenharmony_ci| etemp = FP_reg_[cmdreg1b[12:10]]; 9062306a36Sopenharmony_ci| ete15 = ~ete14; 9162306a36Sopenharmony_ci| cmdreg1b[15:10] = 010010; 9262306a36Sopenharmony_ci| clear(bug_flag_procIDxxxx); 9362306a36Sopenharmony_ci| FRESTORE and return; 9462306a36Sopenharmony_ci| 9562306a36Sopenharmony_ci| 9662306a36Sopenharmony_ci| FIX_OPCLASS2: 9762306a36Sopenharmony_ci| if ((cmdreg1b[9:7] == cmdreg2b[9:7]) && 9862306a36Sopenharmony_ci| (cmdreg1b[9:7] != cmdreg3b[9:7])) { /* xu conflict only */ 9962306a36Sopenharmony_ci| /* We execute the following code if there is an 10062306a36Sopenharmony_ci| xu conflict and NOT an nu conflict */ 10162306a36Sopenharmony_ci| 10262306a36Sopenharmony_ci| /* first save some values on the fsave frame */ 10362306a36Sopenharmony_ci| stag_temp = STAG[fsave_frame]; 10462306a36Sopenharmony_ci| cmdreg1b_temp = CMDREG1B[fsave_frame]; 10562306a36Sopenharmony_ci| dtag_temp = DTAG[fsave_frame]; 10662306a36Sopenharmony_ci| ete15_temp = ETE15[fsave_frame]; 10762306a36Sopenharmony_ci| etemp_temp = ETEMP[fsave_frame]; 10862306a36Sopenharmony_ci| 10962306a36Sopenharmony_ci| CUPC[fsave_frame] = 0000000; 11062306a36Sopenharmony_ci| FRESTORE 11162306a36Sopenharmony_ci| FSAVE 11262306a36Sopenharmony_ci| 11362306a36Sopenharmony_ci| 11462306a36Sopenharmony_ci| /* If the xu instruction is exceptional, we punt. 11562306a36Sopenharmony_ci| * Otherwise, we would have to include OVFL/UNFL handler 11662306a36Sopenharmony_ci| * code here to get the correct answer. 11762306a36Sopenharmony_ci| */ 11862306a36Sopenharmony_ci| if (fsave_frame_format == $4060) {goto KILL_PROCESS} 11962306a36Sopenharmony_ci| 12062306a36Sopenharmony_ci| fsave_frame = /* build a long frame of all zeros */ 12162306a36Sopenharmony_ci| fsave_frame_format = $4060; /* label it as long frame */ 12262306a36Sopenharmony_ci| 12362306a36Sopenharmony_ci| /* load it with the temps we saved */ 12462306a36Sopenharmony_ci| STAG[fsave_frame] = stag_temp; 12562306a36Sopenharmony_ci| CMDREG1B[fsave_frame] = cmdreg1b_temp; 12662306a36Sopenharmony_ci| DTAG[fsave_frame] = dtag_temp; 12762306a36Sopenharmony_ci| ETE15[fsave_frame] = ete15_temp; 12862306a36Sopenharmony_ci| ETEMP[fsave_frame] = etemp_temp; 12962306a36Sopenharmony_ci| 13062306a36Sopenharmony_ci| /* Make sure that the cmdreg3b dest reg is not going to 13162306a36Sopenharmony_ci| * be destroyed by a FMOVEM at the end of all this code. 13262306a36Sopenharmony_ci| * If it is, you should move the current value of the reg 13362306a36Sopenharmony_ci| * onto the stack so that the reg will loaded with that value. 13462306a36Sopenharmony_ci| */ 13562306a36Sopenharmony_ci| 13662306a36Sopenharmony_ci| /* All done. Proceed with the code below */ 13762306a36Sopenharmony_ci| } 13862306a36Sopenharmony_ci| 13962306a36Sopenharmony_ci| if (etemp_exponent == min_sgl) etemp_exponent = min_dbl; 14062306a36Sopenharmony_ci| if (etemp_exponent == max_sgl) etemp_exponent = max_dbl; 14162306a36Sopenharmony_ci| cmdreg1b[15:10] = 010101; 14262306a36Sopenharmony_ci| clear(bug_flag_procIDxxxx); 14362306a36Sopenharmony_ci| FRESTORE and return; 14462306a36Sopenharmony_ci| 14562306a36Sopenharmony_ci| 14662306a36Sopenharmony_ci| NOFIX: 14762306a36Sopenharmony_ci| clear(bug_flag_procIDxxxx); 14862306a36Sopenharmony_ci| FRESTORE and return; 14962306a36Sopenharmony_ci| 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci| Copyright (C) Motorola, Inc. 1990 15362306a36Sopenharmony_ci| All Rights Reserved 15462306a36Sopenharmony_ci| 15562306a36Sopenharmony_ci| For details on the license for this file, please see the 15662306a36Sopenharmony_ci| file, README, in this same directory. 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci|BUGFIX idnt 2,1 | Motorola 040 Floating Point Software Package 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci |section 8 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci#include "fpsp.h" 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci |xref fpsp_fmt_error 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci .global b1238_fix 16762306a36Sopenharmony_cib1238_fix: 16862306a36Sopenharmony_ci| 16962306a36Sopenharmony_ci| This code is entered only on completion of the handling of an 17062306a36Sopenharmony_ci| nu-generated ovfl, unfl, or inex exception. If the version 17162306a36Sopenharmony_ci| number of the fsave is not $40, this handler is not necessary. 17262306a36Sopenharmony_ci| Simply branch to fix_done and exit normally. 17362306a36Sopenharmony_ci| 17462306a36Sopenharmony_ci cmpib #VER_40,4(%a7) 17562306a36Sopenharmony_ci bne fix_done 17662306a36Sopenharmony_ci| 17762306a36Sopenharmony_ci| Test for cu_savepc equal to zero. If not, this is not a bug 17862306a36Sopenharmony_ci| #1238 case. 17962306a36Sopenharmony_ci| 18062306a36Sopenharmony_ci moveb CU_SAVEPC(%a6),%d0 18162306a36Sopenharmony_ci andib #0xFE,%d0 18262306a36Sopenharmony_ci beq fix_done |if zero, this is not bug #1238 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci| 18562306a36Sopenharmony_ci| Test the register conflict aspect. If opclass0, check for 18662306a36Sopenharmony_ci| cu src equal to xu dest or equal to nu dest. If so, go to 18762306a36Sopenharmony_ci| op0. Else, or if opclass2, check for cu dest equal to 18862306a36Sopenharmony_ci| xu dest or equal to nu dest. If so, go to tst_opcl. Else, 18962306a36Sopenharmony_ci| exit, it is not the bug case. 19062306a36Sopenharmony_ci| 19162306a36Sopenharmony_ci| Check for opclass 0. If not, go and check for opclass 2 and sgl. 19262306a36Sopenharmony_ci| 19362306a36Sopenharmony_ci movew CMDREG1B(%a6),%d0 19462306a36Sopenharmony_ci andiw #0xE000,%d0 |strip all but opclass 19562306a36Sopenharmony_ci bne op2sgl |not opclass 0, check op2 19662306a36Sopenharmony_ci| 19762306a36Sopenharmony_ci| Check for cu and nu register conflict. If one exists, this takes 19862306a36Sopenharmony_ci| priority over a cu and xu conflict. 19962306a36Sopenharmony_ci| 20062306a36Sopenharmony_ci bfextu CMDREG1B(%a6){#3:#3},%d0 |get 1st src 20162306a36Sopenharmony_ci bfextu CMDREG3B(%a6){#6:#3},%d1 |get 3rd dest 20262306a36Sopenharmony_ci cmpb %d0,%d1 20362306a36Sopenharmony_ci beqs op0 |if equal, continue bugfix 20462306a36Sopenharmony_ci| 20562306a36Sopenharmony_ci| Check for cu dest equal to nu dest. If so, go and fix the 20662306a36Sopenharmony_ci| bug condition. Otherwise, exit. 20762306a36Sopenharmony_ci| 20862306a36Sopenharmony_ci bfextu CMDREG1B(%a6){#6:#3},%d0 |get 1st dest 20962306a36Sopenharmony_ci cmpb %d0,%d1 |cmp 1st dest with 3rd dest 21062306a36Sopenharmony_ci beqs op0 |if equal, continue bugfix 21162306a36Sopenharmony_ci| 21262306a36Sopenharmony_ci| Check for cu and xu register conflict. 21362306a36Sopenharmony_ci| 21462306a36Sopenharmony_ci bfextu CMDREG2B(%a6){#6:#3},%d1 |get 2nd dest 21562306a36Sopenharmony_ci cmpb %d0,%d1 |cmp 1st dest with 2nd dest 21662306a36Sopenharmony_ci beqs op0_xu |if equal, continue bugfix 21762306a36Sopenharmony_ci bfextu CMDREG1B(%a6){#3:#3},%d0 |get 1st src 21862306a36Sopenharmony_ci cmpb %d0,%d1 |cmp 1st src with 2nd dest 21962306a36Sopenharmony_ci beq op0_xu 22062306a36Sopenharmony_ci bne fix_done |if the reg checks fail, exit 22162306a36Sopenharmony_ci| 22262306a36Sopenharmony_ci| We have the opclass 0 situation. 22362306a36Sopenharmony_ci| 22462306a36Sopenharmony_ciop0: 22562306a36Sopenharmony_ci bfextu CMDREG1B(%a6){#3:#3},%d0 |get source register no 22662306a36Sopenharmony_ci movel #7,%d1 22762306a36Sopenharmony_ci subl %d0,%d1 22862306a36Sopenharmony_ci clrl %d0 22962306a36Sopenharmony_ci bsetl %d1,%d0 23062306a36Sopenharmony_ci fmovemx %d0,ETEMP(%a6) |load source to ETEMP 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci moveb #0x12,%d0 23362306a36Sopenharmony_ci bfins %d0,CMDREG1B(%a6){#0:#6} |opclass 2, extended 23462306a36Sopenharmony_ci| 23562306a36Sopenharmony_ci| Set ETEMP exponent bit 15 as the opposite of ete14 23662306a36Sopenharmony_ci| 23762306a36Sopenharmony_ci btst #6,ETEMP_EX(%a6) |check etemp exponent bit 14 23862306a36Sopenharmony_ci beq setete15 23962306a36Sopenharmony_ci bclr #etemp15_bit,STAG(%a6) 24062306a36Sopenharmony_ci bra finish 24162306a36Sopenharmony_cisetete15: 24262306a36Sopenharmony_ci bset #etemp15_bit,STAG(%a6) 24362306a36Sopenharmony_ci bra finish 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci| 24662306a36Sopenharmony_ci| We have the case in which a conflict exists between the cu src or 24762306a36Sopenharmony_ci| dest and the dest of the xu. We must clear the instruction in 24862306a36Sopenharmony_ci| the cu and restore the state, allowing the instruction in the 24962306a36Sopenharmony_ci| xu to complete. Remember, the instruction in the nu 25062306a36Sopenharmony_ci| was exceptional, and was completed by the appropriate handler. 25162306a36Sopenharmony_ci| If the result of the xu instruction is not exceptional, we can 25262306a36Sopenharmony_ci| restore the instruction from the cu to the frame and continue 25362306a36Sopenharmony_ci| processing the original exception. If the result is also 25462306a36Sopenharmony_ci| exceptional, we choose to kill the process. 25562306a36Sopenharmony_ci| 25662306a36Sopenharmony_ci| Items saved from the stack: 25762306a36Sopenharmony_ci| 25862306a36Sopenharmony_ci| $3c stag - L_SCR1 25962306a36Sopenharmony_ci| $40 cmdreg1b - L_SCR2 26062306a36Sopenharmony_ci| $44 dtag - L_SCR3 26162306a36Sopenharmony_ci| 26262306a36Sopenharmony_ci| The cu savepc is set to zero, and the frame is restored to the 26362306a36Sopenharmony_ci| fpu. 26462306a36Sopenharmony_ci| 26562306a36Sopenharmony_ciop0_xu: 26662306a36Sopenharmony_ci movel STAG(%a6),L_SCR1(%a6) 26762306a36Sopenharmony_ci movel CMDREG1B(%a6),L_SCR2(%a6) 26862306a36Sopenharmony_ci movel DTAG(%a6),L_SCR3(%a6) 26962306a36Sopenharmony_ci andil #0xe0000000,L_SCR3(%a6) 27062306a36Sopenharmony_ci moveb #0,CU_SAVEPC(%a6) 27162306a36Sopenharmony_ci movel (%a7)+,%d1 |save return address from bsr 27262306a36Sopenharmony_ci frestore (%a7)+ 27362306a36Sopenharmony_ci fsave -(%a7) 27462306a36Sopenharmony_ci| 27562306a36Sopenharmony_ci| Check if the instruction which just completed was exceptional. 27662306a36Sopenharmony_ci| 27762306a36Sopenharmony_ci cmpw #0x4060,(%a7) 27862306a36Sopenharmony_ci beq op0_xb 27962306a36Sopenharmony_ci| 28062306a36Sopenharmony_ci| It is necessary to isolate the result of the instruction in the 28162306a36Sopenharmony_ci| xu if it is to fp0 - fp3 and write that value to the USER_FPn 28262306a36Sopenharmony_ci| locations on the stack. The correct destination register is in 28362306a36Sopenharmony_ci| cmdreg2b. 28462306a36Sopenharmony_ci| 28562306a36Sopenharmony_ci bfextu CMDREG2B(%a6){#6:#3},%d0 |get dest register no 28662306a36Sopenharmony_ci cmpil #3,%d0 28762306a36Sopenharmony_ci bgts op0_xi 28862306a36Sopenharmony_ci beqs op0_fp3 28962306a36Sopenharmony_ci cmpil #1,%d0 29062306a36Sopenharmony_ci blts op0_fp0 29162306a36Sopenharmony_ci beqs op0_fp1 29262306a36Sopenharmony_ciop0_fp2: 29362306a36Sopenharmony_ci fmovemx %fp2-%fp2,USER_FP2(%a6) 29462306a36Sopenharmony_ci bras op0_xi 29562306a36Sopenharmony_ciop0_fp1: 29662306a36Sopenharmony_ci fmovemx %fp1-%fp1,USER_FP1(%a6) 29762306a36Sopenharmony_ci bras op0_xi 29862306a36Sopenharmony_ciop0_fp0: 29962306a36Sopenharmony_ci fmovemx %fp0-%fp0,USER_FP0(%a6) 30062306a36Sopenharmony_ci bras op0_xi 30162306a36Sopenharmony_ciop0_fp3: 30262306a36Sopenharmony_ci fmovemx %fp3-%fp3,USER_FP3(%a6) 30362306a36Sopenharmony_ci| 30462306a36Sopenharmony_ci| The frame returned is idle. We must build a busy frame to hold 30562306a36Sopenharmony_ci| the cu state information and setup etemp. 30662306a36Sopenharmony_ci| 30762306a36Sopenharmony_ciop0_xi: 30862306a36Sopenharmony_ci movel #22,%d0 |clear 23 lwords 30962306a36Sopenharmony_ci clrl (%a7) 31062306a36Sopenharmony_ciop0_loop: 31162306a36Sopenharmony_ci clrl -(%a7) 31262306a36Sopenharmony_ci dbf %d0,op0_loop 31362306a36Sopenharmony_ci movel #0x40600000,-(%a7) 31462306a36Sopenharmony_ci movel L_SCR1(%a6),STAG(%a6) 31562306a36Sopenharmony_ci movel L_SCR2(%a6),CMDREG1B(%a6) 31662306a36Sopenharmony_ci movel L_SCR3(%a6),DTAG(%a6) 31762306a36Sopenharmony_ci moveb #0x6,CU_SAVEPC(%a6) 31862306a36Sopenharmony_ci movel %d1,-(%a7) |return bsr return address 31962306a36Sopenharmony_ci bfextu CMDREG1B(%a6){#3:#3},%d0 |get source register no 32062306a36Sopenharmony_ci movel #7,%d1 32162306a36Sopenharmony_ci subl %d0,%d1 32262306a36Sopenharmony_ci clrl %d0 32362306a36Sopenharmony_ci bsetl %d1,%d0 32462306a36Sopenharmony_ci fmovemx %d0,ETEMP(%a6) |load source to ETEMP 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci moveb #0x12,%d0 32762306a36Sopenharmony_ci bfins %d0,CMDREG1B(%a6){#0:#6} |opclass 2, extended 32862306a36Sopenharmony_ci| 32962306a36Sopenharmony_ci| Set ETEMP exponent bit 15 as the opposite of ete14 33062306a36Sopenharmony_ci| 33162306a36Sopenharmony_ci btst #6,ETEMP_EX(%a6) |check etemp exponent bit 14 33262306a36Sopenharmony_ci beq op0_sete15 33362306a36Sopenharmony_ci bclr #etemp15_bit,STAG(%a6) 33462306a36Sopenharmony_ci bra finish 33562306a36Sopenharmony_ciop0_sete15: 33662306a36Sopenharmony_ci bset #etemp15_bit,STAG(%a6) 33762306a36Sopenharmony_ci bra finish 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci| 34062306a36Sopenharmony_ci| The frame returned is busy. It is not possible to reconstruct 34162306a36Sopenharmony_ci| the code sequence to allow completion. We will jump to 34262306a36Sopenharmony_ci| fpsp_fmt_error and allow the kernel to kill the process. 34362306a36Sopenharmony_ci| 34462306a36Sopenharmony_ciop0_xb: 34562306a36Sopenharmony_ci jmp fpsp_fmt_error 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci| 34862306a36Sopenharmony_ci| Check for opclass 2 and single size. If not both, exit. 34962306a36Sopenharmony_ci| 35062306a36Sopenharmony_ciop2sgl: 35162306a36Sopenharmony_ci movew CMDREG1B(%a6),%d0 35262306a36Sopenharmony_ci andiw #0xFC00,%d0 |strip all but opclass and size 35362306a36Sopenharmony_ci cmpiw #0x4400,%d0 |test for opclass 2 and size=sgl 35462306a36Sopenharmony_ci bne fix_done |if not, it is not bug 1238 35562306a36Sopenharmony_ci| 35662306a36Sopenharmony_ci| Check for cu dest equal to nu dest or equal to xu dest, with 35762306a36Sopenharmony_ci| a cu and nu conflict taking priority an nu conflict. If either, 35862306a36Sopenharmony_ci| go and fix the bug condition. Otherwise, exit. 35962306a36Sopenharmony_ci| 36062306a36Sopenharmony_ci bfextu CMDREG1B(%a6){#6:#3},%d0 |get 1st dest 36162306a36Sopenharmony_ci bfextu CMDREG3B(%a6){#6:#3},%d1 |get 3rd dest 36262306a36Sopenharmony_ci cmpb %d0,%d1 |cmp 1st dest with 3rd dest 36362306a36Sopenharmony_ci beq op2_com |if equal, continue bugfix 36462306a36Sopenharmony_ci bfextu CMDREG2B(%a6){#6:#3},%d1 |get 2nd dest 36562306a36Sopenharmony_ci cmpb %d0,%d1 |cmp 1st dest with 2nd dest 36662306a36Sopenharmony_ci bne fix_done |if the reg checks fail, exit 36762306a36Sopenharmony_ci| 36862306a36Sopenharmony_ci| We have the case in which a conflict exists between the cu src or 36962306a36Sopenharmony_ci| dest and the dest of the xu. We must clear the instruction in 37062306a36Sopenharmony_ci| the cu and restore the state, allowing the instruction in the 37162306a36Sopenharmony_ci| xu to complete. Remember, the instruction in the nu 37262306a36Sopenharmony_ci| was exceptional, and was completed by the appropriate handler. 37362306a36Sopenharmony_ci| If the result of the xu instruction is not exceptional, we can 37462306a36Sopenharmony_ci| restore the instruction from the cu to the frame and continue 37562306a36Sopenharmony_ci| processing the original exception. If the result is also 37662306a36Sopenharmony_ci| exceptional, we choose to kill the process. 37762306a36Sopenharmony_ci| 37862306a36Sopenharmony_ci| Items saved from the stack: 37962306a36Sopenharmony_ci| 38062306a36Sopenharmony_ci| $3c stag - L_SCR1 38162306a36Sopenharmony_ci| $40 cmdreg1b - L_SCR2 38262306a36Sopenharmony_ci| $44 dtag - L_SCR3 38362306a36Sopenharmony_ci| etemp - FP_SCR2 38462306a36Sopenharmony_ci| 38562306a36Sopenharmony_ci| The cu savepc is set to zero, and the frame is restored to the 38662306a36Sopenharmony_ci| fpu. 38762306a36Sopenharmony_ci| 38862306a36Sopenharmony_ciop2_xu: 38962306a36Sopenharmony_ci movel STAG(%a6),L_SCR1(%a6) 39062306a36Sopenharmony_ci movel CMDREG1B(%a6),L_SCR2(%a6) 39162306a36Sopenharmony_ci movel DTAG(%a6),L_SCR3(%a6) 39262306a36Sopenharmony_ci andil #0xe0000000,L_SCR3(%a6) 39362306a36Sopenharmony_ci moveb #0,CU_SAVEPC(%a6) 39462306a36Sopenharmony_ci movel ETEMP(%a6),FP_SCR2(%a6) 39562306a36Sopenharmony_ci movel ETEMP_HI(%a6),FP_SCR2+4(%a6) 39662306a36Sopenharmony_ci movel ETEMP_LO(%a6),FP_SCR2+8(%a6) 39762306a36Sopenharmony_ci movel (%a7)+,%d1 |save return address from bsr 39862306a36Sopenharmony_ci frestore (%a7)+ 39962306a36Sopenharmony_ci fsave -(%a7) 40062306a36Sopenharmony_ci| 40162306a36Sopenharmony_ci| Check if the instruction which just completed was exceptional. 40262306a36Sopenharmony_ci| 40362306a36Sopenharmony_ci cmpw #0x4060,(%a7) 40462306a36Sopenharmony_ci beq op2_xb 40562306a36Sopenharmony_ci| 40662306a36Sopenharmony_ci| It is necessary to isolate the result of the instruction in the 40762306a36Sopenharmony_ci| xu if it is to fp0 - fp3 and write that value to the USER_FPn 40862306a36Sopenharmony_ci| locations on the stack. The correct destination register is in 40962306a36Sopenharmony_ci| cmdreg2b. 41062306a36Sopenharmony_ci| 41162306a36Sopenharmony_ci bfextu CMDREG2B(%a6){#6:#3},%d0 |get dest register no 41262306a36Sopenharmony_ci cmpil #3,%d0 41362306a36Sopenharmony_ci bgts op2_xi 41462306a36Sopenharmony_ci beqs op2_fp3 41562306a36Sopenharmony_ci cmpil #1,%d0 41662306a36Sopenharmony_ci blts op2_fp0 41762306a36Sopenharmony_ci beqs op2_fp1 41862306a36Sopenharmony_ciop2_fp2: 41962306a36Sopenharmony_ci fmovemx %fp2-%fp2,USER_FP2(%a6) 42062306a36Sopenharmony_ci bras op2_xi 42162306a36Sopenharmony_ciop2_fp1: 42262306a36Sopenharmony_ci fmovemx %fp1-%fp1,USER_FP1(%a6) 42362306a36Sopenharmony_ci bras op2_xi 42462306a36Sopenharmony_ciop2_fp0: 42562306a36Sopenharmony_ci fmovemx %fp0-%fp0,USER_FP0(%a6) 42662306a36Sopenharmony_ci bras op2_xi 42762306a36Sopenharmony_ciop2_fp3: 42862306a36Sopenharmony_ci fmovemx %fp3-%fp3,USER_FP3(%a6) 42962306a36Sopenharmony_ci| 43062306a36Sopenharmony_ci| The frame returned is idle. We must build a busy frame to hold 43162306a36Sopenharmony_ci| the cu state information and fix up etemp. 43262306a36Sopenharmony_ci| 43362306a36Sopenharmony_ciop2_xi: 43462306a36Sopenharmony_ci movel #22,%d0 |clear 23 lwords 43562306a36Sopenharmony_ci clrl (%a7) 43662306a36Sopenharmony_ciop2_loop: 43762306a36Sopenharmony_ci clrl -(%a7) 43862306a36Sopenharmony_ci dbf %d0,op2_loop 43962306a36Sopenharmony_ci movel #0x40600000,-(%a7) 44062306a36Sopenharmony_ci movel L_SCR1(%a6),STAG(%a6) 44162306a36Sopenharmony_ci movel L_SCR2(%a6),CMDREG1B(%a6) 44262306a36Sopenharmony_ci movel L_SCR3(%a6),DTAG(%a6) 44362306a36Sopenharmony_ci moveb #0x6,CU_SAVEPC(%a6) 44462306a36Sopenharmony_ci movel FP_SCR2(%a6),ETEMP(%a6) 44562306a36Sopenharmony_ci movel FP_SCR2+4(%a6),ETEMP_HI(%a6) 44662306a36Sopenharmony_ci movel FP_SCR2+8(%a6),ETEMP_LO(%a6) 44762306a36Sopenharmony_ci movel %d1,-(%a7) 44862306a36Sopenharmony_ci bra op2_com 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci| 45162306a36Sopenharmony_ci| We have the opclass 2 single source situation. 45262306a36Sopenharmony_ci| 45362306a36Sopenharmony_ciop2_com: 45462306a36Sopenharmony_ci moveb #0x15,%d0 45562306a36Sopenharmony_ci bfins %d0,CMDREG1B(%a6){#0:#6} |opclass 2, double 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci cmpw #0x407F,ETEMP_EX(%a6) |single +max 45862306a36Sopenharmony_ci bnes case2 45962306a36Sopenharmony_ci movew #0x43FF,ETEMP_EX(%a6) |to double +max 46062306a36Sopenharmony_ci bra finish 46162306a36Sopenharmony_cicase2: 46262306a36Sopenharmony_ci cmpw #0xC07F,ETEMP_EX(%a6) |single -max 46362306a36Sopenharmony_ci bnes case3 46462306a36Sopenharmony_ci movew #0xC3FF,ETEMP_EX(%a6) |to double -max 46562306a36Sopenharmony_ci bra finish 46662306a36Sopenharmony_cicase3: 46762306a36Sopenharmony_ci cmpw #0x3F80,ETEMP_EX(%a6) |single +min 46862306a36Sopenharmony_ci bnes case4 46962306a36Sopenharmony_ci movew #0x3C00,ETEMP_EX(%a6) |to double +min 47062306a36Sopenharmony_ci bra finish 47162306a36Sopenharmony_cicase4: 47262306a36Sopenharmony_ci cmpw #0xBF80,ETEMP_EX(%a6) |single -min 47362306a36Sopenharmony_ci bne fix_done 47462306a36Sopenharmony_ci movew #0xBC00,ETEMP_EX(%a6) |to double -min 47562306a36Sopenharmony_ci bra finish 47662306a36Sopenharmony_ci| 47762306a36Sopenharmony_ci| The frame returned is busy. It is not possible to reconstruct 47862306a36Sopenharmony_ci| the code sequence to allow completion. fpsp_fmt_error causes 47962306a36Sopenharmony_ci| an fline illegal instruction to be executed. 48062306a36Sopenharmony_ci| 48162306a36Sopenharmony_ci| You should replace the jump to fpsp_fmt_error with a jump 48262306a36Sopenharmony_ci| to the entry point used to kill a process. 48362306a36Sopenharmony_ci| 48462306a36Sopenharmony_ciop2_xb: 48562306a36Sopenharmony_ci jmp fpsp_fmt_error 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci| 48862306a36Sopenharmony_ci| Enter here if the case is not of the situations affected by 48962306a36Sopenharmony_ci| bug #1238, or if the fix is completed, and exit. 49062306a36Sopenharmony_ci| 49162306a36Sopenharmony_cifinish: 49262306a36Sopenharmony_cifix_done: 49362306a36Sopenharmony_ci rts 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci |end 496