1*         $NetBSD: x_snan.sa,v 1.4 2001/09/16 16:34:32 wiz Exp $
2
3*         MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
4*         M68000 Hi-Performance Microprocessor Division
5*         M68040 Software Package
6*
7*         M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
8*         All rights reserved.
9*
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.
17*
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.
25*
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.
32
33*
34*         x_snan.sa 3.3 7/1/91
35*
36* fpsp_snan --- FPSP handler for signalling NAN exception
37*
38* SNAN for float -> integer conversions (integer conversion of
39* an SNAN) is a non-maskable run-time exception.
40*
41* For trap disabled the 040 does the following:
42* If the dest data format is s, d, or x, then the SNAN bit in the NAN
43* is set to one and the resulting non-signaling NAN (truncated if
44* necessary) is transferred to the dest.  If the dest format is b, w,
45* or l, then garbage is written to the dest (actually the upper 32 bits
46* of the mantissa are sent to the integer unit).
47*
48* For trap enabled the 040 does the following:
49* If the inst is move_out, then the results are the same as for trap
50* disabled with the exception posted.  If the instruction is not move_
51* out, the dest. is not modified, and the exception is posted.
52*
53
54X_SNAN    IDNT    2,1 Motorola 040 Floating Point Software Package
55
56          section   8
57
58          include   fpsp.h
59
60          xref      get_fline
61          xref      mem_write
62          xref      real_snan
63          xref      real_inex
64          xref      fpsp_done
65          xref      reg_dest
66
67          xdef      fpsp_snan
68fpsp_snan:
69          link                a6,#-LOCAL_SIZE
70          fsave               -(a7)
71          movem.l             d0-d1/a0-a1,USER_DA(a6)
72          fmovem.x  fp0-fp3,USER_FP0(a6)
73          fmovem.l  fpcr/fpsr/fpiar,USER_FPCR(a6)
74
75*
76* Check if trap enabled
77*
78          btst.b              #snan_bit,FPCR_ENABLE(a6)
79          bne.b               ena                 ;If enabled, then branch
80
81          bsr.l               move_out  ;else SNAN disabled
82*
83* It is possible to have an inex1 exception with the
84* snan.  If the inex enable bit is set in the FPCR, and either
85* inex2 or inex1 occurred, we must clean up and branch to the
86* real inex handler.
87*
88ck_inex:
89          move.b    FPCR_ENABLE(a6),d0
90          and.b     FPSR_EXCEPT(a6),d0
91          andi.b    #$3,d0
92          beq.w     end_snan
93*
94* Inexact enabled and reported, and we must take an inexact exception.
95*
96take_inex:
97          move.b              #INEX_VEC,EXC_VEC+1(a6)
98          movem.l             USER_DA(a6),d0-d1/a0-a1
99          fmovem.x  USER_FP0(a6),fp0-fp3
100          fmovem.l  USER_FPCR(a6),fpcr/fpsr/fpiar
101          frestore  (a7)+
102          unlk                a6
103          bra.l               real_inex
104*
105* SNAN is enabled.  Check if inst is move_out.
106* Make any corrections to the 040 output as necessary.
107*
108ena:
109          btst.b              #5,CMDREG1B(a6) ;if set, inst is move out
110          beq.w               not_out
111
112          bsr.l               move_out
113
114report_snan:
115          move.b              (a7),VER_TMP(a6)
116          cmpi.b              #VER_40,(a7)        ;test for orig unimp frame
117          bne.b               ck_rev
118          moveq.l             #13,d0              ;need to zero 14 lwords
119          bra.b               rep_con
120ck_rev:
121          moveq.l             #11,d0              ;need to zero 12 lwords
122rep_con:
123          clr.l               (a7)
124loop1:
125          clr.l               -(a7)               ;clear and dec a7
126          dbra.w              d0,loop1
127          move.b              VER_TMP(a6),(a7) ;format a busy frame
128          move.b              #BUSY_SIZE-4,1(a7)
129          move.l              USER_FPSR(a6),FPSR_SHADOW(a6)
130          or.l                #sx_mask,E_BYTE(a6)
131          movem.l             USER_DA(a6),d0-d1/a0-a1
132          fmovem.x  USER_FP0(a6),fp0-fp3
133          fmovem.l  USER_FPCR(a6),fpcr/fpsr/fpiar
134          frestore  (a7)+
135          unlk                a6
136          bra.l               real_snan
137*
138* Exit snan handler by expanding the unimp frame into a busy frame
139*
140end_snan:
141          bclr.b              #E1,E_BYTE(a6)
142
143          move.b              (a7),VER_TMP(a6)
144          cmpi.b              #VER_40,(a7)        ;test for orig unimp frame
145          bne.b               ck_rev2
146          moveq.l             #13,d0              ;need to zero 14 lwords
147          bra.b               rep_con2
148ck_rev2:
149          moveq.l             #11,d0              ;need to zero 12 lwords
150rep_con2:
151          clr.l               (a7)
152loop2:
153          clr.l               -(a7)               ;clear and dec a7
154          dbra.w              d0,loop2
155          move.b              VER_TMP(a6),(a7) ;format a busy frame
156          move.b              #BUSY_SIZE-4,1(a7) ;write busy size
157          move.l              USER_FPSR(a6),FPSR_SHADOW(a6)
158          or.l                #sx_mask,E_BYTE(a6)
159          movem.l             USER_DA(a6),d0-d1/a0-a1
160          fmovem.x  USER_FP0(a6),fp0-fp3
161          fmovem.l  USER_FPCR(a6),fpcr/fpsr/fpiar
162          frestore  (a7)+
163          unlk                a6
164          bra.l               fpsp_done
165
166*
167* Move_out
168*
169move_out:
170          move.l              EXC_EA(a6),a0       ;get <ea> from exc frame
171
172          bfextu              CMDREG1B(a6){3:3},d0 ;move rx field to d0{2:0}
173          tst.l               d0                  ;check for long
174          beq.b               sto_long  ;branch if move_out long
175
176          cmpi.l              #4,d0               ;check for word
177          beq.b               sto_word  ;branch if move_out word
178
179          cmpi.l              #6,d0               ;check for byte
180          beq.b               sto_byte  ;branch if move_out byte
181
182*
183* Not byte, word or long
184*
185          rts
186*
187* Get the 32 most significant bits of etemp mantissa
188*
189sto_long:
190          move.l              ETEMP_HI(a6),d1
191          move.l              #4,d0               ;load byte count
192*
193* Set signalling nan bit
194*
195          bset.l              #30,d1
196*
197* Store to the users destination address
198*
199          tst.l               a0                  ;check if <ea> is 0
200          beq.b               wrt_dn              ;destination is a data register
201
202          move.l              d1,-(a7)  ;move the snan onto the stack
203          move.l              a0,a1               ;load dest addr into a1
204          move.l              a7,a0               ;load src addr of snan into a0
205          bsr.l               mem_write ;write snan to user memory
206          move.l              (a7)+,d1  ;clear off stack
207          rts
208*
209* Get the 16 most significant bits of etemp mantissa
210*
211sto_word:
212          move.l              ETEMP_HI(a6),d1
213          move.l              #2,d0               ;load byte count
214*
215* Set signalling nan bit
216*
217          bset.l              #30,d1
218*
219* Store to the users destination address
220*
221          tst.l               a0                  ;check if <ea> is 0
222          beq.b               wrt_dn              ;destination is a data register
223
224          move.l              d1,-(a7)  ;move the snan onto the stack
225          move.l              a0,a1               ;load dest addr into a1
226          move.l              a7,a0               ;point to low word
227          bsr.l               mem_write ;write snan to user memory
228          move.l              (a7)+,d1  ;clear off stack
229          rts
230*
231* Get the 8 most significant bits of etemp mantissa
232*
233sto_byte:
234          move.l              ETEMP_HI(a6),d1
235          move.l              #1,d0               ;load byte count
236*
237* Set signalling nan bit
238*
239          bset.l              #30,d1
240*
241* Store to the users destination address
242*
243          tst.l               a0                  ;check if <ea> is 0
244          beq.b               wrt_dn              ;destination is a data register
245          move.l              d1,-(a7)  ;move the snan onto the stack
246          move.l              a0,a1               ;load dest addr into a1
247          move.l              a7,a0               ;point to source byte
248          bsr.l               mem_write ;write snan to user memory
249          move.l              (a7)+,d1  ;clear off stack
250          rts
251
252*
253*         wrt_dn --- write to a data register
254*
255*         We get here with D1 containing the data to write and D0 the
256*         number of bytes to write: 1=byte,2=word,4=long.
257*
258wrt_dn:
259          move.l              d1,L_SCR1(a6)       ;data
260          move.l              d0,-(a7)  ;size
261          bsr.l               get_fline ;returns fline word in d0
262          move.l              d0,d1
263          andi.l              #$7,d1              ;d1 now holds register number
264          move.l              (sp)+,d0  ;get original size
265          cmpi.l              #4,d0
266          beq.b               wrt_long
267          cmpi.l              #2,d0
268          bne.b               wrt_byte
269wrt_word:
270          or.l                #$8,d1
271          bra.l               reg_dest
272wrt_long:
273          or.l                #$10,d1
274          bra.l               reg_dest
275wrt_byte:
276          bra.l               reg_dest
277*
278* Check if it is a src nan or dst nan
279*
280not_out:
281          move.l              DTAG(a6),d0
282          bfextu              d0{0:3},d0          ;isolate dtag in lsbs
283
284          cmpi.b              #3,d0               ;check for nan in destination
285          bne.b               issrc               ;destination nan has priority
286dst_nan:
287          btst.b              #6,FPTEMP_HI(a6) ;check if dest nan is an snan
288          bne.b               issrc               ;no, so check source for snan
289          move.w              FPTEMP_EX(a6),d0
290          bra.b               cont
291issrc:
292          move.w              ETEMP_EX(a6),d0
293cont:
294          btst.l              #15,d0              ;test for sign of snan
295          beq.b               clr_neg
296          bset.b              #neg_bit,FPSR_CC(a6)
297          bra.w               report_snan
298clr_neg:
299          bclr.b              #neg_bit,FPSR_CC(a6)
300          bra.w               report_snan
301
302          end
303