revert between 56095 -> 55830 in arch
[AROS.git] / arch / m68k-all / m680x0 / fpsp / x_operr.sa
blob49fb3c9c5b1c3834fc17743345c3bdd9c138daaa
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.
8 *       All rights reserved.
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
47 * garbage.
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
61 *         signalled operr:
62 *                       fpts = 1
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 
72 * during a move_out.
75 X_OPERR IDNT    2,1 Motorola 040 Floating Point Software Package
77         section 8
79         include fpsp.h
81         xref    mem_write
82         xref    real_operr
83         xref    real_inex
84         xref    get_fline
85         xref    fpsp_done
86         xref    reg_dest
88         xdef    fpsp_operr
89 fpsp_operr:
91         link            a6,#-LOCAL_SIZE
92         fsave           -(a7)
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)
102         beq.b   operr_end
105 * If the destination size is B,W,or L, the operr must be 
106 * handled here.
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
111         beq.w   operr_long
112         cmpi.b  #4,d0           ;check word
113         beq.w   operr_word
114         cmpi.b  #6,d0           ;check byte
115         beq.w   operr_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.
123 operr_end:
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
130         frestore        (a7)+
131         unlk            a6
132         bra.l           real_operr
134 operr_long:
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
139         beq     operr_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
143         tst.l   d0
144         bne.b   chklerr         ;if d0 is true, check for incorrect operr
145         move.l  #$80000000,d0   ;store special case result
146         bsr     operr_store
147         bra.w   not_enabled     ;clean and exit
149 *       CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
151 chklerr:
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
155         bne.b   chklerr2
156 fixlong:
157         move.l  FPTEMP_LO(a6),d0
158         bsr     operr_store
159         bra.w   not_enabled
160 chklerr2:
161         move.w  FPTEMP_EX(a6),d0
162         and.w   #$7FFF,d0       ;ignore sign bit
163         cmp.w   #$4000,d0
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
168         cmp.l   #$7FFF0000,d0
169         beq.b   fixlong
171         tst.l   FPTEMP_LO(a6)
172         bpl.b   chklepos
173         cmp.l   #$FFFFFFFF,FPTEMP_HI(a6)
174         beq.b   fixlong
175         bra.w   store_max
176 chklepos:
177         tst.l   FPTEMP_HI(a6)
178         beq.b   fixlong
179         bra.w   store_max
181 operr_word:
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
186         beq.w   operr_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
190         tst.l   d0
191         bne.b   chkwerr         ;if d0 is true, check for incorrect operr
192         move.l  #$80000000,d0   ;store special case result
193         bsr     operr_store
194         bra.w   not_enabled     ;clean and exit
196 *       CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
198 chkwerr:
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
202         bne.b   store_max
203         move.l  FPTEMP_LO(a6),d0
204         swap    d0
205         bsr     operr_store
206         bra.w   not_enabled
208 operr_byte:
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
213         beq.b   operr_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
217         tst.l   d0
218         bne.b   chkberr         ;if d0 is true, check for incorrect operr
219         move.l  #$80000000,d0   ;store special case result
220         bsr     operr_store
221         bra.w   not_enabled     ;clean and exit
223 *       CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
225 chkberr:
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
229         bne.b   store_max
230         move.l  FPTEMP_LO(a6),d0
231         asl.l   #8,d0
232         swap    d0
233         bsr     operr_store
234         bra.w   not_enabled
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
239 * given size.
241 operr_nan:
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
245         bsr     operr_store
246         bra     end_operr
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
250 * set by the 040.
252 store_max:
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)
256         fmove.l #0,FPSR
257         
258         tst.w   FPTEMP_EX(a6)   ;check sign
259         blt.b   load_neg
260         move.l  #$7fffffff,d0
261         bsr     operr_store
262         bra     end_operr
263 load_neg:
264         move.l  #$80000000,d0
265         bsr     operr_store
266         bra     end_operr
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.
273 operr_store:
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
277         move.l  (a7)+,d1
278         bftst   d0{26:3}                ;if mode is zero, dest is Dn
279         bne.b   dest_mem
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
285         cmpi.l  #4,d1
286         beq.b   op_long         ;the most frequent case
287         cmpi.l  #2,d1
288         bne.b   op_con
289         or.l    #8,d0
290         bra.b   op_con
291 op_long:
292         or.l    #$10,d0
293 op_con:
294         move.l  d0,d1           ;format size:reg for reg_dest
295         bra.l   reg_dest        ;call to reg_dest returns to caller
296 *                               ;of operr_store
298 * Destination is memory.  Get <ea> from integer exception frame
299 * and call mem_write.
301 dest_mem:
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
305         bsr.l   mem_write
306         rts
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.
313 check_upper:
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
320 true_operr:
321         move.l  #1,d0           ;signal real operr
322         rts
323 not_true_operr:
324         clr.l   d0              ;signal no real operr
325         rts
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.
334 end_operr:
335         btst.b          #operr_bit,FPCR_ENABLE(a6)
336         beq.b           not_enabled
337 enabled:
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
341         frestore        (a7)+
342         unlk            a6
343         bra.l           real_operr
345 not_enabled:
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
350 * real inex handler.
352 ck_inex:
353         move.b  FPCR_ENABLE(a6),d0
354         and.b   FPSR_EXCEPT(a6),d0
355         andi.b  #$3,d0
356         beq.w   operr_exit
358 * Inexact enabled and reported, and we must take an inexact exception.
360 take_inex:
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
367         frestore        (a7)+
368         unlk            a6
369         bra.l           real_inex
371 * Since operr is only an E1 exception, there is no need to frestore
372 * any state back to the fpu.
374 operr_exit:
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
378         unlk            a6
379         bra.l           fpsp_done
381         end