Annotation of sys/arch/m68k/fpsp/x_operr.sa, Revision 1.1.1.1
1.1 nbrk 1: * $OpenBSD: x_operr.sa,v 1.3 2001/09/20 17:02:30 mpech Exp $
2: * $NetBSD: x_operr.sa,v 1.4 1994/10/26 07:50:24 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: * x_operr.sa 3.5 7/1/91
36: *
37: * fpsp_operr --- FPSP handler for operand error exception
38: *
39: * See 68040 User's Manual pp. 9-44f
40: *
41: * Note 1: For trap disabled 040 does the following:
42: * If the dest is a fp reg, then an extended precision non_signaling
43: * NAN is stored in the dest reg. If the dest format is b, w, or l and
44: * the source op is a NAN, then garbage is stored as the result (actually
45: * the upper 32 bits of the mantissa are sent to the integer unit). If
46: * the dest format is integer (b, w, l) and the operr is caused by
47: * integer overflow, or the source op is inf, then the result stored is
48: * garbage.
49: * There are three cases in which operr is incorrectly signaled on the
50: * 040. This occurs for move_out of format b, w, or l for the largest
51: * negative integer (-2^7 for b, -2^15 for w, -2^31 for l).
52: *
53: * On opclass = 011 fmove.(b,w,l) that causes a conversion
54: * overflow -> OPERR, the exponent in wbte (and fpte) is:
55: * byte 56 - (62 - exp)
56: * word 48 - (62 - exp)
57: * long 32 - (62 - exp)
58: *
59: * where exp = (true exp) - 1
60: *
61: * So, wbtemp and fptemp will contain the following on erroneoulsy
62: * signalled operr:
63: * fpts = 1
64: * fpte = $4000 (15 bit externally)
65: * byte fptm = $ffffffff ffffff80
66: * word fptm = $ffffffff ffff8000
67: * long fptm = $ffffffff 80000000
68: *
69: * Note 2: For trap enabled 040 does the following:
70: * If the inst is move_out, then same as Note 1.
71: * If the inst is not move_out, the dest is not modified.
72: * The exceptional operand is not defined for integer overflow
73: * during a move_out.
74: *
75:
76: X_OPERR IDNT 2,1 Motorola 040 Floating Point Software Package
77:
78: section 8
79:
80: include fpsp.h
81:
82: xref mem_write
83: xref real_operr
84: xref real_inex
85: xref get_fline
86: xref fpsp_done
87: xref reg_dest
88:
89: xdef fpsp_operr
90: fpsp_operr:
91: *
92: link a6,#-LOCAL_SIZE
93: fsave -(a7)
94: movem.l d0-d1/a0-a1,USER_DA(a6)
95: fmovem.x fp0-fp3,USER_FP0(a6)
96: fmovem.l fpcr/fpsr/fpiar,USER_FPCR(a6)
97:
98: *
99: * Check if this is an opclass 3 instruction.
100: * If so, fall through, else branch to operr_end
101: *
102: btst.b #TFLAG,T_BYTE(a6)
103: beq.b operr_end
104:
105: *
106: * If the destination size is B,W,or L, the operr must be
107: * handled here.
108: *
109: move.l CMDREG1B(a6),d0
110: bfextu d0{3:3},d0 ;0=long, 4=word, 6=byte
111: tst.b d0 ;determine size; check long
112: beq.w operr_long
113: cmpi.b #4,d0 ;check word
114: beq.w operr_word
115: cmpi.b #6,d0 ;check byte
116: beq.w operr_byte
117:
118: *
119: * The size is not B,W,or L, so the operr is handled by the
120: * kernel handler. Set the operr bits and clean up, leaving
121: * only the integer exception frame on the stack, and the
122: * fpu in the original exceptional state.
123: *
124: operr_end:
125: bset.b #operr_bit,FPSR_EXCEPT(a6)
126: bset.b #aiop_bit,FPSR_AEXCEPT(a6)
127:
128: movem.l USER_DA(a6),d0-d1/a0-a1
129: fmovem.x USER_FP0(a6),fp0-fp3
130: fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar
131: frestore (a7)+
132: unlk a6
133: bra.l real_operr
134:
135: operr_long:
136: moveq.l #4,d1 ;write size to d1
137: move.b STAG(a6),d0 ;test stag for nan
138: andi.b #$e0,d0 ;clr all but tag
139: cmpi.b #$60,d0 ;check for nan
140: beq operr_nan
141: cmpi.l #$80000000,FPTEMP_LO(a6) ;test if ls lword is special
142: bne.b chklerr ;if not equal, check for incorrect operr
143: bsr check_upper ;check if exp and ms mant are special
144: tst.l d0
145: bne.b chklerr ;if d0 is true, check for incorrect operr
146: move.l #$80000000,d0 ;store special case result
147: bsr operr_store
148: bra.w not_enabled ;clean and exit
149: *
150: * CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
151: *
152: chklerr:
153: move.w FPTEMP_EX(a6),d0
154: and.w #$7FFF,d0 ;ignore sign bit
155: cmp.w #$3FFE,d0 ;this is the only possible exponent value
156: bne.b chklerr2
157: fixlong:
158: move.l FPTEMP_LO(a6),d0
159: bsr operr_store
160: bra.w not_enabled
161: chklerr2:
162: move.w FPTEMP_EX(a6),d0
163: and.w #$7FFF,d0 ;ignore sign bit
164: cmp.w #$4000,d0
165: bcc.w store_max ;exponent out of range
166:
167: move.l FPTEMP_LO(a6),d0
168: and.l #$7FFF0000,d0 ;look for all 1's on bits 30-16
169: cmp.l #$7FFF0000,d0
170: beq.b fixlong
171:
172: tst.l FPTEMP_LO(a6)
173: bpl.b chklepos
174: cmp.l #$FFFFFFFF,FPTEMP_HI(a6)
175: beq.b fixlong
176: bra.w store_max
177: chklepos:
178: tst.l FPTEMP_HI(a6)
179: beq.b fixlong
180: bra.w store_max
181:
182: operr_word:
183: moveq.l #2,d1 ;write size to d1
184: move.b STAG(a6),d0 ;test stag for nan
185: andi.b #$e0,d0 ;clr all but tag
186: cmpi.b #$60,d0 ;check for nan
187: beq.w operr_nan
188: cmpi.l #$ffff8000,FPTEMP_LO(a6) ;test if ls lword is special
189: bne.b chkwerr ;if not equal, check for incorrect operr
190: bsr check_upper ;check if exp and ms mant are special
191: tst.l d0
192: bne.b chkwerr ;if d0 is true, check for incorrect operr
193: move.l #$80000000,d0 ;store special case result
194: bsr operr_store
195: bra.w not_enabled ;clean and exit
196: *
197: * CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
198: *
199: chkwerr:
200: move.w FPTEMP_EX(a6),d0
201: and.w #$7FFF,d0 ;ignore sign bit
202: cmp.w #$3FFE,d0 ;this is the only possible exponent value
203: bne.b store_max
204: move.l FPTEMP_LO(a6),d0
205: swap d0
206: bsr operr_store
207: bra.w not_enabled
208:
209: operr_byte:
210: moveq.l #1,d1 ;write size to d1
211: move.b STAG(a6),d0 ;test stag for nan
212: andi.b #$e0,d0 ;clr all but tag
213: cmpi.b #$60,d0 ;check for nan
214: beq.b operr_nan
215: cmpi.l #$ffffff80,FPTEMP_LO(a6) ;test if ls lword is special
216: bne.b chkberr ;if not equal, check for incorrect operr
217: bsr check_upper ;check if exp and ms mant are special
218: tst.l d0
219: bne.b chkberr ;if d0 is true, check for incorrect operr
220: move.l #$80000000,d0 ;store special case result
221: bsr operr_store
222: bra.w not_enabled ;clean and exit
223: *
224: * CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
225: *
226: chkberr:
227: move.w FPTEMP_EX(a6),d0
228: and.w #$7FFF,d0 ;ignore sign bit
229: cmp.w #$3FFE,d0 ;this is the only possible exponent value
230: bne.b store_max
231: move.l FPTEMP_LO(a6),d0
232: asl.l #8,d0
233: swap d0
234: bsr operr_store
235: bra.w not_enabled
236:
237: *
238: * This operr condition is not of the special case. Set operr
239: * and aiop and write the portion of the nan to memory for the
240: * given size.
241: *
242: operr_nan:
243: or.l #opaop_mask,USER_FPSR(a6) ;set operr & aiop
244:
245: move.l ETEMP_HI(a6),d0 ;output will be from upper 32 bits
246: bsr operr_store
247: bra end_operr
248: *
249: * Store_max loads the max pos or negative for the size, sets
250: * the operr and aiop bits, and clears inex and ainex, incorrectly
251: * set by the 040.
252: *
253: store_max:
254: or.l #opaop_mask,USER_FPSR(a6) ;set operr & aiop
255: bclr.b #inex2_bit,FPSR_EXCEPT(a6)
256: bclr.b #ainex_bit,FPSR_AEXCEPT(a6)
257: fmove.l #0,FPSR
258:
259: tst.w FPTEMP_EX(a6) ;check sign
260: blt.b load_neg
261: move.l #$7fffffff,d0
262: bsr operr_store
263: bra end_operr
264: load_neg:
265: move.l #$80000000,d0
266: bsr operr_store
267: bra end_operr
268:
269: *
270: * This routine stores the data in d0, for the given size in d1,
271: * to memory or data register as required. A read of the fline
272: * is required to determine the destination.
273: *
274: operr_store:
275: move.l d0,L_SCR1(a6) ;move write data to L_SCR1
276: move.l d1,-(a7) ;save register size
277: bsr.l get_fline ;fline returned in d0
278: move.l (a7)+,d1
279: bftst d0{26:3} ;if mode is zero, dest is Dn
280: bne.b dest_mem
281: *
282: * Destination is Dn. Get register number from d0. Data is on
283: * the stack at (a7). D1 has size: 1=byte,2=word,4=long/single
284: *
285: andi.l #7,d0 ;isolate register number
286: cmpi.l #4,d1
287: beq.b op_long ;the most frequent case
288: cmpi.l #2,d1
289: bne.b op_con
290: or.l #8,d0
291: bra.b op_con
292: op_long:
293: or.l #$10,d0
294: op_con:
295: move.l d0,d1 ;format size:reg for reg_dest
296: bra.l reg_dest ;call to reg_dest returns to caller
297: * ;of operr_store
298: *
299: * Destination is memory. Get <ea> from integer exception frame
300: * and call mem_write.
301: *
302: dest_mem:
303: lea.l L_SCR1(a6),a0 ;put ptr to write data in a0
304: move.l EXC_EA(a6),a1 ;put user destination address in a1
305: move.l d1,d0 ;put size in d0
306: bsr.l mem_write
307: rts
308: *
309: * Check the exponent for $c000 and the upper 32 bits of the
310: * mantissa for $ffffffff. If both are true, return d0 clr
311: * and store the lower n bits of the least lword of FPTEMP
312: * to d0 for write out. If not, it is a real operr, and set d0.
313: *
314: check_upper:
315: cmpi.l #$ffffffff,FPTEMP_HI(a6) ;check if first byte is all 1's
316: bne.b true_operr ;if not all 1's then was true operr
317: cmpi.w #$c000,FPTEMP_EX(a6) ;check if incorrectly signalled
318: beq.b not_true_operr ;branch if not true operr
319: cmpi.w #$bfff,FPTEMP_EX(a6) ;check if incorrectly signalled
320: beq.b not_true_operr ;branch if not true operr
321: true_operr:
322: move.l #1,d0 ;signal real operr
323: rts
324: not_true_operr:
325: clr.l d0 ;signal no real operr
326: rts
327:
328: *
329: * End_operr tests for operr enabled. If not, it cleans up the stack
330: * and does an rte. If enabled, it cleans up the stack and branches
331: * to the kernel operr handler with only the integer exception
332: * frame on the stack and the fpu in the original exceptional state
333: * with correct data written to the destination.
334: *
335: end_operr:
336: btst.b #operr_bit,FPCR_ENABLE(a6)
337: beq.b not_enabled
338: enabled:
339: movem.l USER_DA(a6),d0-d1/a0-a1
340: fmovem.x USER_FP0(a6),fp0-fp3
341: fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar
342: frestore (a7)+
343: unlk a6
344: bra.l real_operr
345:
346: not_enabled:
347: *
348: * It is possible to have either inex2 or inex1 exceptions with the
349: * operr. If the inex enable bit is set in the FPCR, and either
350: * inex2 or inex1 occurred, we must clean up and branch to the
351: * real inex handler.
352: *
353: ck_inex:
354: move.b FPCR_ENABLE(a6),d0
355: and.b FPSR_EXCEPT(a6),d0
356: andi.b #$3,d0
357: beq.w operr_exit
358: *
359: * Inexact enabled and reported, and we must take an inexact exception.
360: *
361: take_inex:
362: move.b #INEX_VEC,EXC_VEC+1(a6)
363: move.l USER_FPSR(a6),FPSR_SHADOW(a6)
364: or.l #sx_mask,E_BYTE(a6)
365: movem.l USER_DA(a6),d0-d1/a0-a1
366: fmovem.x USER_FP0(a6),fp0-fp3
367: fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar
368: frestore (a7)+
369: unlk a6
370: bra.l real_inex
371: *
372: * Since operr is only an E1 exception, there is no need to frestore
373: * any state back to the fpu.
374: *
375: operr_exit:
376: movem.l USER_DA(a6),d0-d1/a0-a1
377: fmovem.x USER_FP0(a6),fp0-fp3
378: fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar
379: unlk a6
380: bra.l fpsp_done
381:
382: end
CVSweb