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