1 | #include "fpsp-namespace.h" |
---|
2 | // |
---|
3 | // |
---|
4 | // bugfix.sa 3.2 1/31/91 |
---|
5 | // |
---|
6 | // This file contains workarounds for bugs in the 040 |
---|
7 | // relating to the Floating-Point Software Package (FPSP) |
---|
8 | // |
---|
9 | // Fixes for bugs: 1238 |
---|
10 | // |
---|
11 | // Bug: 1238 |
---|
12 | // |
---|
13 | // |
---|
14 | // /* The following dirty_bit clear should be left in |
---|
15 | // * the handler permanently to improve throughput. |
---|
16 | // * The dirty_bits are located at bits [23:16] in |
---|
17 | // * longword $08 in the busy frame $4x60. Bit 16 |
---|
18 | // * corresponds to FP0, bit 17 corresponds to FP1, |
---|
19 | // * and so on. |
---|
20 | // */ |
---|
21 | // if (E3_exception_just_serviced) { |
---|
22 | // dirty_bit[cmdreg3b[9:7]] = 0; |
---|
23 | // } |
---|
24 | // |
---|
25 | // if (fsave_format_version != $40) {goto NOFIX} |
---|
26 | // |
---|
27 | // if !(E3_exception_just_serviced) {goto NOFIX} |
---|
28 | // if (cupc == 0000000) {goto NOFIX} |
---|
29 | // if ((cmdreg1b[15:13] != 000) && |
---|
30 | // (cmdreg1b[15:10] != 010001)) {goto NOFIX} |
---|
31 | // if (((cmdreg1b[15:13] != 000) || ((cmdreg1b[12:10] != cmdreg2b[9:7]) && |
---|
32 | // (cmdreg1b[12:10] != cmdreg3b[9:7])) ) && |
---|
33 | // ((cmdreg1b[ 9: 7] != cmdreg2b[9:7]) && |
---|
34 | // (cmdreg1b[ 9: 7] != cmdreg3b[9:7])) ) {goto NOFIX} |
---|
35 | // |
---|
36 | // /* Note: for 6d43b or 8d43b, you may want to add the following code |
---|
37 | // * to get better coverage. (If you do not insert this code, the part |
---|
38 | // * won't lock up; it will simply get the wrong answer.) |
---|
39 | // * Do NOT insert this code for 10d43b or later parts. |
---|
40 | // * |
---|
41 | // * if (fpiarcu == integer stack return address) { |
---|
42 | // * cupc = 0000000; |
---|
43 | // * goto NOFIX; |
---|
44 | // * } |
---|
45 | // */ |
---|
46 | // |
---|
47 | // if (cmdreg1b[15:13] != 000) {goto FIX_OPCLASS2} |
---|
48 | // FIX_OPCLASS0: |
---|
49 | // if (((cmdreg1b[12:10] == cmdreg2b[9:7]) || |
---|
50 | // (cmdreg1b[ 9: 7] == cmdreg2b[9:7])) && |
---|
51 | // (cmdreg1b[12:10] != cmdreg3b[9:7]) && |
---|
52 | // (cmdreg1b[ 9: 7] != cmdreg3b[9:7])) { /* xu conflict only */ |
---|
53 | // /* We execute the following code if there is an |
---|
54 | // xu conflict and NOT an nu conflict */ |
---|
55 | // |
---|
56 | // /* first save some values on the fsave frame */ |
---|
57 | // stag_temp = STAG[fsave_frame]; |
---|
58 | // cmdreg1b_temp = CMDREG1B[fsave_frame]; |
---|
59 | // dtag_temp = DTAG[fsave_frame]; |
---|
60 | // ete15_temp = ETE15[fsave_frame]; |
---|
61 | // |
---|
62 | // CUPC[fsave_frame] = 0000000; |
---|
63 | // FRESTORE |
---|
64 | // FSAVE |
---|
65 | // |
---|
66 | // /* If the xu instruction is exceptional, we punt. |
---|
67 | // * Otherwise, we would have to include OVFL/UNFL handler |
---|
68 | // * code here to get the correct answer. |
---|
69 | // */ |
---|
70 | // if (fsave_frame_format == $4060) {goto KILL_PROCESS} |
---|
71 | // |
---|
72 | // fsave_frame = /* build a long frame of all zeros */ |
---|
73 | // fsave_frame_format = $4060; /* label it as long frame */ |
---|
74 | // |
---|
75 | // /* load it with the temps we saved */ |
---|
76 | // STAG[fsave_frame] = stag_temp; |
---|
77 | // CMDREG1B[fsave_frame] = cmdreg1b_temp; |
---|
78 | // DTAG[fsave_frame] = dtag_temp; |
---|
79 | // ETE15[fsave_frame] = ete15_temp; |
---|
80 | // |
---|
81 | // /* Make sure that the cmdreg3b dest reg is not going to |
---|
82 | // * be destroyed by a FMOVEM at the end of all this code. |
---|
83 | // * If it is, you should move the current value of the reg |
---|
84 | // * onto the stack so that the reg will loaded with that value. |
---|
85 | // */ |
---|
86 | // |
---|
87 | // /* All done. Proceed with the code below */ |
---|
88 | // } |
---|
89 | // |
---|
90 | // etemp = FP_reg_[cmdreg1b[12:10]]; |
---|
91 | // ete15 = ~ete14; |
---|
92 | // cmdreg1b[15:10] = 010010; |
---|
93 | // clear(bug_flag_procIDxxxx); |
---|
94 | // FRESTORE and return; |
---|
95 | // |
---|
96 | // |
---|
97 | // FIX_OPCLASS2: |
---|
98 | // if ((cmdreg1b[9:7] == cmdreg2b[9:7]) && |
---|
99 | // (cmdreg1b[9:7] != cmdreg3b[9:7])) { /* xu conflict only */ |
---|
100 | // /* We execute the following code if there is an |
---|
101 | // xu conflict and NOT an nu conflict */ |
---|
102 | // |
---|
103 | // /* first save some values on the fsave frame */ |
---|
104 | // stag_temp = STAG[fsave_frame]; |
---|
105 | // cmdreg1b_temp = CMDREG1B[fsave_frame]; |
---|
106 | // dtag_temp = DTAG[fsave_frame]; |
---|
107 | // ete15_temp = ETE15[fsave_frame]; |
---|
108 | // etemp_temp = ETEMP[fsave_frame]; |
---|
109 | // |
---|
110 | // CUPC[fsave_frame] = 0000000; |
---|
111 | // FRESTORE |
---|
112 | // FSAVE |
---|
113 | // |
---|
114 | // |
---|
115 | // /* If the xu instruction is exceptional, we punt. |
---|
116 | // * Otherwise, we would have to include OVFL/UNFL handler |
---|
117 | // * code here to get the correct answer. |
---|
118 | // */ |
---|
119 | // if (fsave_frame_format == $4060) {goto KILL_PROCESS} |
---|
120 | // |
---|
121 | // fsave_frame = /* build a long frame of all zeros */ |
---|
122 | // fsave_frame_format = $4060; /* label it as long frame */ |
---|
123 | // |
---|
124 | // /* load it with the temps we saved */ |
---|
125 | // STAG[fsave_frame] = stag_temp; |
---|
126 | // CMDREG1B[fsave_frame] = cmdreg1b_temp; |
---|
127 | // DTAG[fsave_frame] = dtag_temp; |
---|
128 | // ETE15[fsave_frame] = ete15_temp; |
---|
129 | // ETEMP[fsave_frame] = etemp_temp; |
---|
130 | // |
---|
131 | // /* Make sure that the cmdreg3b dest reg is not going to |
---|
132 | // * be destroyed by a FMOVEM at the end of all this code. |
---|
133 | // * If it is, you should move the current value of the reg |
---|
134 | // * onto the stack so that the reg will loaded with that value. |
---|
135 | // */ |
---|
136 | // |
---|
137 | // /* All done. Proceed with the code below */ |
---|
138 | // } |
---|
139 | // |
---|
140 | // if (etemp_exponent == min_sgl) etemp_exponent = min_dbl; |
---|
141 | // if (etemp_exponent == max_sgl) etemp_exponent = max_dbl; |
---|
142 | // cmdreg1b[15:10] = 010101; |
---|
143 | // clear(bug_flag_procIDxxxx); |
---|
144 | // FRESTORE and return; |
---|
145 | // |
---|
146 | // |
---|
147 | // NOFIX: |
---|
148 | // clear(bug_flag_procIDxxxx); |
---|
149 | // FRESTORE and return; |
---|
150 | // |
---|
151 | |
---|
152 | |
---|
153 | // Copyright (C) Motorola, Inc. 1990 |
---|
154 | // All Rights Reserved |
---|
155 | // |
---|
156 | // THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA |
---|
157 | // The copyright notice above does not evidence any |
---|
158 | // actual or intended publication of such source code. |
---|
159 | |
---|
160 | //BUGFIX idnt 2,1 | Motorola 040 Floating Point Software Package |
---|
161 | |
---|
162 | |section 8 |
---|
163 | |
---|
164 | #include "fpsp.defs" |
---|
165 | |
---|
166 | |xref fpsp_fmt_error |
---|
167 | |
---|
168 | .global b1238_fix |
---|
169 | b1238_fix: |
---|
170 | // |
---|
171 | // This code is entered only on completion of the handling of an |
---|
172 | // nu-generated ovfl, unfl, or inex exception. If the version |
---|
173 | // number of the fsave is not $40, this handler is not necessary. |
---|
174 | // Simply branch to fix_done and exit normally. |
---|
175 | // |
---|
176 | cmpib #VER_40,4(%a7) |
---|
177 | bne fix_done |
---|
178 | // |
---|
179 | // Test for cu_savepc equal to zero. If not, this is not a bug |
---|
180 | // #1238 case. |
---|
181 | // |
---|
182 | moveb CU_SAVEPC(%a6),%d0 |
---|
183 | andib #0xFE,%d0 |
---|
184 | beq fix_done //if zero, this is not bug #1238 |
---|
185 | |
---|
186 | // |
---|
187 | // Test the register conflict aspect. If opclass0, check for |
---|
188 | // cu src equal to xu dest or equal to nu dest. If so, go to |
---|
189 | // op0. Else, or if opclass2, check for cu dest equal to |
---|
190 | // xu dest or equal to nu dest. If so, go to tst_opcl. Else, |
---|
191 | // exit, it is not the bug case. |
---|
192 | // |
---|
193 | // Check for opclass 0. If not, go and check for opclass 2 and sgl. |
---|
194 | // |
---|
195 | movew CMDREG1B(%a6),%d0 |
---|
196 | andiw #0xE000,%d0 //strip all but opclass |
---|
197 | bne op2sgl //not opclass 0, check op2 |
---|
198 | // |
---|
199 | // Check for cu and nu register conflict. If one exists, this takes |
---|
200 | // priority over a cu and xu conflict. |
---|
201 | // |
---|
202 | bfextu CMDREG1B(%a6){#3:#3},%d0 //get 1st src |
---|
203 | bfextu CMDREG3B(%a6){#6:#3},%d1 //get 3rd dest |
---|
204 | cmpb %d0,%d1 |
---|
205 | beqs op0 //if equal, continue bugfix |
---|
206 | // |
---|
207 | // Check for cu dest equal to nu dest. If so, go and fix the |
---|
208 | // bug condition. Otherwise, exit. |
---|
209 | // |
---|
210 | bfextu CMDREG1B(%a6){#6:#3},%d0 //get 1st dest |
---|
211 | cmpb %d0,%d1 //cmp 1st dest with 3rd dest |
---|
212 | beqs op0 //if equal, continue bugfix |
---|
213 | // |
---|
214 | // Check for cu and xu register conflict. |
---|
215 | // |
---|
216 | bfextu CMDREG2B(%a6){#6:#3},%d1 //get 2nd dest |
---|
217 | cmpb %d0,%d1 //cmp 1st dest with 2nd dest |
---|
218 | beqs op0_xu //if equal, continue bugfix |
---|
219 | bfextu CMDREG1B(%a6){#3:#3},%d0 //get 1st src |
---|
220 | cmpb %d0,%d1 //cmp 1st src with 2nd dest |
---|
221 | beq op0_xu |
---|
222 | bne fix_done //if the reg checks fail, exit |
---|
223 | // |
---|
224 | // We have the opclass 0 situation. |
---|
225 | // |
---|
226 | op0: |
---|
227 | bfextu CMDREG1B(%a6){#3:#3},%d0 //get source register no |
---|
228 | movel #7,%d1 |
---|
229 | subl %d0,%d1 |
---|
230 | clrl %d0 |
---|
231 | bsetl %d1,%d0 |
---|
232 | fmovemx %d0,ETEMP(%a6) //load source to ETEMP |
---|
233 | |
---|
234 | moveb #0x12,%d0 |
---|
235 | bfins %d0,CMDREG1B(%a6){#0:#6} //opclass 2, extended |
---|
236 | // |
---|
237 | // Set ETEMP exponent bit 15 as the opposite of ete14 |
---|
238 | // |
---|
239 | btst #6,ETEMP_EX(%a6) //check etemp exponent bit 14 |
---|
240 | beq setete15 |
---|
241 | bclr #etemp15_bit,STAG(%a6) |
---|
242 | bra finish |
---|
243 | setete15: |
---|
244 | bset #etemp15_bit,STAG(%a6) |
---|
245 | bra finish |
---|
246 | |
---|
247 | // |
---|
248 | // We have the case in which a conflict exists between the cu src or |
---|
249 | // dest and the dest of the xu. We must clear the instruction in |
---|
250 | // the cu and restore the state, allowing the instruction in the |
---|
251 | // xu to complete. Remember, the instruction in the nu |
---|
252 | // was exceptional, and was completed by the appropriate handler. |
---|
253 | // If the result of the xu instruction is not exceptional, we can |
---|
254 | // restore the instruction from the cu to the frame and continue |
---|
255 | // processing the original exception. If the result is also |
---|
256 | // exceptional, we choose to kill the process. |
---|
257 | // |
---|
258 | // Items saved from the stack: |
---|
259 | // |
---|
260 | // $3c stag - L_SCR1 |
---|
261 | // $40 cmdreg1b - L_SCR2 |
---|
262 | // $44 dtag - L_SCR3 |
---|
263 | // |
---|
264 | // The cu savepc is set to zero, and the frame is restored to the |
---|
265 | // fpu. |
---|
266 | // |
---|
267 | op0_xu: |
---|
268 | movel STAG(%a6),L_SCR1(%a6) |
---|
269 | movel CMDREG1B(%a6),L_SCR2(%a6) |
---|
270 | movel DTAG(%a6),L_SCR3(%a6) |
---|
271 | andil #0xe0000000,L_SCR3(%a6) |
---|
272 | moveb #0,CU_SAVEPC(%a6) |
---|
273 | movel (%a7)+,%d1 //save return address from bsr |
---|
274 | frestore (%a7)+ |
---|
275 | fsave -(%a7) |
---|
276 | // |
---|
277 | // Check if the instruction which just completed was exceptional. |
---|
278 | // |
---|
279 | cmpw #0x4060,(%a7) |
---|
280 | beq op0_xb |
---|
281 | // |
---|
282 | // It is necessary to isolate the result of the instruction in the |
---|
283 | // xu if it is to fp0 - fp3 and write that value to the USER_FPn |
---|
284 | // locations on the stack. The correct destination register is in |
---|
285 | // cmdreg2b. |
---|
286 | // |
---|
287 | bfextu CMDREG2B(%a6){#6:#3},%d0 //get dest register no |
---|
288 | cmpil #3,%d0 |
---|
289 | bgts op0_xi |
---|
290 | beqs op0_fp3 |
---|
291 | cmpil #1,%d0 |
---|
292 | blts op0_fp0 |
---|
293 | beqs op0_fp1 |
---|
294 | op0_fp2: |
---|
295 | fmovemx %fp2-%fp2,USER_FP2(%a6) |
---|
296 | bras op0_xi |
---|
297 | op0_fp1: |
---|
298 | fmovemx %fp1-%fp1,USER_FP1(%a6) |
---|
299 | bras op0_xi |
---|
300 | op0_fp0: |
---|
301 | fmovemx %fp0-%fp0,USER_FP0(%a6) |
---|
302 | bras op0_xi |
---|
303 | op0_fp3: |
---|
304 | fmovemx %fp3-%fp3,USER_FP3(%a6) |
---|
305 | // |
---|
306 | // The frame returned is idle. We must build a busy frame to hold |
---|
307 | // the cu state information and setup etemp. |
---|
308 | // |
---|
309 | op0_xi: |
---|
310 | movel #22,%d0 //clear 23 lwords |
---|
311 | clrl (%a7) |
---|
312 | op0_loop: |
---|
313 | clrl -(%a7) |
---|
314 | dbf %d0,op0_loop |
---|
315 | movel #0x40600000,-(%a7) |
---|
316 | movel L_SCR1(%a6),STAG(%a6) |
---|
317 | movel L_SCR2(%a6),CMDREG1B(%a6) |
---|
318 | movel L_SCR3(%a6),DTAG(%a6) |
---|
319 | moveb #0x6,CU_SAVEPC(%a6) |
---|
320 | movel %d1,-(%a7) //return bsr return address |
---|
321 | bfextu CMDREG1B(%a6){#3:#3},%d0 //get source register no |
---|
322 | movel #7,%d1 |
---|
323 | subl %d0,%d1 |
---|
324 | clrl %d0 |
---|
325 | bsetl %d1,%d0 |
---|
326 | fmovemx %d0,ETEMP(%a6) //load source to ETEMP |
---|
327 | |
---|
328 | moveb #0x12,%d0 |
---|
329 | bfins %d0,CMDREG1B(%a6){#0:#6} //opclass 2, extended |
---|
330 | // |
---|
331 | // Set ETEMP exponent bit 15 as the opposite of ete14 |
---|
332 | // |
---|
333 | btst #6,ETEMP_EX(%a6) //check etemp exponent bit 14 |
---|
334 | beq op0_sete15 |
---|
335 | bclr #etemp15_bit,STAG(%a6) |
---|
336 | bra finish |
---|
337 | op0_sete15: |
---|
338 | bset #etemp15_bit,STAG(%a6) |
---|
339 | bra finish |
---|
340 | |
---|
341 | // |
---|
342 | // The frame returned is busy. It is not possible to reconstruct |
---|
343 | // the code sequence to allow completion. We will jump to |
---|
344 | // fpsp_fmt_error and allow the kernel to kill the process. |
---|
345 | // |
---|
346 | op0_xb: |
---|
347 | jmp fpsp_fmt_error |
---|
348 | |
---|
349 | // |
---|
350 | // Check for opclass 2 and single size. If not both, exit. |
---|
351 | // |
---|
352 | op2sgl: |
---|
353 | movew CMDREG1B(%a6),%d0 |
---|
354 | andiw #0xFC00,%d0 //strip all but opclass and size |
---|
355 | cmpiw #0x4400,%d0 //test for opclass 2 and size=sgl |
---|
356 | bne fix_done //if not, it is not bug 1238 |
---|
357 | // |
---|
358 | // Check for cu dest equal to nu dest or equal to xu dest, with |
---|
359 | // a cu and nu conflict taking priority an nu conflict. If either, |
---|
360 | // go and fix the bug condition. Otherwise, exit. |
---|
361 | // |
---|
362 | bfextu CMDREG1B(%a6){#6:#3},%d0 //get 1st dest |
---|
363 | bfextu CMDREG3B(%a6){#6:#3},%d1 //get 3rd dest |
---|
364 | cmpb %d0,%d1 //cmp 1st dest with 3rd dest |
---|
365 | beq op2_com //if equal, continue bugfix |
---|
366 | bfextu CMDREG2B(%a6){#6:#3},%d1 //get 2nd dest |
---|
367 | cmpb %d0,%d1 //cmp 1st dest with 2nd dest |
---|
368 | bne fix_done //if the reg checks fail, exit |
---|
369 | // |
---|
370 | // We have the case in which a conflict exists between the cu src or |
---|
371 | // dest and the dest of the xu. We must clear the instruction in |
---|
372 | // the cu and restore the state, allowing the instruction in the |
---|
373 | // xu to complete. Remember, the instruction in the nu |
---|
374 | // was exceptional, and was completed by the appropriate handler. |
---|
375 | // If the result of the xu instruction is not exceptional, we can |
---|
376 | // restore the instruction from the cu to the frame and continue |
---|
377 | // processing the original exception. If the result is also |
---|
378 | // exceptional, we choose to kill the process. |
---|
379 | // |
---|
380 | // Items saved from the stack: |
---|
381 | // |
---|
382 | // $3c stag - L_SCR1 |
---|
383 | // $40 cmdreg1b - L_SCR2 |
---|
384 | // $44 dtag - L_SCR3 |
---|
385 | // etemp - FP_SCR2 |
---|
386 | // |
---|
387 | // The cu savepc is set to zero, and the frame is restored to the |
---|
388 | // fpu. |
---|
389 | // |
---|
390 | op2_xu: |
---|
391 | movel STAG(%a6),L_SCR1(%a6) |
---|
392 | movel CMDREG1B(%a6),L_SCR2(%a6) |
---|
393 | movel DTAG(%a6),L_SCR3(%a6) |
---|
394 | andil #0xe0000000,L_SCR3(%a6) |
---|
395 | moveb #0,CU_SAVEPC(%a6) |
---|
396 | movel ETEMP(%a6),FP_SCR2(%a6) |
---|
397 | movel ETEMP_HI(%a6),FP_SCR2+4(%a6) |
---|
398 | movel ETEMP_LO(%a6),FP_SCR2+8(%a6) |
---|
399 | movel (%a7)+,%d1 //save return address from bsr |
---|
400 | frestore (%a7)+ |
---|
401 | fsave -(%a7) |
---|
402 | // |
---|
403 | // Check if the instruction which just completed was exceptional. |
---|
404 | // |
---|
405 | cmpw #0x4060,(%a7) |
---|
406 | beq op2_xb |
---|
407 | // |
---|
408 | // It is necessary to isolate the result of the instruction in the |
---|
409 | // xu if it is to fp0 - fp3 and write that value to the USER_FPn |
---|
410 | // locations on the stack. The correct destination register is in |
---|
411 | // cmdreg2b. |
---|
412 | // |
---|
413 | bfextu CMDREG2B(%a6){#6:#3},%d0 //get dest register no |
---|
414 | cmpil #3,%d0 |
---|
415 | bgts op2_xi |
---|
416 | beqs op2_fp3 |
---|
417 | cmpil #1,%d0 |
---|
418 | blts op2_fp0 |
---|
419 | beqs op2_fp1 |
---|
420 | op2_fp2: |
---|
421 | fmovemx %fp2-%fp2,USER_FP2(%a6) |
---|
422 | bras op2_xi |
---|
423 | op2_fp1: |
---|
424 | fmovemx %fp1-%fp1,USER_FP1(%a6) |
---|
425 | bras op2_xi |
---|
426 | op2_fp0: |
---|
427 | fmovemx %fp0-%fp0,USER_FP0(%a6) |
---|
428 | bras op2_xi |
---|
429 | op2_fp3: |
---|
430 | fmovemx %fp3-%fp3,USER_FP3(%a6) |
---|
431 | // |
---|
432 | // The frame returned is idle. We must build a busy frame to hold |
---|
433 | // the cu state information and fix up etemp. |
---|
434 | // |
---|
435 | op2_xi: |
---|
436 | movel #22,%d0 //clear 23 lwords |
---|
437 | clrl (%a7) |
---|
438 | op2_loop: |
---|
439 | clrl -(%a7) |
---|
440 | dbf %d0,op2_loop |
---|
441 | movel #0x40600000,-(%a7) |
---|
442 | movel L_SCR1(%a6),STAG(%a6) |
---|
443 | movel L_SCR2(%a6),CMDREG1B(%a6) |
---|
444 | movel L_SCR3(%a6),DTAG(%a6) |
---|
445 | moveb #0x6,CU_SAVEPC(%a6) |
---|
446 | movel FP_SCR2(%a6),ETEMP(%a6) |
---|
447 | movel FP_SCR2+4(%a6),ETEMP_HI(%a6) |
---|
448 | movel FP_SCR2+8(%a6),ETEMP_LO(%a6) |
---|
449 | movel %d1,-(%a7) |
---|
450 | bra op2_com |
---|
451 | |
---|
452 | // |
---|
453 | // We have the opclass 2 single source situation. |
---|
454 | // |
---|
455 | op2_com: |
---|
456 | moveb #0x15,%d0 |
---|
457 | bfins %d0,CMDREG1B(%a6){#0:#6} //opclass 2, double |
---|
458 | |
---|
459 | cmpw #0x407F,ETEMP_EX(%a6) //single +max |
---|
460 | bnes case2 |
---|
461 | movew #0x43FF,ETEMP_EX(%a6) //to double +max |
---|
462 | bra finish |
---|
463 | case2: |
---|
464 | cmpw #0xC07F,ETEMP_EX(%a6) //single -max |
---|
465 | bnes case3 |
---|
466 | movew #0xC3FF,ETEMP_EX(%a6) //to double -max |
---|
467 | bra finish |
---|
468 | case3: |
---|
469 | cmpw #0x3F80,ETEMP_EX(%a6) //single +min |
---|
470 | bnes case4 |
---|
471 | movew #0x3C00,ETEMP_EX(%a6) //to double +min |
---|
472 | bra finish |
---|
473 | case4: |
---|
474 | cmpw #0xBF80,ETEMP_EX(%a6) //single -min |
---|
475 | bne fix_done |
---|
476 | movew #0xBC00,ETEMP_EX(%a6) //to double -min |
---|
477 | bra finish |
---|
478 | // |
---|
479 | // The frame returned is busy. It is not possible to reconstruct |
---|
480 | // the code sequence to allow completion. fpsp_fmt_error causes |
---|
481 | // an fline illegal instruction to be executed. |
---|
482 | // |
---|
483 | // You should replace the jump to fpsp_fmt_error with a jump |
---|
484 | // to the entry point used to kill a process. |
---|
485 | // |
---|
486 | op2_xb: |
---|
487 | jmp fpsp_fmt_error |
---|
488 | |
---|
489 | // |
---|
490 | // Enter here if the case is not of the situations affected by |
---|
491 | // bug #1238, or if the fix is completed, and exit. |
---|
492 | // |
---|
493 | finish: |
---|
494 | fix_done: |
---|
495 | rts |
---|
496 | |
---|
497 | |end |
---|