diff options
Diffstat (limited to 'arch/m68k/fpsp040/x_snan.S')
-rw-r--r-- | arch/m68k/fpsp040/x_snan.S | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/arch/m68k/fpsp040/x_snan.S b/arch/m68k/fpsp040/x_snan.S new file mode 100644 index 000000000000..039af573312e --- /dev/null +++ b/arch/m68k/fpsp040/x_snan.S | |||
@@ -0,0 +1,277 @@ | |||
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.h" | ||
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 | ||