18c2ecf20Sopenharmony_ci| 28c2ecf20Sopenharmony_ci| bugfix.sa 3.2 1/31/91 38c2ecf20Sopenharmony_ci| 48c2ecf20Sopenharmony_ci| 58c2ecf20Sopenharmony_ci| This file contains workarounds for bugs in the 040 68c2ecf20Sopenharmony_ci| relating to the Floating-Point Software Package (FPSP) 78c2ecf20Sopenharmony_ci| 88c2ecf20Sopenharmony_ci| Fixes for bugs: 1238 98c2ecf20Sopenharmony_ci| 108c2ecf20Sopenharmony_ci| Bug: 1238 118c2ecf20Sopenharmony_ci| 128c2ecf20Sopenharmony_ci| 138c2ecf20Sopenharmony_ci| /* The following dirty_bit clear should be left in 148c2ecf20Sopenharmony_ci| * the handler permanently to improve throughput. 158c2ecf20Sopenharmony_ci| * The dirty_bits are located at bits [23:16] in 168c2ecf20Sopenharmony_ci| * longword $08 in the busy frame $4x60. Bit 16 178c2ecf20Sopenharmony_ci| * corresponds to FP0, bit 17 corresponds to FP1, 188c2ecf20Sopenharmony_ci| * and so on. 198c2ecf20Sopenharmony_ci| */ 208c2ecf20Sopenharmony_ci| if (E3_exception_just_serviced) { 218c2ecf20Sopenharmony_ci| dirty_bit[cmdreg3b[9:7]] = 0; 228c2ecf20Sopenharmony_ci| } 238c2ecf20Sopenharmony_ci| 248c2ecf20Sopenharmony_ci| if (fsave_format_version != $40) {goto NOFIX} 258c2ecf20Sopenharmony_ci| 268c2ecf20Sopenharmony_ci| if !(E3_exception_just_serviced) {goto NOFIX} 278c2ecf20Sopenharmony_ci| if (cupc == 0000000) {goto NOFIX} 288c2ecf20Sopenharmony_ci| if ((cmdreg1b[15:13] != 000) && 298c2ecf20Sopenharmony_ci| (cmdreg1b[15:10] != 010001)) {goto NOFIX} 308c2ecf20Sopenharmony_ci| if (((cmdreg1b[15:13] != 000) || ((cmdreg1b[12:10] != cmdreg2b[9:7]) && 318c2ecf20Sopenharmony_ci| (cmdreg1b[12:10] != cmdreg3b[9:7])) ) && 328c2ecf20Sopenharmony_ci| ((cmdreg1b[ 9: 7] != cmdreg2b[9:7]) && 338c2ecf20Sopenharmony_ci| (cmdreg1b[ 9: 7] != cmdreg3b[9:7])) ) {goto NOFIX} 348c2ecf20Sopenharmony_ci| 358c2ecf20Sopenharmony_ci| /* Note: for 6d43b or 8d43b, you may want to add the following code 368c2ecf20Sopenharmony_ci| * to get better coverage. (If you do not insert this code, the part 378c2ecf20Sopenharmony_ci| * won't lock up; it will simply get the wrong answer.) 388c2ecf20Sopenharmony_ci| * Do NOT insert this code for 10d43b or later parts. 398c2ecf20Sopenharmony_ci| * 408c2ecf20Sopenharmony_ci| * if (fpiarcu == integer stack return address) { 418c2ecf20Sopenharmony_ci| * cupc = 0000000; 428c2ecf20Sopenharmony_ci| * goto NOFIX; 438c2ecf20Sopenharmony_ci| * } 448c2ecf20Sopenharmony_ci| */ 458c2ecf20Sopenharmony_ci| 468c2ecf20Sopenharmony_ci| if (cmdreg1b[15:13] != 000) {goto FIX_OPCLASS2} 478c2ecf20Sopenharmony_ci| FIX_OPCLASS0: 488c2ecf20Sopenharmony_ci| if (((cmdreg1b[12:10] == cmdreg2b[9:7]) || 498c2ecf20Sopenharmony_ci| (cmdreg1b[ 9: 7] == cmdreg2b[9:7])) && 508c2ecf20Sopenharmony_ci| (cmdreg1b[12:10] != cmdreg3b[9:7]) && 518c2ecf20Sopenharmony_ci| (cmdreg1b[ 9: 7] != cmdreg3b[9:7])) { /* xu conflict only */ 528c2ecf20Sopenharmony_ci| /* We execute the following code if there is an 538c2ecf20Sopenharmony_ci| xu conflict and NOT an nu conflict */ 548c2ecf20Sopenharmony_ci| 558c2ecf20Sopenharmony_ci| /* first save some values on the fsave frame */ 568c2ecf20Sopenharmony_ci| stag_temp = STAG[fsave_frame]; 578c2ecf20Sopenharmony_ci| cmdreg1b_temp = CMDREG1B[fsave_frame]; 588c2ecf20Sopenharmony_ci| dtag_temp = DTAG[fsave_frame]; 598c2ecf20Sopenharmony_ci| ete15_temp = ETE15[fsave_frame]; 608c2ecf20Sopenharmony_ci| 618c2ecf20Sopenharmony_ci| CUPC[fsave_frame] = 0000000; 628c2ecf20Sopenharmony_ci| FRESTORE 638c2ecf20Sopenharmony_ci| FSAVE 648c2ecf20Sopenharmony_ci| 658c2ecf20Sopenharmony_ci| /* If the xu instruction is exceptional, we punt. 668c2ecf20Sopenharmony_ci| * Otherwise, we would have to include OVFL/UNFL handler 678c2ecf20Sopenharmony_ci| * code here to get the correct answer. 688c2ecf20Sopenharmony_ci| */ 698c2ecf20Sopenharmony_ci| if (fsave_frame_format == $4060) {goto KILL_PROCESS} 708c2ecf20Sopenharmony_ci| 718c2ecf20Sopenharmony_ci| fsave_frame = /* build a long frame of all zeros */ 728c2ecf20Sopenharmony_ci| fsave_frame_format = $4060; /* label it as long frame */ 738c2ecf20Sopenharmony_ci| 748c2ecf20Sopenharmony_ci| /* load it with the temps we saved */ 758c2ecf20Sopenharmony_ci| STAG[fsave_frame] = stag_temp; 768c2ecf20Sopenharmony_ci| CMDREG1B[fsave_frame] = cmdreg1b_temp; 778c2ecf20Sopenharmony_ci| DTAG[fsave_frame] = dtag_temp; 788c2ecf20Sopenharmony_ci| ETE15[fsave_frame] = ete15_temp; 798c2ecf20Sopenharmony_ci| 808c2ecf20Sopenharmony_ci| /* Make sure that the cmdreg3b dest reg is not going to 818c2ecf20Sopenharmony_ci| * be destroyed by a FMOVEM at the end of all this code. 828c2ecf20Sopenharmony_ci| * If it is, you should move the current value of the reg 838c2ecf20Sopenharmony_ci| * onto the stack so that the reg will loaded with that value. 848c2ecf20Sopenharmony_ci| */ 858c2ecf20Sopenharmony_ci| 868c2ecf20Sopenharmony_ci| /* All done. Proceed with the code below */ 878c2ecf20Sopenharmony_ci| } 888c2ecf20Sopenharmony_ci| 898c2ecf20Sopenharmony_ci| etemp = FP_reg_[cmdreg1b[12:10]]; 908c2ecf20Sopenharmony_ci| ete15 = ~ete14; 918c2ecf20Sopenharmony_ci| cmdreg1b[15:10] = 010010; 928c2ecf20Sopenharmony_ci| clear(bug_flag_procIDxxxx); 938c2ecf20Sopenharmony_ci| FRESTORE and return; 948c2ecf20Sopenharmony_ci| 958c2ecf20Sopenharmony_ci| 968c2ecf20Sopenharmony_ci| FIX_OPCLASS2: 978c2ecf20Sopenharmony_ci| if ((cmdreg1b[9:7] == cmdreg2b[9:7]) && 988c2ecf20Sopenharmony_ci| (cmdreg1b[9:7] != cmdreg3b[9:7])) { /* xu conflict only */ 998c2ecf20Sopenharmony_ci| /* We execute the following code if there is an 1008c2ecf20Sopenharmony_ci| xu conflict and NOT an nu conflict */ 1018c2ecf20Sopenharmony_ci| 1028c2ecf20Sopenharmony_ci| /* first save some values on the fsave frame */ 1038c2ecf20Sopenharmony_ci| stag_temp = STAG[fsave_frame]; 1048c2ecf20Sopenharmony_ci| cmdreg1b_temp = CMDREG1B[fsave_frame]; 1058c2ecf20Sopenharmony_ci| dtag_temp = DTAG[fsave_frame]; 1068c2ecf20Sopenharmony_ci| ete15_temp = ETE15[fsave_frame]; 1078c2ecf20Sopenharmony_ci| etemp_temp = ETEMP[fsave_frame]; 1088c2ecf20Sopenharmony_ci| 1098c2ecf20Sopenharmony_ci| CUPC[fsave_frame] = 0000000; 1108c2ecf20Sopenharmony_ci| FRESTORE 1118c2ecf20Sopenharmony_ci| FSAVE 1128c2ecf20Sopenharmony_ci| 1138c2ecf20Sopenharmony_ci| 1148c2ecf20Sopenharmony_ci| /* If the xu instruction is exceptional, we punt. 1158c2ecf20Sopenharmony_ci| * Otherwise, we would have to include OVFL/UNFL handler 1168c2ecf20Sopenharmony_ci| * code here to get the correct answer. 1178c2ecf20Sopenharmony_ci| */ 1188c2ecf20Sopenharmony_ci| if (fsave_frame_format == $4060) {goto KILL_PROCESS} 1198c2ecf20Sopenharmony_ci| 1208c2ecf20Sopenharmony_ci| fsave_frame = /* build a long frame of all zeros */ 1218c2ecf20Sopenharmony_ci| fsave_frame_format = $4060; /* label it as long frame */ 1228c2ecf20Sopenharmony_ci| 1238c2ecf20Sopenharmony_ci| /* load it with the temps we saved */ 1248c2ecf20Sopenharmony_ci| STAG[fsave_frame] = stag_temp; 1258c2ecf20Sopenharmony_ci| CMDREG1B[fsave_frame] = cmdreg1b_temp; 1268c2ecf20Sopenharmony_ci| DTAG[fsave_frame] = dtag_temp; 1278c2ecf20Sopenharmony_ci| ETE15[fsave_frame] = ete15_temp; 1288c2ecf20Sopenharmony_ci| ETEMP[fsave_frame] = etemp_temp; 1298c2ecf20Sopenharmony_ci| 1308c2ecf20Sopenharmony_ci| /* Make sure that the cmdreg3b dest reg is not going to 1318c2ecf20Sopenharmony_ci| * be destroyed by a FMOVEM at the end of all this code. 1328c2ecf20Sopenharmony_ci| * If it is, you should move the current value of the reg 1338c2ecf20Sopenharmony_ci| * onto the stack so that the reg will loaded with that value. 1348c2ecf20Sopenharmony_ci| */ 1358c2ecf20Sopenharmony_ci| 1368c2ecf20Sopenharmony_ci| /* All done. Proceed with the code below */ 1378c2ecf20Sopenharmony_ci| } 1388c2ecf20Sopenharmony_ci| 1398c2ecf20Sopenharmony_ci| if (etemp_exponent == min_sgl) etemp_exponent = min_dbl; 1408c2ecf20Sopenharmony_ci| if (etemp_exponent == max_sgl) etemp_exponent = max_dbl; 1418c2ecf20Sopenharmony_ci| cmdreg1b[15:10] = 010101; 1428c2ecf20Sopenharmony_ci| clear(bug_flag_procIDxxxx); 1438c2ecf20Sopenharmony_ci| FRESTORE and return; 1448c2ecf20Sopenharmony_ci| 1458c2ecf20Sopenharmony_ci| 1468c2ecf20Sopenharmony_ci| NOFIX: 1478c2ecf20Sopenharmony_ci| clear(bug_flag_procIDxxxx); 1488c2ecf20Sopenharmony_ci| FRESTORE and return; 1498c2ecf20Sopenharmony_ci| 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci| Copyright (C) Motorola, Inc. 1990 1538c2ecf20Sopenharmony_ci| All Rights Reserved 1548c2ecf20Sopenharmony_ci| 1558c2ecf20Sopenharmony_ci| For details on the license for this file, please see the 1568c2ecf20Sopenharmony_ci| file, README, in this same directory. 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci|BUGFIX idnt 2,1 | Motorola 040 Floating Point Software Package 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci |section 8 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci#include "fpsp.h" 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci |xref fpsp_fmt_error 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci .global b1238_fix 1678c2ecf20Sopenharmony_cib1238_fix: 1688c2ecf20Sopenharmony_ci| 1698c2ecf20Sopenharmony_ci| This code is entered only on completion of the handling of an 1708c2ecf20Sopenharmony_ci| nu-generated ovfl, unfl, or inex exception. If the version 1718c2ecf20Sopenharmony_ci| number of the fsave is not $40, this handler is not necessary. 1728c2ecf20Sopenharmony_ci| Simply branch to fix_done and exit normally. 1738c2ecf20Sopenharmony_ci| 1748c2ecf20Sopenharmony_ci cmpib #VER_40,4(%a7) 1758c2ecf20Sopenharmony_ci bne fix_done 1768c2ecf20Sopenharmony_ci| 1778c2ecf20Sopenharmony_ci| Test for cu_savepc equal to zero. If not, this is not a bug 1788c2ecf20Sopenharmony_ci| #1238 case. 1798c2ecf20Sopenharmony_ci| 1808c2ecf20Sopenharmony_ci moveb CU_SAVEPC(%a6),%d0 1818c2ecf20Sopenharmony_ci andib #0xFE,%d0 1828c2ecf20Sopenharmony_ci beq fix_done |if zero, this is not bug #1238 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci| 1858c2ecf20Sopenharmony_ci| Test the register conflict aspect. If opclass0, check for 1868c2ecf20Sopenharmony_ci| cu src equal to xu dest or equal to nu dest. If so, go to 1878c2ecf20Sopenharmony_ci| op0. Else, or if opclass2, check for cu dest equal to 1888c2ecf20Sopenharmony_ci| xu dest or equal to nu dest. If so, go to tst_opcl. Else, 1898c2ecf20Sopenharmony_ci| exit, it is not the bug case. 1908c2ecf20Sopenharmony_ci| 1918c2ecf20Sopenharmony_ci| Check for opclass 0. If not, go and check for opclass 2 and sgl. 1928c2ecf20Sopenharmony_ci| 1938c2ecf20Sopenharmony_ci movew CMDREG1B(%a6),%d0 1948c2ecf20Sopenharmony_ci andiw #0xE000,%d0 |strip all but opclass 1958c2ecf20Sopenharmony_ci bne op2sgl |not opclass 0, check op2 1968c2ecf20Sopenharmony_ci| 1978c2ecf20Sopenharmony_ci| Check for cu and nu register conflict. If one exists, this takes 1988c2ecf20Sopenharmony_ci| priority over a cu and xu conflict. 1998c2ecf20Sopenharmony_ci| 2008c2ecf20Sopenharmony_ci bfextu CMDREG1B(%a6){#3:#3},%d0 |get 1st src 2018c2ecf20Sopenharmony_ci bfextu CMDREG3B(%a6){#6:#3},%d1 |get 3rd dest 2028c2ecf20Sopenharmony_ci cmpb %d0,%d1 2038c2ecf20Sopenharmony_ci beqs op0 |if equal, continue bugfix 2048c2ecf20Sopenharmony_ci| 2058c2ecf20Sopenharmony_ci| Check for cu dest equal to nu dest. If so, go and fix the 2068c2ecf20Sopenharmony_ci| bug condition. Otherwise, exit. 2078c2ecf20Sopenharmony_ci| 2088c2ecf20Sopenharmony_ci bfextu CMDREG1B(%a6){#6:#3},%d0 |get 1st dest 2098c2ecf20Sopenharmony_ci cmpb %d0,%d1 |cmp 1st dest with 3rd dest 2108c2ecf20Sopenharmony_ci beqs op0 |if equal, continue bugfix 2118c2ecf20Sopenharmony_ci| 2128c2ecf20Sopenharmony_ci| Check for cu and xu register conflict. 2138c2ecf20Sopenharmony_ci| 2148c2ecf20Sopenharmony_ci bfextu CMDREG2B(%a6){#6:#3},%d1 |get 2nd dest 2158c2ecf20Sopenharmony_ci cmpb %d0,%d1 |cmp 1st dest with 2nd dest 2168c2ecf20Sopenharmony_ci beqs op0_xu |if equal, continue bugfix 2178c2ecf20Sopenharmony_ci bfextu CMDREG1B(%a6){#3:#3},%d0 |get 1st src 2188c2ecf20Sopenharmony_ci cmpb %d0,%d1 |cmp 1st src with 2nd dest 2198c2ecf20Sopenharmony_ci beq op0_xu 2208c2ecf20Sopenharmony_ci bne fix_done |if the reg checks fail, exit 2218c2ecf20Sopenharmony_ci| 2228c2ecf20Sopenharmony_ci| We have the opclass 0 situation. 2238c2ecf20Sopenharmony_ci| 2248c2ecf20Sopenharmony_ciop0: 2258c2ecf20Sopenharmony_ci bfextu CMDREG1B(%a6){#3:#3},%d0 |get source register no 2268c2ecf20Sopenharmony_ci movel #7,%d1 2278c2ecf20Sopenharmony_ci subl %d0,%d1 2288c2ecf20Sopenharmony_ci clrl %d0 2298c2ecf20Sopenharmony_ci bsetl %d1,%d0 2308c2ecf20Sopenharmony_ci fmovemx %d0,ETEMP(%a6) |load source to ETEMP 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci moveb #0x12,%d0 2338c2ecf20Sopenharmony_ci bfins %d0,CMDREG1B(%a6){#0:#6} |opclass 2, extended 2348c2ecf20Sopenharmony_ci| 2358c2ecf20Sopenharmony_ci| Set ETEMP exponent bit 15 as the opposite of ete14 2368c2ecf20Sopenharmony_ci| 2378c2ecf20Sopenharmony_ci btst #6,ETEMP_EX(%a6) |check etemp exponent bit 14 2388c2ecf20Sopenharmony_ci beq setete15 2398c2ecf20Sopenharmony_ci bclr #etemp15_bit,STAG(%a6) 2408c2ecf20Sopenharmony_ci bra finish 2418c2ecf20Sopenharmony_cisetete15: 2428c2ecf20Sopenharmony_ci bset #etemp15_bit,STAG(%a6) 2438c2ecf20Sopenharmony_ci bra finish 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci| 2468c2ecf20Sopenharmony_ci| We have the case in which a conflict exists between the cu src or 2478c2ecf20Sopenharmony_ci| dest and the dest of the xu. We must clear the instruction in 2488c2ecf20Sopenharmony_ci| the cu and restore the state, allowing the instruction in the 2498c2ecf20Sopenharmony_ci| xu to complete. Remember, the instruction in the nu 2508c2ecf20Sopenharmony_ci| was exceptional, and was completed by the appropriate handler. 2518c2ecf20Sopenharmony_ci| If the result of the xu instruction is not exceptional, we can 2528c2ecf20Sopenharmony_ci| restore the instruction from the cu to the frame and continue 2538c2ecf20Sopenharmony_ci| processing the original exception. If the result is also 2548c2ecf20Sopenharmony_ci| exceptional, we choose to kill the process. 2558c2ecf20Sopenharmony_ci| 2568c2ecf20Sopenharmony_ci| Items saved from the stack: 2578c2ecf20Sopenharmony_ci| 2588c2ecf20Sopenharmony_ci| $3c stag - L_SCR1 2598c2ecf20Sopenharmony_ci| $40 cmdreg1b - L_SCR2 2608c2ecf20Sopenharmony_ci| $44 dtag - L_SCR3 2618c2ecf20Sopenharmony_ci| 2628c2ecf20Sopenharmony_ci| The cu savepc is set to zero, and the frame is restored to the 2638c2ecf20Sopenharmony_ci| fpu. 2648c2ecf20Sopenharmony_ci| 2658c2ecf20Sopenharmony_ciop0_xu: 2668c2ecf20Sopenharmony_ci movel STAG(%a6),L_SCR1(%a6) 2678c2ecf20Sopenharmony_ci movel CMDREG1B(%a6),L_SCR2(%a6) 2688c2ecf20Sopenharmony_ci movel DTAG(%a6),L_SCR3(%a6) 2698c2ecf20Sopenharmony_ci andil #0xe0000000,L_SCR3(%a6) 2708c2ecf20Sopenharmony_ci moveb #0,CU_SAVEPC(%a6) 2718c2ecf20Sopenharmony_ci movel (%a7)+,%d1 |save return address from bsr 2728c2ecf20Sopenharmony_ci frestore (%a7)+ 2738c2ecf20Sopenharmony_ci fsave -(%a7) 2748c2ecf20Sopenharmony_ci| 2758c2ecf20Sopenharmony_ci| Check if the instruction which just completed was exceptional. 2768c2ecf20Sopenharmony_ci| 2778c2ecf20Sopenharmony_ci cmpw #0x4060,(%a7) 2788c2ecf20Sopenharmony_ci beq op0_xb 2798c2ecf20Sopenharmony_ci| 2808c2ecf20Sopenharmony_ci| It is necessary to isolate the result of the instruction in the 2818c2ecf20Sopenharmony_ci| xu if it is to fp0 - fp3 and write that value to the USER_FPn 2828c2ecf20Sopenharmony_ci| locations on the stack. The correct destination register is in 2838c2ecf20Sopenharmony_ci| cmdreg2b. 2848c2ecf20Sopenharmony_ci| 2858c2ecf20Sopenharmony_ci bfextu CMDREG2B(%a6){#6:#3},%d0 |get dest register no 2868c2ecf20Sopenharmony_ci cmpil #3,%d0 2878c2ecf20Sopenharmony_ci bgts op0_xi 2888c2ecf20Sopenharmony_ci beqs op0_fp3 2898c2ecf20Sopenharmony_ci cmpil #1,%d0 2908c2ecf20Sopenharmony_ci blts op0_fp0 2918c2ecf20Sopenharmony_ci beqs op0_fp1 2928c2ecf20Sopenharmony_ciop0_fp2: 2938c2ecf20Sopenharmony_ci fmovemx %fp2-%fp2,USER_FP2(%a6) 2948c2ecf20Sopenharmony_ci bras op0_xi 2958c2ecf20Sopenharmony_ciop0_fp1: 2968c2ecf20Sopenharmony_ci fmovemx %fp1-%fp1,USER_FP1(%a6) 2978c2ecf20Sopenharmony_ci bras op0_xi 2988c2ecf20Sopenharmony_ciop0_fp0: 2998c2ecf20Sopenharmony_ci fmovemx %fp0-%fp0,USER_FP0(%a6) 3008c2ecf20Sopenharmony_ci bras op0_xi 3018c2ecf20Sopenharmony_ciop0_fp3: 3028c2ecf20Sopenharmony_ci fmovemx %fp3-%fp3,USER_FP3(%a6) 3038c2ecf20Sopenharmony_ci| 3048c2ecf20Sopenharmony_ci| The frame returned is idle. We must build a busy frame to hold 3058c2ecf20Sopenharmony_ci| the cu state information and setup etemp. 3068c2ecf20Sopenharmony_ci| 3078c2ecf20Sopenharmony_ciop0_xi: 3088c2ecf20Sopenharmony_ci movel #22,%d0 |clear 23 lwords 3098c2ecf20Sopenharmony_ci clrl (%a7) 3108c2ecf20Sopenharmony_ciop0_loop: 3118c2ecf20Sopenharmony_ci clrl -(%a7) 3128c2ecf20Sopenharmony_ci dbf %d0,op0_loop 3138c2ecf20Sopenharmony_ci movel #0x40600000,-(%a7) 3148c2ecf20Sopenharmony_ci movel L_SCR1(%a6),STAG(%a6) 3158c2ecf20Sopenharmony_ci movel L_SCR2(%a6),CMDREG1B(%a6) 3168c2ecf20Sopenharmony_ci movel L_SCR3(%a6),DTAG(%a6) 3178c2ecf20Sopenharmony_ci moveb #0x6,CU_SAVEPC(%a6) 3188c2ecf20Sopenharmony_ci movel %d1,-(%a7) |return bsr return address 3198c2ecf20Sopenharmony_ci bfextu CMDREG1B(%a6){#3:#3},%d0 |get source register no 3208c2ecf20Sopenharmony_ci movel #7,%d1 3218c2ecf20Sopenharmony_ci subl %d0,%d1 3228c2ecf20Sopenharmony_ci clrl %d0 3238c2ecf20Sopenharmony_ci bsetl %d1,%d0 3248c2ecf20Sopenharmony_ci fmovemx %d0,ETEMP(%a6) |load source to ETEMP 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci moveb #0x12,%d0 3278c2ecf20Sopenharmony_ci bfins %d0,CMDREG1B(%a6){#0:#6} |opclass 2, extended 3288c2ecf20Sopenharmony_ci| 3298c2ecf20Sopenharmony_ci| Set ETEMP exponent bit 15 as the opposite of ete14 3308c2ecf20Sopenharmony_ci| 3318c2ecf20Sopenharmony_ci btst #6,ETEMP_EX(%a6) |check etemp exponent bit 14 3328c2ecf20Sopenharmony_ci beq op0_sete15 3338c2ecf20Sopenharmony_ci bclr #etemp15_bit,STAG(%a6) 3348c2ecf20Sopenharmony_ci bra finish 3358c2ecf20Sopenharmony_ciop0_sete15: 3368c2ecf20Sopenharmony_ci bset #etemp15_bit,STAG(%a6) 3378c2ecf20Sopenharmony_ci bra finish 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci| 3408c2ecf20Sopenharmony_ci| The frame returned is busy. It is not possible to reconstruct 3418c2ecf20Sopenharmony_ci| the code sequence to allow completion. We will jump to 3428c2ecf20Sopenharmony_ci| fpsp_fmt_error and allow the kernel to kill the process. 3438c2ecf20Sopenharmony_ci| 3448c2ecf20Sopenharmony_ciop0_xb: 3458c2ecf20Sopenharmony_ci jmp fpsp_fmt_error 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci| 3488c2ecf20Sopenharmony_ci| Check for opclass 2 and single size. If not both, exit. 3498c2ecf20Sopenharmony_ci| 3508c2ecf20Sopenharmony_ciop2sgl: 3518c2ecf20Sopenharmony_ci movew CMDREG1B(%a6),%d0 3528c2ecf20Sopenharmony_ci andiw #0xFC00,%d0 |strip all but opclass and size 3538c2ecf20Sopenharmony_ci cmpiw #0x4400,%d0 |test for opclass 2 and size=sgl 3548c2ecf20Sopenharmony_ci bne fix_done |if not, it is not bug 1238 3558c2ecf20Sopenharmony_ci| 3568c2ecf20Sopenharmony_ci| Check for cu dest equal to nu dest or equal to xu dest, with 3578c2ecf20Sopenharmony_ci| a cu and nu conflict taking priority an nu conflict. If either, 3588c2ecf20Sopenharmony_ci| go and fix the bug condition. Otherwise, exit. 3598c2ecf20Sopenharmony_ci| 3608c2ecf20Sopenharmony_ci bfextu CMDREG1B(%a6){#6:#3},%d0 |get 1st dest 3618c2ecf20Sopenharmony_ci bfextu CMDREG3B(%a6){#6:#3},%d1 |get 3rd dest 3628c2ecf20Sopenharmony_ci cmpb %d0,%d1 |cmp 1st dest with 3rd dest 3638c2ecf20Sopenharmony_ci beq op2_com |if equal, continue bugfix 3648c2ecf20Sopenharmony_ci bfextu CMDREG2B(%a6){#6:#3},%d1 |get 2nd dest 3658c2ecf20Sopenharmony_ci cmpb %d0,%d1 |cmp 1st dest with 2nd dest 3668c2ecf20Sopenharmony_ci bne fix_done |if the reg checks fail, exit 3678c2ecf20Sopenharmony_ci| 3688c2ecf20Sopenharmony_ci| We have the case in which a conflict exists between the cu src or 3698c2ecf20Sopenharmony_ci| dest and the dest of the xu. We must clear the instruction in 3708c2ecf20Sopenharmony_ci| the cu and restore the state, allowing the instruction in the 3718c2ecf20Sopenharmony_ci| xu to complete. Remember, the instruction in the nu 3728c2ecf20Sopenharmony_ci| was exceptional, and was completed by the appropriate handler. 3738c2ecf20Sopenharmony_ci| If the result of the xu instruction is not exceptional, we can 3748c2ecf20Sopenharmony_ci| restore the instruction from the cu to the frame and continue 3758c2ecf20Sopenharmony_ci| processing the original exception. If the result is also 3768c2ecf20Sopenharmony_ci| exceptional, we choose to kill the process. 3778c2ecf20Sopenharmony_ci| 3788c2ecf20Sopenharmony_ci| Items saved from the stack: 3798c2ecf20Sopenharmony_ci| 3808c2ecf20Sopenharmony_ci| $3c stag - L_SCR1 3818c2ecf20Sopenharmony_ci| $40 cmdreg1b - L_SCR2 3828c2ecf20Sopenharmony_ci| $44 dtag - L_SCR3 3838c2ecf20Sopenharmony_ci| etemp - FP_SCR2 3848c2ecf20Sopenharmony_ci| 3858c2ecf20Sopenharmony_ci| The cu savepc is set to zero, and the frame is restored to the 3868c2ecf20Sopenharmony_ci| fpu. 3878c2ecf20Sopenharmony_ci| 3888c2ecf20Sopenharmony_ciop2_xu: 3898c2ecf20Sopenharmony_ci movel STAG(%a6),L_SCR1(%a6) 3908c2ecf20Sopenharmony_ci movel CMDREG1B(%a6),L_SCR2(%a6) 3918c2ecf20Sopenharmony_ci movel DTAG(%a6),L_SCR3(%a6) 3928c2ecf20Sopenharmony_ci andil #0xe0000000,L_SCR3(%a6) 3938c2ecf20Sopenharmony_ci moveb #0,CU_SAVEPC(%a6) 3948c2ecf20Sopenharmony_ci movel ETEMP(%a6),FP_SCR2(%a6) 3958c2ecf20Sopenharmony_ci movel ETEMP_HI(%a6),FP_SCR2+4(%a6) 3968c2ecf20Sopenharmony_ci movel ETEMP_LO(%a6),FP_SCR2+8(%a6) 3978c2ecf20Sopenharmony_ci movel (%a7)+,%d1 |save return address from bsr 3988c2ecf20Sopenharmony_ci frestore (%a7)+ 3998c2ecf20Sopenharmony_ci fsave -(%a7) 4008c2ecf20Sopenharmony_ci| 4018c2ecf20Sopenharmony_ci| Check if the instruction which just completed was exceptional. 4028c2ecf20Sopenharmony_ci| 4038c2ecf20Sopenharmony_ci cmpw #0x4060,(%a7) 4048c2ecf20Sopenharmony_ci beq op2_xb 4058c2ecf20Sopenharmony_ci| 4068c2ecf20Sopenharmony_ci| It is necessary to isolate the result of the instruction in the 4078c2ecf20Sopenharmony_ci| xu if it is to fp0 - fp3 and write that value to the USER_FPn 4088c2ecf20Sopenharmony_ci| locations on the stack. The correct destination register is in 4098c2ecf20Sopenharmony_ci| cmdreg2b. 4108c2ecf20Sopenharmony_ci| 4118c2ecf20Sopenharmony_ci bfextu CMDREG2B(%a6){#6:#3},%d0 |get dest register no 4128c2ecf20Sopenharmony_ci cmpil #3,%d0 4138c2ecf20Sopenharmony_ci bgts op2_xi 4148c2ecf20Sopenharmony_ci beqs op2_fp3 4158c2ecf20Sopenharmony_ci cmpil #1,%d0 4168c2ecf20Sopenharmony_ci blts op2_fp0 4178c2ecf20Sopenharmony_ci beqs op2_fp1 4188c2ecf20Sopenharmony_ciop2_fp2: 4198c2ecf20Sopenharmony_ci fmovemx %fp2-%fp2,USER_FP2(%a6) 4208c2ecf20Sopenharmony_ci bras op2_xi 4218c2ecf20Sopenharmony_ciop2_fp1: 4228c2ecf20Sopenharmony_ci fmovemx %fp1-%fp1,USER_FP1(%a6) 4238c2ecf20Sopenharmony_ci bras op2_xi 4248c2ecf20Sopenharmony_ciop2_fp0: 4258c2ecf20Sopenharmony_ci fmovemx %fp0-%fp0,USER_FP0(%a6) 4268c2ecf20Sopenharmony_ci bras op2_xi 4278c2ecf20Sopenharmony_ciop2_fp3: 4288c2ecf20Sopenharmony_ci fmovemx %fp3-%fp3,USER_FP3(%a6) 4298c2ecf20Sopenharmony_ci| 4308c2ecf20Sopenharmony_ci| The frame returned is idle. We must build a busy frame to hold 4318c2ecf20Sopenharmony_ci| the cu state information and fix up etemp. 4328c2ecf20Sopenharmony_ci| 4338c2ecf20Sopenharmony_ciop2_xi: 4348c2ecf20Sopenharmony_ci movel #22,%d0 |clear 23 lwords 4358c2ecf20Sopenharmony_ci clrl (%a7) 4368c2ecf20Sopenharmony_ciop2_loop: 4378c2ecf20Sopenharmony_ci clrl -(%a7) 4388c2ecf20Sopenharmony_ci dbf %d0,op2_loop 4398c2ecf20Sopenharmony_ci movel #0x40600000,-(%a7) 4408c2ecf20Sopenharmony_ci movel L_SCR1(%a6),STAG(%a6) 4418c2ecf20Sopenharmony_ci movel L_SCR2(%a6),CMDREG1B(%a6) 4428c2ecf20Sopenharmony_ci movel L_SCR3(%a6),DTAG(%a6) 4438c2ecf20Sopenharmony_ci moveb #0x6,CU_SAVEPC(%a6) 4448c2ecf20Sopenharmony_ci movel FP_SCR2(%a6),ETEMP(%a6) 4458c2ecf20Sopenharmony_ci movel FP_SCR2+4(%a6),ETEMP_HI(%a6) 4468c2ecf20Sopenharmony_ci movel FP_SCR2+8(%a6),ETEMP_LO(%a6) 4478c2ecf20Sopenharmony_ci movel %d1,-(%a7) 4488c2ecf20Sopenharmony_ci bra op2_com 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci| 4518c2ecf20Sopenharmony_ci| We have the opclass 2 single source situation. 4528c2ecf20Sopenharmony_ci| 4538c2ecf20Sopenharmony_ciop2_com: 4548c2ecf20Sopenharmony_ci moveb #0x15,%d0 4558c2ecf20Sopenharmony_ci bfins %d0,CMDREG1B(%a6){#0:#6} |opclass 2, double 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci cmpw #0x407F,ETEMP_EX(%a6) |single +max 4588c2ecf20Sopenharmony_ci bnes case2 4598c2ecf20Sopenharmony_ci movew #0x43FF,ETEMP_EX(%a6) |to double +max 4608c2ecf20Sopenharmony_ci bra finish 4618c2ecf20Sopenharmony_cicase2: 4628c2ecf20Sopenharmony_ci cmpw #0xC07F,ETEMP_EX(%a6) |single -max 4638c2ecf20Sopenharmony_ci bnes case3 4648c2ecf20Sopenharmony_ci movew #0xC3FF,ETEMP_EX(%a6) |to double -max 4658c2ecf20Sopenharmony_ci bra finish 4668c2ecf20Sopenharmony_cicase3: 4678c2ecf20Sopenharmony_ci cmpw #0x3F80,ETEMP_EX(%a6) |single +min 4688c2ecf20Sopenharmony_ci bnes case4 4698c2ecf20Sopenharmony_ci movew #0x3C00,ETEMP_EX(%a6) |to double +min 4708c2ecf20Sopenharmony_ci bra finish 4718c2ecf20Sopenharmony_cicase4: 4728c2ecf20Sopenharmony_ci cmpw #0xBF80,ETEMP_EX(%a6) |single -min 4738c2ecf20Sopenharmony_ci bne fix_done 4748c2ecf20Sopenharmony_ci movew #0xBC00,ETEMP_EX(%a6) |to double -min 4758c2ecf20Sopenharmony_ci bra finish 4768c2ecf20Sopenharmony_ci| 4778c2ecf20Sopenharmony_ci| The frame returned is busy. It is not possible to reconstruct 4788c2ecf20Sopenharmony_ci| the code sequence to allow completion. fpsp_fmt_error causes 4798c2ecf20Sopenharmony_ci| an fline illegal instruction to be executed. 4808c2ecf20Sopenharmony_ci| 4818c2ecf20Sopenharmony_ci| You should replace the jump to fpsp_fmt_error with a jump 4828c2ecf20Sopenharmony_ci| to the entry point used to kill a process. 4838c2ecf20Sopenharmony_ci| 4848c2ecf20Sopenharmony_ciop2_xb: 4858c2ecf20Sopenharmony_ci jmp fpsp_fmt_error 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci| 4888c2ecf20Sopenharmony_ci| Enter here if the case is not of the situations affected by 4898c2ecf20Sopenharmony_ci| bug #1238, or if the fix is completed, and exit. 4908c2ecf20Sopenharmony_ci| 4918c2ecf20Sopenharmony_cifinish: 4928c2ecf20Sopenharmony_cifix_done: 4938c2ecf20Sopenharmony_ci rts 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci |end 496