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