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