1 * $NetBSD: x_operr.sa,v 1.5 2001/09/16 16:34:32 wiz Exp $
3 * MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
4 * M68000 Hi-Performance Microprocessor Division
5 * M68040 Software Package
7 * M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
10 * THE SOFTWARE is provided on an "AS IS" basis and without warranty.
11 * To the maximum extent permitted by applicable law,
12 * MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
13 * INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
14 * PARTICULAR PURPOSE and any warranty against infringement with
15 * regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
16 * and any accompanying written materials.
18 * To the maximum extent permitted by applicable law,
19 * IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
20 * (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
21 * PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
22 * OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
23 * SOFTWARE. Motorola assumes no responsibility for the maintenance
24 * and support of the SOFTWARE.
26 * You are hereby granted a copyright license to use, modify, and
27 * distribute the SOFTWARE so long as this entire notice is retained
28 * without alteration in any modified and/or redistributed versions,
29 * and that such modified versions are clearly identified as such.
30 * No licenses are granted by implication, estoppel or otherwise
31 * under any patents or trademarks of Motorola, Inc.
34 * x_operr.sa 3.5 7/1/91
36 * fpsp_operr --- FPSP handler for operand error exception
38 * See 68040 User's Manual pp. 9-44f
40 * Note 1: For trap disabled 040 does the following:
41 * If the dest is a fp reg, then an extended precision non_signaling
42 * NAN is stored in the dest reg. If the dest format is b, w, or l and
43 * the source op is a NAN, then garbage is stored as the result (actually
44 * the upper 32 bits of the mantissa are sent to the integer unit). If
45 * the dest format is integer (b, w, l) and the operr is caused by
46 * integer overflow, or the source op is inf, then the result stored is
48 * There are three cases in which operr is incorrectly signaled on the
49 * 040. This occurs for move_out of format b, w, or l for the largest
50 * negative integer (-2^7 for b, -2^15 for w, -2^31 for l).
52 * On opclass = 011 fmove.(b,w,l) that causes a conversion
53 * overflow -> OPERR, the exponent in wbte (and fpte) is:
54 * byte 56 - (62 - exp)
55 * word 48 - (62 - exp)
56 * long 32 - (62 - exp)
58 * where exp = (true exp) - 1
60 * So, wbtemp and fptemp will contain the following on erroneoulsy
63 * fpte = $4000 (15 bit externally)
64 * byte fptm = $ffffffff ffffff80
65 * word fptm = $ffffffff ffff8000
66 * long fptm = $ffffffff 80000000
68 * Note 2: For trap enabled 040 does the following:
69 * If the inst is move_out, then same as Note 1.
70 * If the inst is not move_out, the dest is not modified.
71 * The exceptional operand is not defined for integer overflow
75 X_OPERR IDNT 2,1 Motorola 040 Floating Point Software Package
93 movem.l d0-d1/a0-a1,USER_DA(a6)
94 fmovem.x fp0-fp3,USER_FP0(a6)
95 fmovem.l fpcr/fpsr/fpiar,USER_FPCR(a6)
98 * Check if this is an opclass 3 instruction.
99 * If so, fall through, else branch to operr_end
101 btst.b #TFLAG,T_BYTE(a6)
105 * If the destination size is B,W,or L, the operr must be
108 move.l CMDREG1B(a6),d0
109 bfextu d0{3:3},d0 ;0=long, 4=word, 6=byte
110 tst.b d0 ;determine size; check long
112 cmpi.b #4,d0 ;check word
114 cmpi.b #6,d0 ;check byte
118 * The size is not B,W,or L, so the operr is handled by the
119 * kernel handler. Set the operr bits and clean up, leaving
120 * only the integer exception frame on the stack, and the
121 * fpu in the original exceptional state.
124 bset.b #operr_bit,FPSR_EXCEPT(a6)
125 bset.b #aiop_bit,FPSR_AEXCEPT(a6)
127 movem.l USER_DA(a6),d0-d1/a0-a1
128 fmovem.x USER_FP0(a6),fp0-fp3
129 fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar
135 moveq.l #4,d1 ;write size to d1
136 move.b STAG(a6),d0 ;test stag for nan
137 andi.b #$e0,d0 ;clr all but tag
138 cmpi.b #$60,d0 ;check for nan
140 cmpi.l #$80000000,FPTEMP_LO(a6) ;test if ls lword is special
141 bne.b chklerr ;if not equal, check for incorrect operr
142 bsr check_upper ;check if exp and ms mant are special
144 bne.b chklerr ;if d0 is true, check for incorrect operr
145 move.l #$80000000,d0 ;store special case result
147 bra.w not_enabled ;clean and exit
149 * CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
152 move.w FPTEMP_EX(a6),d0
153 and.w #$7FFF,d0 ;ignore sign bit
154 cmp.w #$3FFE,d0 ;this is the only possible exponent value
157 move.l FPTEMP_LO(a6),d0
161 move.w FPTEMP_EX(a6),d0
162 and.w #$7FFF,d0 ;ignore sign bit
164 bcc.w store_max ;exponent out of range
166 move.l FPTEMP_LO(a6),d0
167 and.l #$7FFF0000,d0 ;look for all 1's on bits 30-16
173 cmp.l #$FFFFFFFF,FPTEMP_HI(a6)
182 moveq.l #2,d1 ;write size to d1
183 move.b STAG(a6),d0 ;test stag for nan
184 andi.b #$e0,d0 ;clr all but tag
185 cmpi.b #$60,d0 ;check for nan
187 cmpi.l #$ffff8000,FPTEMP_LO(a6) ;test if ls lword is special
188 bne.b chkwerr ;if not equal, check for incorrect operr
189 bsr check_upper ;check if exp and ms mant are special
191 bne.b chkwerr ;if d0 is true, check for incorrect operr
192 move.l #$80000000,d0 ;store special case result
194 bra.w not_enabled ;clean and exit
196 * CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
199 move.w FPTEMP_EX(a6),d0
200 and.w #$7FFF,d0 ;ignore sign bit
201 cmp.w #$3FFE,d0 ;this is the only possible exponent value
203 move.l FPTEMP_LO(a6),d0
209 moveq.l #1,d1 ;write size to d1
210 move.b STAG(a6),d0 ;test stag for nan
211 andi.b #$e0,d0 ;clr all but tag
212 cmpi.b #$60,d0 ;check for nan
214 cmpi.l #$ffffff80,FPTEMP_LO(a6) ;test if ls lword is special
215 bne.b chkberr ;if not equal, check for incorrect operr
216 bsr check_upper ;check if exp and ms mant are special
218 bne.b chkberr ;if d0 is true, check for incorrect operr
219 move.l #$80000000,d0 ;store special case result
221 bra.w not_enabled ;clean and exit
223 * CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
226 move.w FPTEMP_EX(a6),d0
227 and.w #$7FFF,d0 ;ignore sign bit
228 cmp.w #$3FFE,d0 ;this is the only possible exponent value
230 move.l FPTEMP_LO(a6),d0
237 * This operr condition is not of the special case. Set operr
238 * and aiop and write the portion of the nan to memory for the
242 or.l #opaop_mask,USER_FPSR(a6) ;set operr & aiop
244 move.l ETEMP_HI(a6),d0 ;output will be from upper 32 bits
248 * Store_max loads the max pos or negative for the size, sets
249 * the operr and aiop bits, and clears inex and ainex, incorrectly
253 or.l #opaop_mask,USER_FPSR(a6) ;set operr & aiop
254 bclr.b #inex2_bit,FPSR_EXCEPT(a6)
255 bclr.b #ainex_bit,FPSR_AEXCEPT(a6)
258 tst.w FPTEMP_EX(a6) ;check sign
269 * This routine stores the data in d0, for the given size in d1,
270 * to memory or data register as required. A read of the fline
271 * is required to determine the destination.
274 move.l d0,L_SCR1(a6) ;move write data to L_SCR1
275 move.l d1,-(a7) ;save register size
276 bsr.l get_fline ;fline returned in d0
278 bftst d0{26:3} ;if mode is zero, dest is Dn
281 * Destination is Dn. Get register number from d0. Data is on
282 * the stack at (a7). D1 has size: 1=byte,2=word,4=long/single
284 andi.l #7,d0 ;isolate register number
286 beq.b op_long ;the most frequent case
294 move.l d0,d1 ;format size:reg for reg_dest
295 bra.l reg_dest ;call to reg_dest returns to caller
298 * Destination is memory. Get <ea> from integer exception frame
299 * and call mem_write.
302 lea.l L_SCR1(a6),a0 ;put ptr to write data in a0
303 move.l EXC_EA(a6),a1 ;put user destination address in a1
304 move.l d1,d0 ;put size in d0
308 * Check the exponent for $c000 and the upper 32 bits of the
309 * mantissa for $ffffffff. If both are true, return d0 clr
310 * and store the lower n bits of the least lword of FPTEMP
311 * to d0 for write out. If not, it is a real operr, and set d0.
314 cmpi.l #$ffffffff,FPTEMP_HI(a6) ;check if first byte is all 1's
315 bne.b true_operr ;if not all 1's then was true operr
316 cmpi.w #$c000,FPTEMP_EX(a6) ;check if incorrectly signalled
317 beq.b not_true_operr ;branch if not true operr
318 cmpi.w #$bfff,FPTEMP_EX(a6) ;check if incorrectly signalled
319 beq.b not_true_operr ;branch if not true operr
321 move.l #1,d0 ;signal real operr
324 clr.l d0 ;signal no real operr
328 * End_operr tests for operr enabled. If not, it cleans up the stack
329 * and does an rte. If enabled, it cleans up the stack and branches
330 * to the kernel operr handler with only the integer exception
331 * frame on the stack and the fpu in the original exceptional state
332 * with correct data written to the destination.
335 btst.b #operr_bit,FPCR_ENABLE(a6)
338 movem.l USER_DA(a6),d0-d1/a0-a1
339 fmovem.x USER_FP0(a6),fp0-fp3
340 fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar
347 * It is possible to have either inex2 or inex1 exceptions with the
348 * operr. If the inex enable bit is set in the FPCR, and either
349 * inex2 or inex1 occurred, we must clean up and branch to the
353 move.b FPCR_ENABLE(a6),d0
354 and.b FPSR_EXCEPT(a6),d0
358 * Inexact enabled and reported, and we must take an inexact exception.
361 move.b #INEX_VEC,EXC_VEC+1(a6)
362 move.l USER_FPSR(a6),FPSR_SHADOW(a6)
363 or.l #sx_mask,E_BYTE(a6)
364 movem.l USER_DA(a6),d0-d1/a0-a1
365 fmovem.x USER_FP0(a6),fp0-fp3
366 fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar
371 * Since operr is only an E1 exception, there is no need to frestore
372 * any state back to the fpu.
375 movem.l USER_DA(a6),d0-d1/a0-a1
376 fmovem.x USER_FP0(a6),fp0-fp3
377 fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar