pfpsp.s revision 1.2.4.2 1 1.2.4.2 wiz #
2 1.2.4.2 wiz # $NetBSD: pfpsp.s,v 1.2.4.2 2001/09/16 16:34:32 wiz Exp $
3 1.2.4.2 wiz #
4 1.2.4.2 wiz
5 1.2.4.2 wiz #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 1.2.4.2 wiz # MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
7 1.2.4.2 wiz # M68000 Hi-Performance Microprocessor Division
8 1.2.4.2 wiz # M68060 Software Package Production Release
9 1.2.4.2 wiz #
10 1.2.4.2 wiz # M68060 Software Package Copyright (C) 1993, 1994, 1995, 1996 Motorola Inc.
11 1.2.4.2 wiz # All rights reserved.
12 1.2.4.2 wiz #
13 1.2.4.2 wiz # THE SOFTWARE is provided on an "AS IS" basis and without warranty.
14 1.2.4.2 wiz # To the maximum extent permitted by applicable law,
15 1.2.4.2 wiz # MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
16 1.2.4.2 wiz # INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS
17 1.2.4.2 wiz # FOR A PARTICULAR PURPOSE and any warranty against infringement with
18 1.2.4.2 wiz # regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
19 1.2.4.2 wiz # and any accompanying written materials.
20 1.2.4.2 wiz #
21 1.2.4.2 wiz # To the maximum extent permitted by applicable law,
22 1.2.4.2 wiz # IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
23 1.2.4.2 wiz # (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
24 1.2.4.2 wiz # BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
25 1.2.4.2 wiz # ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
26 1.2.4.2 wiz #
27 1.2.4.2 wiz # Motorola assumes no responsibility for the maintenance and support
28 1.2.4.2 wiz # of the SOFTWARE.
29 1.2.4.2 wiz #
30 1.2.4.2 wiz # You are hereby granted a copyright license to use, modify, and distribute the
31 1.2.4.2 wiz # SOFTWARE so long as this entire notice is retained without alteration
32 1.2.4.2 wiz # in any modified and/or redistributed versions, and that such modified
33 1.2.4.2 wiz # versions are clearly identified as such.
34 1.2.4.2 wiz # No licenses are granted by implication, estoppel or otherwise under any
35 1.2.4.2 wiz # patents or trademarks of Motorola, Inc.
36 1.2.4.2 wiz #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
37 1.2.4.2 wiz
38 1.2.4.2 wiz #
39 1.2.4.2 wiz # freal.s:
40 1.2.4.2 wiz # This file is appended to the top of the 060FPSP package
41 1.2.4.2 wiz # and contains the entry points into the package. The user, in
42 1.2.4.2 wiz # effect, branches to one of the branch table entries located
43 1.2.4.2 wiz # after _060FPSP_TABLE.
44 1.2.4.2 wiz # Also, subroutine stubs exist in this file (_fpsp_done for
45 1.2.4.2 wiz # example) that are referenced by the FPSP package itself in order
46 1.2.4.2 wiz # to call a given routine. The stub routine actually performs the
47 1.2.4.2 wiz # callout. The FPSP code does a "bsr" to the stub routine. This
48 1.2.4.2 wiz # extra layer of hierarchy adds a slight performance penalty but
49 1.2.4.2 wiz # it makes the FPSP code easier to read and more mainatinable.
50 1.2.4.2 wiz #
51 1.2.4.2 wiz
52 1.2.4.2 wiz set _off_bsun, 0x00
53 1.2.4.2 wiz set _off_snan, 0x04
54 1.2.4.2 wiz set _off_operr, 0x08
55 1.2.4.2 wiz set _off_ovfl, 0x0c
56 1.2.4.2 wiz set _off_unfl, 0x10
57 1.2.4.2 wiz set _off_dz, 0x14
58 1.2.4.2 wiz set _off_inex, 0x18
59 1.2.4.2 wiz set _off_fline, 0x1c
60 1.2.4.2 wiz set _off_fpu_dis, 0x20
61 1.2.4.2 wiz set _off_trap, 0x24
62 1.2.4.2 wiz set _off_trace, 0x28
63 1.2.4.2 wiz set _off_access, 0x2c
64 1.2.4.2 wiz set _off_done, 0x30
65 1.2.4.2 wiz
66 1.2.4.2 wiz set _off_imr, 0x40
67 1.2.4.2 wiz set _off_dmr, 0x44
68 1.2.4.2 wiz set _off_dmw, 0x48
69 1.2.4.2 wiz set _off_irw, 0x4c
70 1.2.4.2 wiz set _off_irl, 0x50
71 1.2.4.2 wiz set _off_drb, 0x54
72 1.2.4.2 wiz set _off_drw, 0x58
73 1.2.4.2 wiz set _off_drl, 0x5c
74 1.2.4.2 wiz set _off_dwb, 0x60
75 1.2.4.2 wiz set _off_dww, 0x64
76 1.2.4.2 wiz set _off_dwl, 0x68
77 1.2.4.2 wiz
78 1.2.4.2 wiz _060FPSP_TABLE:
79 1.2.4.2 wiz
80 1.2.4.2 wiz ###############################################################
81 1.2.4.2 wiz
82 1.2.4.2 wiz # Here's the table of ENTRY POINTS for those linking the package.
83 1.2.4.2 wiz bra.l _fpsp_snan
84 1.2.4.2 wiz short 0x0000
85 1.2.4.2 wiz bra.l _fpsp_operr
86 1.2.4.2 wiz short 0x0000
87 1.2.4.2 wiz bra.l _fpsp_ovfl
88 1.2.4.2 wiz short 0x0000
89 1.2.4.2 wiz bra.l _fpsp_unfl
90 1.2.4.2 wiz short 0x0000
91 1.2.4.2 wiz bra.l _fpsp_dz
92 1.2.4.2 wiz short 0x0000
93 1.2.4.2 wiz bra.l _fpsp_inex
94 1.2.4.2 wiz short 0x0000
95 1.2.4.2 wiz bra.l _fpsp_fline
96 1.2.4.2 wiz short 0x0000
97 1.2.4.2 wiz bra.l _fpsp_unsupp
98 1.2.4.2 wiz short 0x0000
99 1.2.4.2 wiz bra.l _fpsp_effadd
100 1.2.4.2 wiz short 0x0000
101 1.2.4.2 wiz
102 1.2.4.2 wiz space 56
103 1.2.4.2 wiz
104 1.2.4.2 wiz ###############################################################
105 1.2.4.2 wiz global _fpsp_done
106 1.2.4.2 wiz _fpsp_done:
107 1.2.4.2 wiz mov.l %d0,-(%sp)
108 1.2.4.2 wiz mov.l (_060FPSP_TABLE-0x80+_off_done,%pc),%d0
109 1.2.4.2 wiz pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
110 1.2.4.2 wiz mov.l 0x4(%sp),%d0
111 1.2.4.2 wiz rtd &0x4
112 1.2.4.2 wiz
113 1.2.4.2 wiz global _real_ovfl
114 1.2.4.2 wiz _real_ovfl:
115 1.2.4.2 wiz mov.l %d0,-(%sp)
116 1.2.4.2 wiz mov.l (_060FPSP_TABLE-0x80+_off_ovfl,%pc),%d0
117 1.2.4.2 wiz pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
118 1.2.4.2 wiz mov.l 0x4(%sp),%d0
119 1.2.4.2 wiz rtd &0x4
120 1.2.4.2 wiz
121 1.2.4.2 wiz global _real_unfl
122 1.2.4.2 wiz _real_unfl:
123 1.2.4.2 wiz mov.l %d0,-(%sp)
124 1.2.4.2 wiz mov.l (_060FPSP_TABLE-0x80+_off_unfl,%pc),%d0
125 1.2.4.2 wiz pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
126 1.2.4.2 wiz mov.l 0x4(%sp),%d0
127 1.2.4.2 wiz rtd &0x4
128 1.2.4.2 wiz
129 1.2.4.2 wiz global _real_inex
130 1.2.4.2 wiz _real_inex:
131 1.2.4.2 wiz mov.l %d0,-(%sp)
132 1.2.4.2 wiz mov.l (_060FPSP_TABLE-0x80+_off_inex,%pc),%d0
133 1.2.4.2 wiz pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
134 1.2.4.2 wiz mov.l 0x4(%sp),%d0
135 1.2.4.2 wiz rtd &0x4
136 1.2.4.2 wiz
137 1.2.4.2 wiz global _real_bsun
138 1.2.4.2 wiz _real_bsun:
139 1.2.4.2 wiz mov.l %d0,-(%sp)
140 1.2.4.2 wiz mov.l (_060FPSP_TABLE-0x80+_off_bsun,%pc),%d0
141 1.2.4.2 wiz pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
142 1.2.4.2 wiz mov.l 0x4(%sp),%d0
143 1.2.4.2 wiz rtd &0x4
144 1.2.4.2 wiz
145 1.2.4.2 wiz global _real_operr
146 1.2.4.2 wiz _real_operr:
147 1.2.4.2 wiz mov.l %d0,-(%sp)
148 1.2.4.2 wiz mov.l (_060FPSP_TABLE-0x80+_off_operr,%pc),%d0
149 1.2.4.2 wiz pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
150 1.2.4.2 wiz mov.l 0x4(%sp),%d0
151 1.2.4.2 wiz rtd &0x4
152 1.2.4.2 wiz
153 1.2.4.2 wiz global _real_snan
154 1.2.4.2 wiz _real_snan:
155 1.2.4.2 wiz mov.l %d0,-(%sp)
156 1.2.4.2 wiz mov.l (_060FPSP_TABLE-0x80+_off_snan,%pc),%d0
157 1.2.4.2 wiz pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
158 1.2.4.2 wiz mov.l 0x4(%sp),%d0
159 1.2.4.2 wiz rtd &0x4
160 1.2.4.2 wiz
161 1.2.4.2 wiz global _real_dz
162 1.2.4.2 wiz _real_dz:
163 1.2.4.2 wiz mov.l %d0,-(%sp)
164 1.2.4.2 wiz mov.l (_060FPSP_TABLE-0x80+_off_dz,%pc),%d0
165 1.2.4.2 wiz pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
166 1.2.4.2 wiz mov.l 0x4(%sp),%d0
167 1.2.4.2 wiz rtd &0x4
168 1.2.4.2 wiz
169 1.2.4.2 wiz global _real_fline
170 1.2.4.2 wiz _real_fline:
171 1.2.4.2 wiz mov.l %d0,-(%sp)
172 1.2.4.2 wiz mov.l (_060FPSP_TABLE-0x80+_off_fline,%pc),%d0
173 1.2.4.2 wiz pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
174 1.2.4.2 wiz mov.l 0x4(%sp),%d0
175 1.2.4.2 wiz rtd &0x4
176 1.2.4.2 wiz
177 1.2.4.2 wiz global _real_fpu_disabled
178 1.2.4.2 wiz _real_fpu_disabled:
179 1.2.4.2 wiz mov.l %d0,-(%sp)
180 1.2.4.2 wiz mov.l (_060FPSP_TABLE-0x80+_off_fpu_dis,%pc),%d0
181 1.2.4.2 wiz pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
182 1.2.4.2 wiz mov.l 0x4(%sp),%d0
183 1.2.4.2 wiz rtd &0x4
184 1.2.4.2 wiz
185 1.2.4.2 wiz global _real_trap
186 1.2.4.2 wiz _real_trap:
187 1.2.4.2 wiz mov.l %d0,-(%sp)
188 1.2.4.2 wiz mov.l (_060FPSP_TABLE-0x80+_off_trap,%pc),%d0
189 1.2.4.2 wiz pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
190 1.2.4.2 wiz mov.l 0x4(%sp),%d0
191 1.2.4.2 wiz rtd &0x4
192 1.2.4.2 wiz
193 1.2.4.2 wiz global _real_trace
194 1.2.4.2 wiz _real_trace:
195 1.2.4.2 wiz mov.l %d0,-(%sp)
196 1.2.4.2 wiz mov.l (_060FPSP_TABLE-0x80+_off_trace,%pc),%d0
197 1.2.4.2 wiz pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
198 1.2.4.2 wiz mov.l 0x4(%sp),%d0
199 1.2.4.2 wiz rtd &0x4
200 1.2.4.2 wiz
201 1.2.4.2 wiz global _real_access
202 1.2.4.2 wiz _real_access:
203 1.2.4.2 wiz mov.l %d0,-(%sp)
204 1.2.4.2 wiz mov.l (_060FPSP_TABLE-0x80+_off_access,%pc),%d0
205 1.2.4.2 wiz pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
206 1.2.4.2 wiz mov.l 0x4(%sp),%d0
207 1.2.4.2 wiz rtd &0x4
208 1.2.4.2 wiz
209 1.2.4.2 wiz #######################################
210 1.2.4.2 wiz
211 1.2.4.2 wiz global _imem_read
212 1.2.4.2 wiz _imem_read:
213 1.2.4.2 wiz mov.l %d0,-(%sp)
214 1.2.4.2 wiz mov.l (_060FPSP_TABLE-0x80+_off_imr,%pc),%d0
215 1.2.4.2 wiz pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
216 1.2.4.2 wiz mov.l 0x4(%sp),%d0
217 1.2.4.2 wiz rtd &0x4
218 1.2.4.2 wiz
219 1.2.4.2 wiz global _dmem_read
220 1.2.4.2 wiz _dmem_read:
221 1.2.4.2 wiz mov.l %d0,-(%sp)
222 1.2.4.2 wiz mov.l (_060FPSP_TABLE-0x80+_off_dmr,%pc),%d0
223 1.2.4.2 wiz pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
224 1.2.4.2 wiz mov.l 0x4(%sp),%d0
225 1.2.4.2 wiz rtd &0x4
226 1.2.4.2 wiz
227 1.2.4.2 wiz global _dmem_write
228 1.2.4.2 wiz _dmem_write:
229 1.2.4.2 wiz mov.l %d0,-(%sp)
230 1.2.4.2 wiz mov.l (_060FPSP_TABLE-0x80+_off_dmw,%pc),%d0
231 1.2.4.2 wiz pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
232 1.2.4.2 wiz mov.l 0x4(%sp),%d0
233 1.2.4.2 wiz rtd &0x4
234 1.2.4.2 wiz
235 1.2.4.2 wiz global _imem_read_word
236 1.2.4.2 wiz _imem_read_word:
237 1.2.4.2 wiz mov.l %d0,-(%sp)
238 1.2.4.2 wiz mov.l (_060FPSP_TABLE-0x80+_off_irw,%pc),%d0
239 1.2.4.2 wiz pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
240 1.2.4.2 wiz mov.l 0x4(%sp),%d0
241 1.2.4.2 wiz rtd &0x4
242 1.2.4.2 wiz
243 1.2.4.2 wiz global _imem_read_long
244 1.2.4.2 wiz _imem_read_long:
245 1.2.4.2 wiz mov.l %d0,-(%sp)
246 1.2.4.2 wiz mov.l (_060FPSP_TABLE-0x80+_off_irl,%pc),%d0
247 1.2.4.2 wiz pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
248 1.2.4.2 wiz mov.l 0x4(%sp),%d0
249 1.2.4.2 wiz rtd &0x4
250 1.2.4.2 wiz
251 1.2.4.2 wiz global _dmem_read_byte
252 1.2.4.2 wiz _dmem_read_byte:
253 1.2.4.2 wiz mov.l %d0,-(%sp)
254 1.2.4.2 wiz mov.l (_060FPSP_TABLE-0x80+_off_drb,%pc),%d0
255 1.2.4.2 wiz pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
256 1.2.4.2 wiz mov.l 0x4(%sp),%d0
257 1.2.4.2 wiz rtd &0x4
258 1.2.4.2 wiz
259 1.2.4.2 wiz global _dmem_read_word
260 1.2.4.2 wiz _dmem_read_word:
261 1.2.4.2 wiz mov.l %d0,-(%sp)
262 1.2.4.2 wiz mov.l (_060FPSP_TABLE-0x80+_off_drw,%pc),%d0
263 1.2.4.2 wiz pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
264 1.2.4.2 wiz mov.l 0x4(%sp),%d0
265 1.2.4.2 wiz rtd &0x4
266 1.2.4.2 wiz
267 1.2.4.2 wiz global _dmem_read_long
268 1.2.4.2 wiz _dmem_read_long:
269 1.2.4.2 wiz mov.l %d0,-(%sp)
270 1.2.4.2 wiz mov.l (_060FPSP_TABLE-0x80+_off_drl,%pc),%d0
271 1.2.4.2 wiz pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
272 1.2.4.2 wiz mov.l 0x4(%sp),%d0
273 1.2.4.2 wiz rtd &0x4
274 1.2.4.2 wiz
275 1.2.4.2 wiz global _dmem_write_byte
276 1.2.4.2 wiz _dmem_write_byte:
277 1.2.4.2 wiz mov.l %d0,-(%sp)
278 1.2.4.2 wiz mov.l (_060FPSP_TABLE-0x80+_off_dwb,%pc),%d0
279 1.2.4.2 wiz pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
280 1.2.4.2 wiz mov.l 0x4(%sp),%d0
281 1.2.4.2 wiz rtd &0x4
282 1.2.4.2 wiz
283 1.2.4.2 wiz global _dmem_write_word
284 1.2.4.2 wiz _dmem_write_word:
285 1.2.4.2 wiz mov.l %d0,-(%sp)
286 1.2.4.2 wiz mov.l (_060FPSP_TABLE-0x80+_off_dww,%pc),%d0
287 1.2.4.2 wiz pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
288 1.2.4.2 wiz mov.l 0x4(%sp),%d0
289 1.2.4.2 wiz rtd &0x4
290 1.2.4.2 wiz
291 1.2.4.2 wiz global _dmem_write_long
292 1.2.4.2 wiz _dmem_write_long:
293 1.2.4.2 wiz mov.l %d0,-(%sp)
294 1.2.4.2 wiz mov.l (_060FPSP_TABLE-0x80+_off_dwl,%pc),%d0
295 1.2.4.2 wiz pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
296 1.2.4.2 wiz mov.l 0x4(%sp),%d0
297 1.2.4.2 wiz rtd &0x4
298 1.2.4.2 wiz
299 1.2.4.2 wiz #
300 1.2.4.2 wiz # This file contains a set of define statements for constants
301 1.2.4.2 wiz # in order to promote readability within the corecode itself.
302 1.2.4.2 wiz #
303 1.2.4.2 wiz
304 1.2.4.2 wiz set LOCAL_SIZE, 192 # stack frame size(bytes)
305 1.2.4.2 wiz set LV, -LOCAL_SIZE # stack offset
306 1.2.4.2 wiz
307 1.2.4.2 wiz set EXC_SR, 0x4 # stack status register
308 1.2.4.2 wiz set EXC_PC, 0x6 # stack pc
309 1.2.4.2 wiz set EXC_VOFF, 0xa # stacked vector offset
310 1.2.4.2 wiz set EXC_EA, 0xc # stacked <ea>
311 1.2.4.2 wiz
312 1.2.4.2 wiz set EXC_FP, 0x0 # frame pointer
313 1.2.4.2 wiz
314 1.2.4.2 wiz set EXC_AREGS, -68 # offset of all address regs
315 1.2.4.2 wiz set EXC_DREGS, -100 # offset of all data regs
316 1.2.4.2 wiz set EXC_FPREGS, -36 # offset of all fp regs
317 1.2.4.2 wiz
318 1.2.4.2 wiz set EXC_A7, EXC_AREGS+(7*4) # offset of saved a7
319 1.2.4.2 wiz set OLD_A7, EXC_AREGS+(6*4) # extra copy of saved a7
320 1.2.4.2 wiz set EXC_A6, EXC_AREGS+(6*4) # offset of saved a6
321 1.2.4.2 wiz set EXC_A5, EXC_AREGS+(5*4)
322 1.2.4.2 wiz set EXC_A4, EXC_AREGS+(4*4)
323 1.2.4.2 wiz set EXC_A3, EXC_AREGS+(3*4)
324 1.2.4.2 wiz set EXC_A2, EXC_AREGS+(2*4)
325 1.2.4.2 wiz set EXC_A1, EXC_AREGS+(1*4)
326 1.2.4.2 wiz set EXC_A0, EXC_AREGS+(0*4)
327 1.2.4.2 wiz set EXC_D7, EXC_DREGS+(7*4)
328 1.2.4.2 wiz set EXC_D6, EXC_DREGS+(6*4)
329 1.2.4.2 wiz set EXC_D5, EXC_DREGS+(5*4)
330 1.2.4.2 wiz set EXC_D4, EXC_DREGS+(4*4)
331 1.2.4.2 wiz set EXC_D3, EXC_DREGS+(3*4)
332 1.2.4.2 wiz set EXC_D2, EXC_DREGS+(2*4)
333 1.2.4.2 wiz set EXC_D1, EXC_DREGS+(1*4)
334 1.2.4.2 wiz set EXC_D0, EXC_DREGS+(0*4)
335 1.2.4.2 wiz
336 1.2.4.2 wiz set EXC_FP0, EXC_FPREGS+(0*12) # offset of saved fp0
337 1.2.4.2 wiz set EXC_FP1, EXC_FPREGS+(1*12) # offset of saved fp1
338 1.2.4.2 wiz set EXC_FP2, EXC_FPREGS+(2*12) # offset of saved fp2 (not used)
339 1.2.4.2 wiz
340 1.2.4.2 wiz set FP_SCR1, LV+80 # fp scratch 1
341 1.2.4.2 wiz set FP_SCR1_EX, FP_SCR1+0
342 1.2.4.2 wiz set FP_SCR1_SGN, FP_SCR1+2
343 1.2.4.2 wiz set FP_SCR1_HI, FP_SCR1+4
344 1.2.4.2 wiz set FP_SCR1_LO, FP_SCR1+8
345 1.2.4.2 wiz
346 1.2.4.2 wiz set FP_SCR0, LV+68 # fp scratch 0
347 1.2.4.2 wiz set FP_SCR0_EX, FP_SCR0+0
348 1.2.4.2 wiz set FP_SCR0_SGN, FP_SCR0+2
349 1.2.4.2 wiz set FP_SCR0_HI, FP_SCR0+4
350 1.2.4.2 wiz set FP_SCR0_LO, FP_SCR0+8
351 1.2.4.2 wiz
352 1.2.4.2 wiz set FP_DST, LV+56 # fp destination operand
353 1.2.4.2 wiz set FP_DST_EX, FP_DST+0
354 1.2.4.2 wiz set FP_DST_SGN, FP_DST+2
355 1.2.4.2 wiz set FP_DST_HI, FP_DST+4
356 1.2.4.2 wiz set FP_DST_LO, FP_DST+8
357 1.2.4.2 wiz
358 1.2.4.2 wiz set FP_SRC, LV+44 # fp source operand
359 1.2.4.2 wiz set FP_SRC_EX, FP_SRC+0
360 1.2.4.2 wiz set FP_SRC_SGN, FP_SRC+2
361 1.2.4.2 wiz set FP_SRC_HI, FP_SRC+4
362 1.2.4.2 wiz set FP_SRC_LO, FP_SRC+8
363 1.2.4.2 wiz
364 1.2.4.2 wiz set USER_FPIAR, LV+40 # FP instr address register
365 1.2.4.2 wiz
366 1.2.4.2 wiz set USER_FPSR, LV+36 # FP status register
367 1.2.4.2 wiz set FPSR_CC, USER_FPSR+0 # FPSR condition codes
368 1.2.4.2 wiz set FPSR_QBYTE, USER_FPSR+1 # FPSR qoutient byte
369 1.2.4.2 wiz set FPSR_EXCEPT, USER_FPSR+2 # FPSR exception status byte
370 1.2.4.2 wiz set FPSR_AEXCEPT, USER_FPSR+3 # FPSR accrued exception byte
371 1.2.4.2 wiz
372 1.2.4.2 wiz set USER_FPCR, LV+32 # FP control register
373 1.2.4.2 wiz set FPCR_ENABLE, USER_FPCR+2 # FPCR exception enable
374 1.2.4.2 wiz set FPCR_MODE, USER_FPCR+3 # FPCR rounding mode control
375 1.2.4.2 wiz
376 1.2.4.2 wiz set L_SCR3, LV+28 # integer scratch 3
377 1.2.4.2 wiz set L_SCR2, LV+24 # integer scratch 2
378 1.2.4.2 wiz set L_SCR1, LV+20 # integer scratch 1
379 1.2.4.2 wiz
380 1.2.4.2 wiz set STORE_FLG, LV+19 # flag: operand store (ie. not fcmp/ftst)
381 1.2.4.2 wiz
382 1.2.4.2 wiz set EXC_TEMP2, LV+24 # temporary space
383 1.2.4.2 wiz set EXC_TEMP, LV+16 # temporary space
384 1.2.4.2 wiz
385 1.2.4.2 wiz set DTAG, LV+15 # destination operand type
386 1.2.4.2 wiz set STAG, LV+14 # source operand type
387 1.2.4.2 wiz
388 1.2.4.2 wiz set SPCOND_FLG, LV+10 # flag: special case (see below)
389 1.2.4.2 wiz
390 1.2.4.2 wiz set EXC_CC, LV+8 # saved condition codes
391 1.2.4.2 wiz set EXC_EXTWPTR, LV+4 # saved current PC (active)
392 1.2.4.2 wiz set EXC_EXTWORD, LV+2 # saved extension word
393 1.2.4.2 wiz set EXC_CMDREG, LV+2 # saved extension word
394 1.2.4.2 wiz set EXC_OPWORD, LV+0 # saved operation word
395 1.2.4.2 wiz
396 1.2.4.2 wiz ################################
397 1.2.4.2 wiz
398 1.2.4.2 wiz # Helpful macros
399 1.2.4.2 wiz
400 1.2.4.2 wiz set FTEMP, 0 # offsets within an
401 1.2.4.2 wiz set FTEMP_EX, 0 # extended precision
402 1.2.4.2 wiz set FTEMP_SGN, 2 # value saved in memory.
403 1.2.4.2 wiz set FTEMP_HI, 4
404 1.2.4.2 wiz set FTEMP_LO, 8
405 1.2.4.2 wiz set FTEMP_GRS, 12
406 1.2.4.2 wiz
407 1.2.4.2 wiz set LOCAL, 0 # offsets within an
408 1.2.4.2 wiz set LOCAL_EX, 0 # extended precision
409 1.2.4.2 wiz set LOCAL_SGN, 2 # value saved in memory.
410 1.2.4.2 wiz set LOCAL_HI, 4
411 1.2.4.2 wiz set LOCAL_LO, 8
412 1.2.4.2 wiz set LOCAL_GRS, 12
413 1.2.4.2 wiz
414 1.2.4.2 wiz set DST, 0 # offsets within an
415 1.2.4.2 wiz set DST_EX, 0 # extended precision
416 1.2.4.2 wiz set DST_HI, 4 # value saved in memory.
417 1.2.4.2 wiz set DST_LO, 8
418 1.2.4.2 wiz
419 1.2.4.2 wiz set SRC, 0 # offsets within an
420 1.2.4.2 wiz set SRC_EX, 0 # extended precision
421 1.2.4.2 wiz set SRC_HI, 4 # value saved in memory.
422 1.2.4.2 wiz set SRC_LO, 8
423 1.2.4.2 wiz
424 1.2.4.2 wiz set SGL_LO, 0x3f81 # min sgl prec exponent
425 1.2.4.2 wiz set SGL_HI, 0x407e # max sgl prec exponent
426 1.2.4.2 wiz set DBL_LO, 0x3c01 # min dbl prec exponent
427 1.2.4.2 wiz set DBL_HI, 0x43fe # max dbl prec exponent
428 1.2.4.2 wiz set EXT_LO, 0x0 # min ext prec exponent
429 1.2.4.2 wiz set EXT_HI, 0x7ffe # max ext prec exponent
430 1.2.4.2 wiz
431 1.2.4.2 wiz set EXT_BIAS, 0x3fff # extended precision bias
432 1.2.4.2 wiz set SGL_BIAS, 0x007f # single precision bias
433 1.2.4.2 wiz set DBL_BIAS, 0x03ff # double precision bias
434 1.2.4.2 wiz
435 1.2.4.2 wiz set NORM, 0x00 # operand type for STAG/DTAG
436 1.2.4.2 wiz set ZERO, 0x01 # operand type for STAG/DTAG
437 1.2.4.2 wiz set INF, 0x02 # operand type for STAG/DTAG
438 1.2.4.2 wiz set QNAN, 0x03 # operand type for STAG/DTAG
439 1.2.4.2 wiz set DENORM, 0x04 # operand type for STAG/DTAG
440 1.2.4.2 wiz set SNAN, 0x05 # operand type for STAG/DTAG
441 1.2.4.2 wiz set UNNORM, 0x06 # operand type for STAG/DTAG
442 1.2.4.2 wiz
443 1.2.4.2 wiz ##################
444 1.2.4.2 wiz # FPSR/FPCR bits #
445 1.2.4.2 wiz ##################
446 1.2.4.2 wiz set neg_bit, 0x3 # negative result
447 1.2.4.2 wiz set z_bit, 0x2 # zero result
448 1.2.4.2 wiz set inf_bit, 0x1 # infinite result
449 1.2.4.2 wiz set nan_bit, 0x0 # NAN result
450 1.2.4.2 wiz
451 1.2.4.2 wiz set q_sn_bit, 0x7 # sign bit of quotient byte
452 1.2.4.2 wiz
453 1.2.4.2 wiz set bsun_bit, 7 # branch on unordered
454 1.2.4.2 wiz set snan_bit, 6 # signalling NAN
455 1.2.4.2 wiz set operr_bit, 5 # operand error
456 1.2.4.2 wiz set ovfl_bit, 4 # overflow
457 1.2.4.2 wiz set unfl_bit, 3 # underflow
458 1.2.4.2 wiz set dz_bit, 2 # divide by zero
459 1.2.4.2 wiz set inex2_bit, 1 # inexact result 2
460 1.2.4.2 wiz set inex1_bit, 0 # inexact result 1
461 1.2.4.2 wiz
462 1.2.4.2 wiz set aiop_bit, 7 # accrued inexact operation bit
463 1.2.4.2 wiz set aovfl_bit, 6 # accrued overflow bit
464 1.2.4.2 wiz set aunfl_bit, 5 # accrued underflow bit
465 1.2.4.2 wiz set adz_bit, 4 # accrued dz bit
466 1.2.4.2 wiz set ainex_bit, 3 # accrued inexact bit
467 1.2.4.2 wiz
468 1.2.4.2 wiz #############################
469 1.2.4.2 wiz # FPSR individual bit masks #
470 1.2.4.2 wiz #############################
471 1.2.4.2 wiz set neg_mask, 0x08000000 # negative bit mask (lw)
472 1.2.4.2 wiz set inf_mask, 0x02000000 # infinity bit mask (lw)
473 1.2.4.2 wiz set z_mask, 0x04000000 # zero bit mask (lw)
474 1.2.4.2 wiz set nan_mask, 0x01000000 # nan bit mask (lw)
475 1.2.4.2 wiz
476 1.2.4.2 wiz set neg_bmask, 0x08 # negative bit mask (byte)
477 1.2.4.2 wiz set inf_bmask, 0x02 # infinity bit mask (byte)
478 1.2.4.2 wiz set z_bmask, 0x04 # zero bit mask (byte)
479 1.2.4.2 wiz set nan_bmask, 0x01 # nan bit mask (byte)
480 1.2.4.2 wiz
481 1.2.4.2 wiz set bsun_mask, 0x00008000 # bsun exception mask
482 1.2.4.2 wiz set snan_mask, 0x00004000 # snan exception mask
483 1.2.4.2 wiz set operr_mask, 0x00002000 # operr exception mask
484 1.2.4.2 wiz set ovfl_mask, 0x00001000 # overflow exception mask
485 1.2.4.2 wiz set unfl_mask, 0x00000800 # underflow exception mask
486 1.2.4.2 wiz set dz_mask, 0x00000400 # dz exception mask
487 1.2.4.2 wiz set inex2_mask, 0x00000200 # inex2 exception mask
488 1.2.4.2 wiz set inex1_mask, 0x00000100 # inex1 exception mask
489 1.2.4.2 wiz
490 1.2.4.2 wiz set aiop_mask, 0x00000080 # accrued illegal operation
491 1.2.4.2 wiz set aovfl_mask, 0x00000040 # accrued overflow
492 1.2.4.2 wiz set aunfl_mask, 0x00000020 # accrued underflow
493 1.2.4.2 wiz set adz_mask, 0x00000010 # accrued divide by zero
494 1.2.4.2 wiz set ainex_mask, 0x00000008 # accrued inexact
495 1.2.4.2 wiz
496 1.2.4.2 wiz ######################################
497 1.2.4.2 wiz # FPSR combinations used in the FPSP #
498 1.2.4.2 wiz ######################################
499 1.2.4.2 wiz set dzinf_mask, inf_mask+dz_mask+adz_mask
500 1.2.4.2 wiz set opnan_mask, nan_mask+operr_mask+aiop_mask
501 1.2.4.2 wiz set nzi_mask, 0x01ffffff #clears N, Z, and I
502 1.2.4.2 wiz set unfinx_mask, unfl_mask+inex2_mask+aunfl_mask+ainex_mask
503 1.2.4.2 wiz set unf2inx_mask, unfl_mask+inex2_mask+ainex_mask
504 1.2.4.2 wiz set ovfinx_mask, ovfl_mask+inex2_mask+aovfl_mask+ainex_mask
505 1.2.4.2 wiz set inx1a_mask, inex1_mask+ainex_mask
506 1.2.4.2 wiz set inx2a_mask, inex2_mask+ainex_mask
507 1.2.4.2 wiz set snaniop_mask, nan_mask+snan_mask+aiop_mask
508 1.2.4.2 wiz set snaniop2_mask, snan_mask+aiop_mask
509 1.2.4.2 wiz set naniop_mask, nan_mask+aiop_mask
510 1.2.4.2 wiz set neginf_mask, neg_mask+inf_mask
511 1.2.4.2 wiz set infaiop_mask, inf_mask+aiop_mask
512 1.2.4.2 wiz set negz_mask, neg_mask+z_mask
513 1.2.4.2 wiz set opaop_mask, operr_mask+aiop_mask
514 1.2.4.2 wiz set unfl_inx_mask, unfl_mask+aunfl_mask+ainex_mask
515 1.2.4.2 wiz set ovfl_inx_mask, ovfl_mask+aovfl_mask+ainex_mask
516 1.2.4.2 wiz
517 1.2.4.2 wiz #########
518 1.2.4.2 wiz # misc. #
519 1.2.4.2 wiz #########
520 1.2.4.2 wiz set rnd_stky_bit, 29 # stky bit pos in longword
521 1.2.4.2 wiz
522 1.2.4.2 wiz set sign_bit, 0x7 # sign bit
523 1.2.4.2 wiz set signan_bit, 0x6 # signalling nan bit
524 1.2.4.2 wiz
525 1.2.4.2 wiz set sgl_thresh, 0x3f81 # minimum sgl exponent
526 1.2.4.2 wiz set dbl_thresh, 0x3c01 # minimum dbl exponent
527 1.2.4.2 wiz
528 1.2.4.2 wiz set x_mode, 0x0 # extended precision
529 1.2.4.2 wiz set s_mode, 0x4 # single precision
530 1.2.4.2 wiz set d_mode, 0x8 # double precision
531 1.2.4.2 wiz
532 1.2.4.2 wiz set rn_mode, 0x0 # round-to-nearest
533 1.2.4.2 wiz set rz_mode, 0x1 # round-to-zero
534 1.2.4.2 wiz set rm_mode, 0x2 # round-tp-minus-infinity
535 1.2.4.2 wiz set rp_mode, 0x3 # round-to-plus-infinity
536 1.2.4.2 wiz
537 1.2.4.2 wiz set mantissalen, 64 # length of mantissa in bits
538 1.2.4.2 wiz
539 1.2.4.2 wiz set BYTE, 1 # len(byte) == 1 byte
540 1.2.4.2 wiz set WORD, 2 # len(word) == 2 bytes
541 1.2.4.2 wiz set LONG, 4 # len(longword) == 2 bytes
542 1.2.4.2 wiz
543 1.2.4.2 wiz set BSUN_VEC, 0xc0 # bsun vector offset
544 1.2.4.2 wiz set INEX_VEC, 0xc4 # inexact vector offset
545 1.2.4.2 wiz set DZ_VEC, 0xc8 # dz vector offset
546 1.2.4.2 wiz set UNFL_VEC, 0xcc # unfl vector offset
547 1.2.4.2 wiz set OPERR_VEC, 0xd0 # operr vector offset
548 1.2.4.2 wiz set OVFL_VEC, 0xd4 # ovfl vector offset
549 1.2.4.2 wiz set SNAN_VEC, 0xd8 # snan vector offset
550 1.2.4.2 wiz
551 1.2.4.2 wiz ###########################
552 1.2.4.2 wiz # SPecial CONDition FLaGs #
553 1.2.4.2 wiz ###########################
554 1.2.4.2 wiz set ftrapcc_flg, 0x01 # flag bit: ftrapcc exception
555 1.2.4.2 wiz set fbsun_flg, 0x02 # flag bit: bsun exception
556 1.2.4.2 wiz set mia7_flg, 0x04 # flag bit: (a7)+ <ea>
557 1.2.4.2 wiz set mda7_flg, 0x08 # flag bit: -(a7) <ea>
558 1.2.4.2 wiz set fmovm_flg, 0x40 # flag bit: fmovm instruction
559 1.2.4.2 wiz set immed_flg, 0x80 # flag bit: &<data> <ea>
560 1.2.4.2 wiz
561 1.2.4.2 wiz set ftrapcc_bit, 0x0
562 1.2.4.2 wiz set fbsun_bit, 0x1
563 1.2.4.2 wiz set mia7_bit, 0x2
564 1.2.4.2 wiz set mda7_bit, 0x3
565 1.2.4.2 wiz set immed_bit, 0x7
566 1.2.4.2 wiz
567 1.2.4.2 wiz ##################################
568 1.2.4.2 wiz # TRANSCENDENTAL "LAST-OP" FLAGS #
569 1.2.4.2 wiz ##################################
570 1.2.4.2 wiz set FMUL_OP, 0x0 # fmul instr performed last
571 1.2.4.2 wiz set FDIV_OP, 0x1 # fdiv performed last
572 1.2.4.2 wiz set FADD_OP, 0x2 # fadd performed last
573 1.2.4.2 wiz set FMOV_OP, 0x3 # fmov performed last
574 1.2.4.2 wiz
575 1.2.4.2 wiz #############
576 1.2.4.2 wiz # CONSTANTS #
577 1.2.4.2 wiz #############
578 1.2.4.2 wiz T1: long 0x40C62D38,0xD3D64634 # 16381 LOG2 LEAD
579 1.2.4.2 wiz T2: long 0x3D6F90AE,0xB1E75CC7 # 16381 LOG2 TRAIL
580 1.2.4.2 wiz
581 1.2.4.2 wiz PI: long 0x40000000,0xC90FDAA2,0x2168C235,0x00000000
582 1.2.4.2 wiz PIBY2: long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
583 1.2.4.2 wiz
584 1.2.4.2 wiz TWOBYPI:
585 1.2.4.2 wiz long 0x3FE45F30,0x6DC9C883
586 1.2.4.2 wiz
587 1.2.4.2 wiz #########################################################################
588 1.2.4.2 wiz # XDEF **************************************************************** #
589 1.2.4.2 wiz # _fpsp_ovfl(): 060FPSP entry point for FP Overflow exception. #
590 1.2.4.2 wiz # #
591 1.2.4.2 wiz # This handler should be the first code executed upon taking the #
592 1.2.4.2 wiz # FP Overflow exception in an operating system. #
593 1.2.4.2 wiz # #
594 1.2.4.2 wiz # XREF **************************************************************** #
595 1.2.4.2 wiz # _imem_read_long() - read instruction longword #
596 1.2.4.2 wiz # fix_skewed_ops() - adjust src operand in fsave frame #
597 1.2.4.2 wiz # set_tag_x() - determine optype of src/dst operands #
598 1.2.4.2 wiz # store_fpreg() - store opclass 0 or 2 result to FP regfile #
599 1.2.4.2 wiz # unnorm_fix() - change UNNORM operands to NORM or ZERO #
600 1.2.4.2 wiz # load_fpn2() - load dst operand from FP regfile #
601 1.2.4.2 wiz # fout() - emulate an opclass 3 instruction #
602 1.2.4.2 wiz # tbl_unsupp - add of table of emulation routines for opclass 0,2 #
603 1.2.4.2 wiz # _fpsp_done() - "callout" for 060FPSP exit (all work done!) #
604 1.2.4.2 wiz # _real_ovfl() - "callout" for Overflow exception enabled code #
605 1.2.4.2 wiz # _real_inex() - "callout" for Inexact exception enabled code #
606 1.2.4.2 wiz # _real_trace() - "callout" for Trace exception code #
607 1.2.4.2 wiz # #
608 1.2.4.2 wiz # INPUT *************************************************************** #
609 1.2.4.2 wiz # - The system stack contains the FP Ovfl exception stack frame #
610 1.2.4.2 wiz # - The fsave frame contains the source operand #
611 1.2.4.2 wiz # #
612 1.2.4.2 wiz # OUTPUT ************************************************************** #
613 1.2.4.2 wiz # Overflow Exception enabled: #
614 1.2.4.2 wiz # - The system stack is unchanged #
615 1.2.4.2 wiz # - The fsave frame contains the adjusted src op for opclass 0,2 #
616 1.2.4.2 wiz # Overflow Exception disabled: #
617 1.2.4.2 wiz # - The system stack is unchanged #
618 1.2.4.2 wiz # - The "exception present" flag in the fsave frame is cleared #
619 1.2.4.2 wiz # #
620 1.2.4.2 wiz # ALGORITHM *********************************************************** #
621 1.2.4.2 wiz # On the 060, if an FP overflow is present as the result of any #
622 1.2.4.2 wiz # instruction, the 060 will take an overflow exception whether the #
623 1.2.4.2 wiz # exception is enabled or disabled in the FPCR. For the disabled case, #
624 1.2.4.2 wiz # This handler emulates the instruction to determine what the correct #
625 1.2.4.2 wiz # default result should be for the operation. This default result is #
626 1.2.4.2 wiz # then stored in either the FP regfile, data regfile, or memory. #
627 1.2.4.2 wiz # Finally, the handler exits through the "callout" _fpsp_done() #
628 1.2.4.2 wiz # denoting that no exceptional conditions exist within the machine. #
629 1.2.4.2 wiz # If the exception is enabled, then this handler must create the #
630 1.2.4.2 wiz # exceptional operand and plave it in the fsave state frame, and store #
631 1.2.4.2 wiz # the default result (only if the instruction is opclass 3). For #
632 1.2.4.2 wiz # exceptions enabled, this handler must exit through the "callout" #
633 1.2.4.2 wiz # _real_ovfl() so that the operating system enabled overflow handler #
634 1.2.4.2 wiz # can handle this case. #
635 1.2.4.2 wiz # Two other conditions exist. First, if overflow was disabled #
636 1.2.4.2 wiz # but the inexact exception was enabled, this handler must exit #
637 1.2.4.2 wiz # through the "callout" _real_inex() regardless of whether the result #
638 1.2.4.2 wiz # was inexact. #
639 1.2.4.2 wiz # Also, in the case of an opclass three instruction where #
640 1.2.4.2 wiz # overflow was disabled and the trace exception was enabled, this #
641 1.2.4.2 wiz # handler must exit through the "callout" _real_trace(). #
642 1.2.4.2 wiz # #
643 1.2.4.2 wiz #########################################################################
644 1.2.4.2 wiz
645 1.2.4.2 wiz global _fpsp_ovfl
646 1.2.4.2 wiz _fpsp_ovfl:
647 1.2.4.2 wiz
648 1.2.4.2 wiz #$# sub.l &24,%sp # make room for src/dst
649 1.2.4.2 wiz
650 1.2.4.2 wiz link.w %a6,&-LOCAL_SIZE # init stack frame
651 1.2.4.2 wiz
652 1.2.4.2 wiz fsave FP_SRC(%a6) # grab the "busy" frame
653 1.2.4.2 wiz
654 1.2.4.2 wiz movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
655 1.2.4.2 wiz fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
656 1.2.4.2 wiz fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
657 1.2.4.2 wiz
658 1.2.4.2 wiz # the FPIAR holds the "current PC" of the faulting instruction
659 1.2.4.2 wiz mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
660 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
661 1.2.4.2 wiz addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
662 1.2.4.2 wiz bsr.l _imem_read_long # fetch the instruction words
663 1.2.4.2 wiz mov.l %d0,EXC_OPWORD(%a6)
664 1.2.4.2 wiz
665 1.2.4.2 wiz ##############################################################################
666 1.2.4.2 wiz
667 1.2.4.2 wiz btst &0x5,EXC_CMDREG(%a6) # is instr an fmove out?
668 1.2.4.2 wiz bne.w fovfl_out
669 1.2.4.2 wiz
670 1.2.4.2 wiz
671 1.2.4.2 wiz lea FP_SRC(%a6),%a0 # pass: ptr to src op
672 1.2.4.2 wiz bsr.l fix_skewed_ops # fix src op
673 1.2.4.2 wiz
674 1.2.4.2 wiz # since, I believe, only NORMs and DENORMs can come through here,
675 1.2.4.2 wiz # maybe we can avoid the subroutine call.
676 1.2.4.2 wiz lea FP_SRC(%a6),%a0 # pass: ptr to src op
677 1.2.4.2 wiz bsr.l set_tag_x # tag the operand type
678 1.2.4.2 wiz mov.b %d0,STAG(%a6) # maybe NORM,DENORM
679 1.2.4.2 wiz
680 1.2.4.2 wiz # bit five of the fp extension word separates the monadic and dyadic operations
681 1.2.4.2 wiz # that can pass through fpsp_ovfl(). remember that fcmp, ftst, and fsincos
682 1.2.4.2 wiz # will never take this exception.
683 1.2.4.2 wiz btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic?
684 1.2.4.2 wiz beq.b fovfl_extract # monadic
685 1.2.4.2 wiz
686 1.2.4.2 wiz bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
687 1.2.4.2 wiz bsr.l load_fpn2 # load dst into FP_DST
688 1.2.4.2 wiz
689 1.2.4.2 wiz lea FP_DST(%a6),%a0 # pass: ptr to dst op
690 1.2.4.2 wiz bsr.l set_tag_x # tag the operand type
691 1.2.4.2 wiz cmpi.b %d0,&UNNORM # is operand an UNNORM?
692 1.2.4.2 wiz bne.b fovfl_op2_done # no
693 1.2.4.2 wiz bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
694 1.2.4.2 wiz fovfl_op2_done:
695 1.2.4.2 wiz mov.b %d0,DTAG(%a6) # save dst optype tag
696 1.2.4.2 wiz
697 1.2.4.2 wiz fovfl_extract:
698 1.2.4.2 wiz
699 1.2.4.2 wiz #$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
700 1.2.4.2 wiz #$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
701 1.2.4.2 wiz #$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
702 1.2.4.2 wiz #$# mov.l FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6)
703 1.2.4.2 wiz #$# mov.l FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6)
704 1.2.4.2 wiz #$# mov.l FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6)
705 1.2.4.2 wiz
706 1.2.4.2 wiz clr.l %d0
707 1.2.4.2 wiz mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
708 1.2.4.2 wiz
709 1.2.4.2 wiz mov.b 1+EXC_CMDREG(%a6),%d1
710 1.2.4.2 wiz andi.w &0x007f,%d1 # extract extension
711 1.2.4.2 wiz
712 1.2.4.2 wiz andi.l &0x00ff01ff,USER_FPSR(%a6) # zero all but accured field
713 1.2.4.2 wiz
714 1.2.4.2 wiz fmov.l &0x0,%fpcr # zero current control regs
715 1.2.4.2 wiz fmov.l &0x0,%fpsr
716 1.2.4.2 wiz
717 1.2.4.2 wiz lea FP_SRC(%a6),%a0
718 1.2.4.2 wiz lea FP_DST(%a6),%a1
719 1.2.4.2 wiz
720 1.2.4.2 wiz # maybe we can make these entry points ONLY the OVFL entry points of each routine.
721 1.2.4.2 wiz mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
722 1.2.4.2 wiz jsr (tbl_unsupp.l,%pc,%d1.l*1)
723 1.2.4.2 wiz
724 1.2.4.2 wiz # the operation has been emulated. the result is in fp0.
725 1.2.4.2 wiz # the EXOP, if an exception occurred, is in fp1.
726 1.2.4.2 wiz # we must save the default result regardless of whether
727 1.2.4.2 wiz # traps are enabled or disabled.
728 1.2.4.2 wiz bfextu EXC_CMDREG(%a6){&6:&3},%d0
729 1.2.4.2 wiz bsr.l store_fpreg
730 1.2.4.2 wiz
731 1.2.4.2 wiz # the exceptional possibilities we have left ourselves with are ONLY overflow
732 1.2.4.2 wiz # and inexact. and, the inexact is such that overflow occurred and was disabled
733 1.2.4.2 wiz # but inexact was enabled.
734 1.2.4.2 wiz btst &ovfl_bit,FPCR_ENABLE(%a6)
735 1.2.4.2 wiz bne.b fovfl_ovfl_on
736 1.2.4.2 wiz
737 1.2.4.2 wiz btst &inex2_bit,FPCR_ENABLE(%a6)
738 1.2.4.2 wiz bne.b fovfl_inex_on
739 1.2.4.2 wiz
740 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
741 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
742 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
743 1.2.4.2 wiz
744 1.2.4.2 wiz unlk %a6
745 1.2.4.2 wiz #$# add.l &24,%sp
746 1.2.4.2 wiz bra.l _fpsp_done
747 1.2.4.2 wiz
748 1.2.4.2 wiz # overflow is enabled AND overflow, of course, occurred. so, we have the EXOP
749 1.2.4.2 wiz # in fp1. now, simply jump to _real_ovfl()!
750 1.2.4.2 wiz fovfl_ovfl_on:
751 1.2.4.2 wiz fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack
752 1.2.4.2 wiz
753 1.2.4.2 wiz mov.w &0xe005,2+FP_SRC(%a6) # save exc status
754 1.2.4.2 wiz
755 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
756 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
757 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
758 1.2.4.2 wiz
759 1.2.4.2 wiz frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
760 1.2.4.2 wiz
761 1.2.4.2 wiz unlk %a6
762 1.2.4.2 wiz
763 1.2.4.2 wiz bra.l _real_ovfl
764 1.2.4.2 wiz
765 1.2.4.2 wiz # overflow occurred but is disabled. meanwhile, inexact is enabled. therefore,
766 1.2.4.2 wiz # we must jump to real_inex().
767 1.2.4.2 wiz fovfl_inex_on:
768 1.2.4.2 wiz
769 1.2.4.2 wiz fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack
770 1.2.4.2 wiz
771 1.2.4.2 wiz mov.b &0xc4,1+EXC_VOFF(%a6) # vector offset = 0xc4
772 1.2.4.2 wiz mov.w &0xe001,2+FP_SRC(%a6) # save exc status
773 1.2.4.2 wiz
774 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
775 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
776 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
777 1.2.4.2 wiz
778 1.2.4.2 wiz frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
779 1.2.4.2 wiz
780 1.2.4.2 wiz unlk %a6
781 1.2.4.2 wiz
782 1.2.4.2 wiz bra.l _real_inex
783 1.2.4.2 wiz
784 1.2.4.2 wiz ########################################################################
785 1.2.4.2 wiz fovfl_out:
786 1.2.4.2 wiz
787 1.2.4.2 wiz
788 1.2.4.2 wiz #$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
789 1.2.4.2 wiz #$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
790 1.2.4.2 wiz #$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
791 1.2.4.2 wiz
792 1.2.4.2 wiz # the src operand is definitely a NORM(!), so tag it as such
793 1.2.4.2 wiz mov.b &NORM,STAG(%a6) # set src optype tag
794 1.2.4.2 wiz
795 1.2.4.2 wiz clr.l %d0
796 1.2.4.2 wiz mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
797 1.2.4.2 wiz
798 1.2.4.2 wiz and.l &0xffff00ff,USER_FPSR(%a6) # zero all but accured field
799 1.2.4.2 wiz
800 1.2.4.2 wiz fmov.l &0x0,%fpcr # zero current control regs
801 1.2.4.2 wiz fmov.l &0x0,%fpsr
802 1.2.4.2 wiz
803 1.2.4.2 wiz lea FP_SRC(%a6),%a0 # pass ptr to src operand
804 1.2.4.2 wiz
805 1.2.4.2 wiz bsr.l fout
806 1.2.4.2 wiz
807 1.2.4.2 wiz btst &ovfl_bit,FPCR_ENABLE(%a6)
808 1.2.4.2 wiz bne.w fovfl_ovfl_on
809 1.2.4.2 wiz
810 1.2.4.2 wiz btst &inex2_bit,FPCR_ENABLE(%a6)
811 1.2.4.2 wiz bne.w fovfl_inex_on
812 1.2.4.2 wiz
813 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
814 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
815 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
816 1.2.4.2 wiz
817 1.2.4.2 wiz unlk %a6
818 1.2.4.2 wiz #$# add.l &24,%sp
819 1.2.4.2 wiz
820 1.2.4.2 wiz btst &0x7,(%sp) # is trace on?
821 1.2.4.2 wiz beq.l _fpsp_done # no
822 1.2.4.2 wiz
823 1.2.4.2 wiz fmov.l %fpiar,0x8(%sp) # "Current PC" is in FPIAR
824 1.2.4.2 wiz mov.w &0x2024,0x6(%sp) # stk fmt = 0x2; voff = 0x024
825 1.2.4.2 wiz bra.l _real_trace
826 1.2.4.2 wiz
827 1.2.4.2 wiz #########################################################################
828 1.2.4.2 wiz # XDEF **************************************************************** #
829 1.2.4.2 wiz # _fpsp_unfl(): 060FPSP entry point for FP Underflow exception. #
830 1.2.4.2 wiz # #
831 1.2.4.2 wiz # This handler should be the first code executed upon taking the #
832 1.2.4.2 wiz # FP Underflow exception in an operating system. #
833 1.2.4.2 wiz # #
834 1.2.4.2 wiz # XREF **************************************************************** #
835 1.2.4.2 wiz # _imem_read_long() - read instruction longword #
836 1.2.4.2 wiz # fix_skewed_ops() - adjust src operand in fsave frame #
837 1.2.4.2 wiz # set_tag_x() - determine optype of src/dst operands #
838 1.2.4.2 wiz # store_fpreg() - store opclass 0 or 2 result to FP regfile #
839 1.2.4.2 wiz # unnorm_fix() - change UNNORM operands to NORM or ZERO #
840 1.2.4.2 wiz # load_fpn2() - load dst operand from FP regfile #
841 1.2.4.2 wiz # fout() - emulate an opclass 3 instruction #
842 1.2.4.2 wiz # tbl_unsupp - add of table of emulation routines for opclass 0,2 #
843 1.2.4.2 wiz # _fpsp_done() - "callout" for 060FPSP exit (all work done!) #
844 1.2.4.2 wiz # _real_ovfl() - "callout" for Overflow exception enabled code #
845 1.2.4.2 wiz # _real_inex() - "callout" for Inexact exception enabled code #
846 1.2.4.2 wiz # _real_trace() - "callout" for Trace exception code #
847 1.2.4.2 wiz # #
848 1.2.4.2 wiz # INPUT *************************************************************** #
849 1.2.4.2 wiz # - The system stack contains the FP Unfl exception stack frame #
850 1.2.4.2 wiz # - The fsave frame contains the source operand #
851 1.2.4.2 wiz # #
852 1.2.4.2 wiz # OUTPUT ************************************************************** #
853 1.2.4.2 wiz # Underflow Exception enabled: #
854 1.2.4.2 wiz # - The system stack is unchanged #
855 1.2.4.2 wiz # - The fsave frame contains the adjusted src op for opclass 0,2 #
856 1.2.4.2 wiz # Underflow Exception disabled: #
857 1.2.4.2 wiz # - The system stack is unchanged #
858 1.2.4.2 wiz # - The "exception present" flag in the fsave frame is cleared #
859 1.2.4.2 wiz # #
860 1.2.4.2 wiz # ALGORITHM *********************************************************** #
861 1.2.4.2 wiz # On the 060, if an FP underflow is present as the result of any #
862 1.2.4.2 wiz # instruction, the 060 will take an underflow exception whether the #
863 1.2.4.2 wiz # exception is enabled or disabled in the FPCR. For the disabled case, #
864 1.2.4.2 wiz # This handler emulates the instruction to determine what the correct #
865 1.2.4.2 wiz # default result should be for the operation. This default result is #
866 1.2.4.2 wiz # then stored in either the FP regfile, data regfile, or memory. #
867 1.2.4.2 wiz # Finally, the handler exits through the "callout" _fpsp_done() #
868 1.2.4.2 wiz # denoting that no exceptional conditions exist within the machine. #
869 1.2.4.2 wiz # If the exception is enabled, then this handler must create the #
870 1.2.4.2 wiz # exceptional operand and plave it in the fsave state frame, and store #
871 1.2.4.2 wiz # the default result (only if the instruction is opclass 3). For #
872 1.2.4.2 wiz # exceptions enabled, this handler must exit through the "callout" #
873 1.2.4.2 wiz # _real_unfl() so that the operating system enabled overflow handler #
874 1.2.4.2 wiz # can handle this case. #
875 1.2.4.2 wiz # Two other conditions exist. First, if underflow was disabled #
876 1.2.4.2 wiz # but the inexact exception was enabled and the result was inexact, #
877 1.2.4.2 wiz # this handler must exit through the "callout" _real_inex(). #
878 1.2.4.2 wiz # was inexact. #
879 1.2.4.2 wiz # Also, in the case of an opclass three instruction where #
880 1.2.4.2 wiz # underflow was disabled and the trace exception was enabled, this #
881 1.2.4.2 wiz # handler must exit through the "callout" _real_trace(). #
882 1.2.4.2 wiz # #
883 1.2.4.2 wiz #########################################################################
884 1.2.4.2 wiz
885 1.2.4.2 wiz global _fpsp_unfl
886 1.2.4.2 wiz _fpsp_unfl:
887 1.2.4.2 wiz
888 1.2.4.2 wiz #$# sub.l &24,%sp # make room for src/dst
889 1.2.4.2 wiz
890 1.2.4.2 wiz link.w %a6,&-LOCAL_SIZE # init stack frame
891 1.2.4.2 wiz
892 1.2.4.2 wiz fsave FP_SRC(%a6) # grab the "busy" frame
893 1.2.4.2 wiz
894 1.2.4.2 wiz movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
895 1.2.4.2 wiz fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
896 1.2.4.2 wiz fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
897 1.2.4.2 wiz
898 1.2.4.2 wiz # the FPIAR holds the "current PC" of the faulting instruction
899 1.2.4.2 wiz mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
900 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
901 1.2.4.2 wiz addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
902 1.2.4.2 wiz bsr.l _imem_read_long # fetch the instruction words
903 1.2.4.2 wiz mov.l %d0,EXC_OPWORD(%a6)
904 1.2.4.2 wiz
905 1.2.4.2 wiz ##############################################################################
906 1.2.4.2 wiz
907 1.2.4.2 wiz btst &0x5,EXC_CMDREG(%a6) # is instr an fmove out?
908 1.2.4.2 wiz bne.w funfl_out
909 1.2.4.2 wiz
910 1.2.4.2 wiz
911 1.2.4.2 wiz lea FP_SRC(%a6),%a0 # pass: ptr to src op
912 1.2.4.2 wiz bsr.l fix_skewed_ops # fix src op
913 1.2.4.2 wiz
914 1.2.4.2 wiz lea FP_SRC(%a6),%a0 # pass: ptr to src op
915 1.2.4.2 wiz bsr.l set_tag_x # tag the operand type
916 1.2.4.2 wiz mov.b %d0,STAG(%a6) # maybe NORM,DENORM
917 1.2.4.2 wiz
918 1.2.4.2 wiz # bit five of the fp ext word separates the monadic and dyadic operations
919 1.2.4.2 wiz # that can pass through fpsp_unfl(). remember that fcmp, and ftst
920 1.2.4.2 wiz # will never take this exception.
921 1.2.4.2 wiz btst &0x5,1+EXC_CMDREG(%a6) # is op monadic or dyadic?
922 1.2.4.2 wiz beq.b funfl_extract # monadic
923 1.2.4.2 wiz
924 1.2.4.2 wiz # now, what's left that's not dyadic is fsincos. we can distinguish it
925 1.2.4.2 wiz # from all dyadics by the '0110xxx pattern
926 1.2.4.2 wiz btst &0x4,1+EXC_CMDREG(%a6) # is op an fsincos?
927 1.2.4.2 wiz bne.b funfl_extract # yes
928 1.2.4.2 wiz
929 1.2.4.2 wiz bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
930 1.2.4.2 wiz bsr.l load_fpn2 # load dst into FP_DST
931 1.2.4.2 wiz
932 1.2.4.2 wiz lea FP_DST(%a6),%a0 # pass: ptr to dst op
933 1.2.4.2 wiz bsr.l set_tag_x # tag the operand type
934 1.2.4.2 wiz cmpi.b %d0,&UNNORM # is operand an UNNORM?
935 1.2.4.2 wiz bne.b funfl_op2_done # no
936 1.2.4.2 wiz bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
937 1.2.4.2 wiz funfl_op2_done:
938 1.2.4.2 wiz mov.b %d0,DTAG(%a6) # save dst optype tag
939 1.2.4.2 wiz
940 1.2.4.2 wiz funfl_extract:
941 1.2.4.2 wiz
942 1.2.4.2 wiz #$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
943 1.2.4.2 wiz #$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
944 1.2.4.2 wiz #$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
945 1.2.4.2 wiz #$# mov.l FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6)
946 1.2.4.2 wiz #$# mov.l FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6)
947 1.2.4.2 wiz #$# mov.l FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6)
948 1.2.4.2 wiz
949 1.2.4.2 wiz clr.l %d0
950 1.2.4.2 wiz mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
951 1.2.4.2 wiz
952 1.2.4.2 wiz mov.b 1+EXC_CMDREG(%a6),%d1
953 1.2.4.2 wiz andi.w &0x007f,%d1 # extract extension
954 1.2.4.2 wiz
955 1.2.4.2 wiz andi.l &0x00ff01ff,USER_FPSR(%a6)
956 1.2.4.2 wiz
957 1.2.4.2 wiz fmov.l &0x0,%fpcr # zero current control regs
958 1.2.4.2 wiz fmov.l &0x0,%fpsr
959 1.2.4.2 wiz
960 1.2.4.2 wiz lea FP_SRC(%a6),%a0
961 1.2.4.2 wiz lea FP_DST(%a6),%a1
962 1.2.4.2 wiz
963 1.2.4.2 wiz # maybe we can make these entry points ONLY the OVFL entry points of each routine.
964 1.2.4.2 wiz mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
965 1.2.4.2 wiz jsr (tbl_unsupp.l,%pc,%d1.l*1)
966 1.2.4.2 wiz
967 1.2.4.2 wiz bfextu EXC_CMDREG(%a6){&6:&3},%d0
968 1.2.4.2 wiz bsr.l store_fpreg
969 1.2.4.2 wiz
970 1.2.4.2 wiz # The `060 FPU multiplier hardware is such that if the result of a
971 1.2.4.2 wiz # multiply operation is the smallest possible normalized number
972 1.2.4.2 wiz # (0x00000000_80000000_00000000), then the machine will take an
973 1.2.4.2 wiz # underflow exception. Since this is incorrect, we need to check
974 1.2.4.2 wiz # if our emulation, after re-doing the operation, decided that
975 1.2.4.2 wiz # no underflow was called for. We do these checks only in
976 1.2.4.2 wiz # funfl_{unfl,inex}_on() because w/ both exceptions disabled, this
977 1.2.4.2 wiz # special case will simply exit gracefully with the correct result.
978 1.2.4.2 wiz
979 1.2.4.2 wiz # the exceptional possibilities we have left ourselves with are ONLY overflow
980 1.2.4.2 wiz # and inexact. and, the inexact is such that overflow occurred and was disabled
981 1.2.4.2 wiz # but inexact was enabled.
982 1.2.4.2 wiz btst &unfl_bit,FPCR_ENABLE(%a6)
983 1.2.4.2 wiz bne.b funfl_unfl_on
984 1.2.4.2 wiz
985 1.2.4.2 wiz funfl_chkinex:
986 1.2.4.2 wiz btst &inex2_bit,FPCR_ENABLE(%a6)
987 1.2.4.2 wiz bne.b funfl_inex_on
988 1.2.4.2 wiz
989 1.2.4.2 wiz funfl_exit:
990 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
991 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
992 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
993 1.2.4.2 wiz
994 1.2.4.2 wiz unlk %a6
995 1.2.4.2 wiz #$# add.l &24,%sp
996 1.2.4.2 wiz bra.l _fpsp_done
997 1.2.4.2 wiz
998 1.2.4.2 wiz # overflow is enabled AND overflow, of course, occurred. so, we have the EXOP
999 1.2.4.2 wiz # in fp1 (don't forget to save fp0). what to do now?
1000 1.2.4.2 wiz # well, we simply have to get to go to _real_unfl()!
1001 1.2.4.2 wiz funfl_unfl_on:
1002 1.2.4.2 wiz
1003 1.2.4.2 wiz # The `060 FPU multiplier hardware is such that if the result of a
1004 1.2.4.2 wiz # multiply operation is the smallest possible normalized number
1005 1.2.4.2 wiz # (0x00000000_80000000_00000000), then the machine will take an
1006 1.2.4.2 wiz # underflow exception. Since this is incorrect, we check here to see
1007 1.2.4.2 wiz # if our emulation, after re-doing the operation, decided that
1008 1.2.4.2 wiz # no underflow was called for.
1009 1.2.4.2 wiz btst &unfl_bit,FPSR_EXCEPT(%a6)
1010 1.2.4.2 wiz beq.w funfl_chkinex
1011 1.2.4.2 wiz
1012 1.2.4.2 wiz funfl_unfl_on2:
1013 1.2.4.2 wiz fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack
1014 1.2.4.2 wiz
1015 1.2.4.2 wiz mov.w &0xe003,2+FP_SRC(%a6) # save exc status
1016 1.2.4.2 wiz
1017 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
1018 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1019 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1020 1.2.4.2 wiz
1021 1.2.4.2 wiz frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
1022 1.2.4.2 wiz
1023 1.2.4.2 wiz unlk %a6
1024 1.2.4.2 wiz
1025 1.2.4.2 wiz bra.l _real_unfl
1026 1.2.4.2 wiz
1027 1.2.4.2 wiz # undeflow occurred but is disabled. meanwhile, inexact is enabled. therefore,
1028 1.2.4.2 wiz # we must jump to real_inex().
1029 1.2.4.2 wiz funfl_inex_on:
1030 1.2.4.2 wiz
1031 1.2.4.2 wiz # The `060 FPU multiplier hardware is such that if the result of a
1032 1.2.4.2 wiz # multiply operation is the smallest possible normalized number
1033 1.2.4.2 wiz # (0x00000000_80000000_00000000), then the machine will take an
1034 1.2.4.2 wiz # underflow exception.
1035 1.2.4.2 wiz # But, whether bogus or not, if inexact is enabled AND it occurred,
1036 1.2.4.2 wiz # then we have to branch to real_inex.
1037 1.2.4.2 wiz
1038 1.2.4.2 wiz btst &inex2_bit,FPSR_EXCEPT(%a6)
1039 1.2.4.2 wiz beq.w funfl_exit
1040 1.2.4.2 wiz
1041 1.2.4.2 wiz funfl_inex_on2:
1042 1.2.4.2 wiz
1043 1.2.4.2 wiz fmovm.x &0x40,FP_SRC(%a6) # save EXOP to stack
1044 1.2.4.2 wiz
1045 1.2.4.2 wiz mov.b &0xc4,1+EXC_VOFF(%a6) # vector offset = 0xc4
1046 1.2.4.2 wiz mov.w &0xe001,2+FP_SRC(%a6) # save exc status
1047 1.2.4.2 wiz
1048 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
1049 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1050 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1051 1.2.4.2 wiz
1052 1.2.4.2 wiz frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
1053 1.2.4.2 wiz
1054 1.2.4.2 wiz unlk %a6
1055 1.2.4.2 wiz
1056 1.2.4.2 wiz bra.l _real_inex
1057 1.2.4.2 wiz
1058 1.2.4.2 wiz #######################################################################
1059 1.2.4.2 wiz funfl_out:
1060 1.2.4.2 wiz
1061 1.2.4.2 wiz
1062 1.2.4.2 wiz #$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
1063 1.2.4.2 wiz #$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
1064 1.2.4.2 wiz #$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
1065 1.2.4.2 wiz
1066 1.2.4.2 wiz # the src operand is definitely a NORM(!), so tag it as such
1067 1.2.4.2 wiz mov.b &NORM,STAG(%a6) # set src optype tag
1068 1.2.4.2 wiz
1069 1.2.4.2 wiz clr.l %d0
1070 1.2.4.2 wiz mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
1071 1.2.4.2 wiz
1072 1.2.4.2 wiz and.l &0xffff00ff,USER_FPSR(%a6) # zero all but accured field
1073 1.2.4.2 wiz
1074 1.2.4.2 wiz fmov.l &0x0,%fpcr # zero current control regs
1075 1.2.4.2 wiz fmov.l &0x0,%fpsr
1076 1.2.4.2 wiz
1077 1.2.4.2 wiz lea FP_SRC(%a6),%a0 # pass ptr to src operand
1078 1.2.4.2 wiz
1079 1.2.4.2 wiz bsr.l fout
1080 1.2.4.2 wiz
1081 1.2.4.2 wiz btst &unfl_bit,FPCR_ENABLE(%a6)
1082 1.2.4.2 wiz bne.w funfl_unfl_on2
1083 1.2.4.2 wiz
1084 1.2.4.2 wiz btst &inex2_bit,FPCR_ENABLE(%a6)
1085 1.2.4.2 wiz bne.w funfl_inex_on2
1086 1.2.4.2 wiz
1087 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
1088 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1089 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1090 1.2.4.2 wiz
1091 1.2.4.2 wiz unlk %a6
1092 1.2.4.2 wiz #$# add.l &24,%sp
1093 1.2.4.2 wiz
1094 1.2.4.2 wiz btst &0x7,(%sp) # is trace on?
1095 1.2.4.2 wiz beq.l _fpsp_done # no
1096 1.2.4.2 wiz
1097 1.2.4.2 wiz fmov.l %fpiar,0x8(%sp) # "Current PC" is in FPIAR
1098 1.2.4.2 wiz mov.w &0x2024,0x6(%sp) # stk fmt = 0x2; voff = 0x024
1099 1.2.4.2 wiz bra.l _real_trace
1100 1.2.4.2 wiz
1101 1.2.4.2 wiz #########################################################################
1102 1.2.4.2 wiz # XDEF **************************************************************** #
1103 1.2.4.2 wiz # _fpsp_unsupp(): 060FPSP entry point for FP "Unimplemented #
1104 1.2.4.2 wiz # Data Type" exception. #
1105 1.2.4.2 wiz # #
1106 1.2.4.2 wiz # This handler should be the first code executed upon taking the #
1107 1.2.4.2 wiz # FP Unimplemented Data Type exception in an operating system. #
1108 1.2.4.2 wiz # #
1109 1.2.4.2 wiz # XREF **************************************************************** #
1110 1.2.4.2 wiz # _imem_read_{word,long}() - read instruction word/longword #
1111 1.2.4.2 wiz # fix_skewed_ops() - adjust src operand in fsave frame #
1112 1.2.4.2 wiz # set_tag_x() - determine optype of src/dst operands #
1113 1.2.4.2 wiz # store_fpreg() - store opclass 0 or 2 result to FP regfile #
1114 1.2.4.2 wiz # unnorm_fix() - change UNNORM operands to NORM or ZERO #
1115 1.2.4.2 wiz # load_fpn2() - load dst operand from FP regfile #
1116 1.2.4.2 wiz # load_fpn1() - load src operand from FP regfile #
1117 1.2.4.2 wiz # fout() - emulate an opclass 3 instruction #
1118 1.2.4.2 wiz # tbl_unsupp - add of table of emulation routines for opclass 0,2 #
1119 1.2.4.2 wiz # _real_inex() - "callout" to operating system inexact handler #
1120 1.2.4.2 wiz # _fpsp_done() - "callout" for exit; work all done #
1121 1.2.4.2 wiz # _real_trace() - "callout" for Trace enabled exception #
1122 1.2.4.2 wiz # funimp_skew() - adjust fsave src ops to "incorrect" value #
1123 1.2.4.2 wiz # _real_snan() - "callout" for SNAN exception #
1124 1.2.4.2 wiz # _real_operr() - "callout" for OPERR exception #
1125 1.2.4.2 wiz # _real_ovfl() - "callout" for OVFL exception #
1126 1.2.4.2 wiz # _real_unfl() - "callout" for UNFL exception #
1127 1.2.4.2 wiz # get_packed() - fetch packed operand from memory #
1128 1.2.4.2 wiz # #
1129 1.2.4.2 wiz # INPUT *************************************************************** #
1130 1.2.4.2 wiz # - The system stack contains the "Unimp Data Type" stk frame #
1131 1.2.4.2 wiz # - The fsave frame contains the ssrc op (for UNNORM/DENORM) #
1132 1.2.4.2 wiz # #
1133 1.2.4.2 wiz # OUTPUT ************************************************************** #
1134 1.2.4.2 wiz # If Inexact exception (opclass 3): #
1135 1.2.4.2 wiz # - The system stack is changed to an Inexact exception stk frame #
1136 1.2.4.2 wiz # If SNAN exception (opclass 3): #
1137 1.2.4.2 wiz # - The system stack is changed to an SNAN exception stk frame #
1138 1.2.4.2 wiz # If OPERR exception (opclass 3): #
1139 1.2.4.2 wiz # - The system stack is changed to an OPERR exception stk frame #
1140 1.2.4.2 wiz # If OVFL exception (opclass 3): #
1141 1.2.4.2 wiz # - The system stack is changed to an OVFL exception stk frame #
1142 1.2.4.2 wiz # If UNFL exception (opclass 3): #
1143 1.2.4.2 wiz # - The system stack is changed to an UNFL exception stack frame #
1144 1.2.4.2 wiz # If Trace exception enabled: #
1145 1.2.4.2 wiz # - The system stack is changed to a Trace exception stack frame #
1146 1.2.4.2 wiz # Else: (normal case) #
1147 1.2.4.2 wiz # - Correct result has been stored as appropriate #
1148 1.2.4.2 wiz # #
1149 1.2.4.2 wiz # ALGORITHM *********************************************************** #
1150 1.2.4.2 wiz # Two main instruction types can enter here: (1) DENORM or UNNORM #
1151 1.2.4.2 wiz # unimplemented data types. These can be either opclass 0,2 or 3 #
1152 1.2.4.2 wiz # instructions, and (2) PACKED unimplemented data format instructions #
1153 1.2.4.2 wiz # also of opclasses 0,2, or 3. #
1154 1.2.4.2 wiz # For UNNORM/DENORM opclass 0 and 2, the handler fetches the src #
1155 1.2.4.2 wiz # operand from the fsave state frame and the dst operand (if dyadic) #
1156 1.2.4.2 wiz # from the FP register file. The instruction is then emulated by #
1157 1.2.4.2 wiz # choosing an emulation routine from a table of routines indexed by #
1158 1.2.4.2 wiz # instruction type. Once the instruction has been emulated and result #
1159 1.2.4.2 wiz # saved, then we check to see if any enabled exceptions resulted from #
1160 1.2.4.2 wiz # instruction emulation. If none, then we exit through the "callout" #
1161 1.2.4.2 wiz # _fpsp_done(). If there is an enabled FP exception, then we insert #
1162 1.2.4.2 wiz # this exception into the FPU in the fsave state frame and then exit #
1163 1.2.4.2 wiz # through _fpsp_done(). #
1164 1.2.4.2 wiz # PACKED opclass 0 and 2 is similar in how the instruction is #
1165 1.2.4.2 wiz # emulated and exceptions handled. The differences occur in how the #
1166 1.2.4.2 wiz # handler loads the packed op (by calling get_packed() routine) and #
1167 1.2.4.2 wiz # by the fact that a Trace exception could be pending for PACKED ops. #
1168 1.2.4.2 wiz # If a Trace exception is pending, then the current exception stack #
1169 1.2.4.2 wiz # frame is changed to a Trace exception stack frame and an exit is #
1170 1.2.4.2 wiz # made through _real_trace(). #
1171 1.2.4.2 wiz # For UNNORM/DENORM opclass 3, the actual move out to memory is #
1172 1.2.4.2 wiz # performed by calling the routine fout(). If no exception should occur #
1173 1.2.4.2 wiz # as the result of emulation, then an exit either occurs through #
1174 1.2.4.2 wiz # _fpsp_done() or through _real_trace() if a Trace exception is pending #
1175 1.2.4.2 wiz # (a Trace stack frame must be created here, too). If an FP exception #
1176 1.2.4.2 wiz # should occur, then we must create an exception stack frame of that #
1177 1.2.4.2 wiz # type and jump to either _real_snan(), _real_operr(), _real_inex(), #
1178 1.2.4.2 wiz # _real_unfl(), or _real_ovfl() as appropriate. PACKED opclass 3 #
1179 1.2.4.2 wiz # emulation is performed in a similar manner. #
1180 1.2.4.2 wiz # #
1181 1.2.4.2 wiz #########################################################################
1182 1.2.4.2 wiz
1183 1.2.4.2 wiz #
1184 1.2.4.2 wiz # (1) DENORM and UNNORM (unimplemented) data types:
1185 1.2.4.2 wiz #
1186 1.2.4.2 wiz # post-instruction
1187 1.2.4.2 wiz # *****************
1188 1.2.4.2 wiz # * EA *
1189 1.2.4.2 wiz # pre-instruction * *
1190 1.2.4.2 wiz # ***************** *****************
1191 1.2.4.2 wiz # * 0x0 * 0x0dc * * 0x3 * 0x0dc *
1192 1.2.4.2 wiz # ***************** *****************
1193 1.2.4.2 wiz # * Next * * Next *
1194 1.2.4.2 wiz # * PC * * PC *
1195 1.2.4.2 wiz # ***************** *****************
1196 1.2.4.2 wiz # * SR * * SR *
1197 1.2.4.2 wiz # ***************** *****************
1198 1.2.4.2 wiz #
1199 1.2.4.2 wiz # (2) PACKED format (unsupported) opclasses two and three:
1200 1.2.4.2 wiz # *****************
1201 1.2.4.2 wiz # * EA *
1202 1.2.4.2 wiz # * *
1203 1.2.4.2 wiz # *****************
1204 1.2.4.2 wiz # * 0x2 * 0x0dc *
1205 1.2.4.2 wiz # *****************
1206 1.2.4.2 wiz # * Next *
1207 1.2.4.2 wiz # * PC *
1208 1.2.4.2 wiz # *****************
1209 1.2.4.2 wiz # * SR *
1210 1.2.4.2 wiz # *****************
1211 1.2.4.2 wiz #
1212 1.2.4.2 wiz global _fpsp_unsupp
1213 1.2.4.2 wiz _fpsp_unsupp:
1214 1.2.4.2 wiz
1215 1.2.4.2 wiz link.w %a6,&-LOCAL_SIZE # init stack frame
1216 1.2.4.2 wiz
1217 1.2.4.2 wiz fsave FP_SRC(%a6) # save fp state
1218 1.2.4.2 wiz
1219 1.2.4.2 wiz movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1220 1.2.4.2 wiz fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
1221 1.2.4.2 wiz fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
1222 1.2.4.2 wiz
1223 1.2.4.2 wiz btst &0x5,EXC_SR(%a6) # user or supervisor mode?
1224 1.2.4.2 wiz bne.b fu_s
1225 1.2.4.2 wiz fu_u:
1226 1.2.4.2 wiz mov.l %usp,%a0 # fetch user stack pointer
1227 1.2.4.2 wiz mov.l %a0,EXC_A7(%a6) # save on stack
1228 1.2.4.2 wiz bra.b fu_cont
1229 1.2.4.2 wiz # if the exception is an opclass zero or two unimplemented data type
1230 1.2.4.2 wiz # exception, then the a7' calculated here is wrong since it doesn't
1231 1.2.4.2 wiz # stack an ea. however, we don't need an a7' for this case anyways.
1232 1.2.4.2 wiz fu_s:
1233 1.2.4.2 wiz lea 0x4+EXC_EA(%a6),%a0 # load old a7'
1234 1.2.4.2 wiz mov.l %a0,EXC_A7(%a6) # save on stack
1235 1.2.4.2 wiz
1236 1.2.4.2 wiz fu_cont:
1237 1.2.4.2 wiz
1238 1.2.4.2 wiz # the FPIAR holds the "current PC" of the faulting instruction
1239 1.2.4.2 wiz # the FPIAR should be set correctly for ALL exceptions passing through
1240 1.2.4.2 wiz # this point.
1241 1.2.4.2 wiz mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
1242 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1243 1.2.4.2 wiz addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
1244 1.2.4.2 wiz bsr.l _imem_read_long # fetch the instruction words
1245 1.2.4.2 wiz mov.l %d0,EXC_OPWORD(%a6) # store OPWORD and EXTWORD
1246 1.2.4.2 wiz
1247 1.2.4.2 wiz ############################
1248 1.2.4.2 wiz
1249 1.2.4.2 wiz clr.b SPCOND_FLG(%a6) # clear special condition flag
1250 1.2.4.2 wiz
1251 1.2.4.2 wiz # Separate opclass three (fpn-to-mem) ops since they have a different
1252 1.2.4.2 wiz # stack frame and protocol.
1253 1.2.4.2 wiz btst &0x5,EXC_CMDREG(%a6) # is it an fmove out?
1254 1.2.4.2 wiz bne.w fu_out # yes
1255 1.2.4.2 wiz
1256 1.2.4.2 wiz # Separate packed opclass two instructions.
1257 1.2.4.2 wiz bfextu EXC_CMDREG(%a6){&0:&6},%d0
1258 1.2.4.2 wiz cmpi.b %d0,&0x13
1259 1.2.4.2 wiz beq.w fu_in_pack
1260 1.2.4.2 wiz
1261 1.2.4.2 wiz
1262 1.2.4.2 wiz # I'm not sure at this point what FPSR bits are valid for this instruction.
1263 1.2.4.2 wiz # so, since the emulation routines re-create them anyways, zero exception field
1264 1.2.4.2 wiz andi.l &0x00ff00ff,USER_FPSR(%a6) # zero exception field
1265 1.2.4.2 wiz
1266 1.2.4.2 wiz fmov.l &0x0,%fpcr # zero current control regs
1267 1.2.4.2 wiz fmov.l &0x0,%fpsr
1268 1.2.4.2 wiz
1269 1.2.4.2 wiz # Opclass two w/ memory-to-fpn operation will have an incorrect extended
1270 1.2.4.2 wiz # precision format if the src format was single or double and the
1271 1.2.4.2 wiz # source data type was an INF, NAN, DENORM, or UNNORM
1272 1.2.4.2 wiz lea FP_SRC(%a6),%a0 # pass ptr to input
1273 1.2.4.2 wiz bsr.l fix_skewed_ops
1274 1.2.4.2 wiz
1275 1.2.4.2 wiz # we don't know whether the src operand or the dst operand (or both) is the
1276 1.2.4.2 wiz # UNNORM or DENORM. call the function that tags the operand type. if the
1277 1.2.4.2 wiz # input is an UNNORM, then convert it to a NORM, DENORM, or ZERO.
1278 1.2.4.2 wiz lea FP_SRC(%a6),%a0 # pass: ptr to src op
1279 1.2.4.2 wiz bsr.l set_tag_x # tag the operand type
1280 1.2.4.2 wiz cmpi.b %d0,&UNNORM # is operand an UNNORM?
1281 1.2.4.2 wiz bne.b fu_op2 # no
1282 1.2.4.2 wiz bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
1283 1.2.4.2 wiz
1284 1.2.4.2 wiz fu_op2:
1285 1.2.4.2 wiz mov.b %d0,STAG(%a6) # save src optype tag
1286 1.2.4.2 wiz
1287 1.2.4.2 wiz bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
1288 1.2.4.2 wiz
1289 1.2.4.2 wiz # bit five of the fp extension word separates the monadic and dyadic operations
1290 1.2.4.2 wiz # at this point
1291 1.2.4.2 wiz btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic?
1292 1.2.4.2 wiz beq.b fu_extract # monadic
1293 1.2.4.2 wiz cmpi.b 1+EXC_CMDREG(%a6),&0x3a # is operation an ftst?
1294 1.2.4.2 wiz beq.b fu_extract # yes, so it's monadic, too
1295 1.2.4.2 wiz
1296 1.2.4.2 wiz bsr.l load_fpn2 # load dst into FP_DST
1297 1.2.4.2 wiz
1298 1.2.4.2 wiz lea FP_DST(%a6),%a0 # pass: ptr to dst op
1299 1.2.4.2 wiz bsr.l set_tag_x # tag the operand type
1300 1.2.4.2 wiz cmpi.b %d0,&UNNORM # is operand an UNNORM?
1301 1.2.4.2 wiz bne.b fu_op2_done # no
1302 1.2.4.2 wiz bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
1303 1.2.4.2 wiz fu_op2_done:
1304 1.2.4.2 wiz mov.b %d0,DTAG(%a6) # save dst optype tag
1305 1.2.4.2 wiz
1306 1.2.4.2 wiz fu_extract:
1307 1.2.4.2 wiz clr.l %d0
1308 1.2.4.2 wiz mov.b FPCR_MODE(%a6),%d0 # fetch rnd mode/prec
1309 1.2.4.2 wiz
1310 1.2.4.2 wiz bfextu 1+EXC_CMDREG(%a6){&1:&7},%d1 # extract extension
1311 1.2.4.2 wiz
1312 1.2.4.2 wiz lea FP_SRC(%a6),%a0
1313 1.2.4.2 wiz lea FP_DST(%a6),%a1
1314 1.2.4.2 wiz
1315 1.2.4.2 wiz mov.l (tbl_unsupp.l,%pc,%d1.l*4),%d1 # fetch routine addr
1316 1.2.4.2 wiz jsr (tbl_unsupp.l,%pc,%d1.l*1)
1317 1.2.4.2 wiz
1318 1.2.4.2 wiz #
1319 1.2.4.2 wiz # Exceptions in order of precedence:
1320 1.2.4.2 wiz # BSUN : none
1321 1.2.4.2 wiz # SNAN : all dyadic ops
1322 1.2.4.2 wiz # OPERR : fsqrt(-NORM)
1323 1.2.4.2 wiz # OVFL : all except ftst,fcmp
1324 1.2.4.2 wiz # UNFL : all except ftst,fcmp
1325 1.2.4.2 wiz # DZ : fdiv
1326 1.2.4.2 wiz # INEX2 : all except ftst,fcmp
1327 1.2.4.2 wiz # INEX1 : none (packed doesn't go through here)
1328 1.2.4.2 wiz #
1329 1.2.4.2 wiz
1330 1.2.4.2 wiz # we determine the highest priority exception(if any) set by the
1331 1.2.4.2 wiz # emulation routine that has also been enabled by the user.
1332 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions set
1333 1.2.4.2 wiz bne.b fu_in_ena # some are enabled
1334 1.2.4.2 wiz
1335 1.2.4.2 wiz fu_in_cont:
1336 1.2.4.2 wiz # fcmp and ftst do not store any result.
1337 1.2.4.2 wiz mov.b 1+EXC_CMDREG(%a6),%d0 # fetch extension
1338 1.2.4.2 wiz andi.b &0x38,%d0 # extract bits 3-5
1339 1.2.4.2 wiz cmpi.b %d0,&0x38 # is instr fcmp or ftst?
1340 1.2.4.2 wiz beq.b fu_in_exit # yes
1341 1.2.4.2 wiz
1342 1.2.4.2 wiz bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
1343 1.2.4.2 wiz bsr.l store_fpreg # store the result
1344 1.2.4.2 wiz
1345 1.2.4.2 wiz fu_in_exit:
1346 1.2.4.2 wiz
1347 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1348 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1349 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1350 1.2.4.2 wiz
1351 1.2.4.2 wiz unlk %a6
1352 1.2.4.2 wiz
1353 1.2.4.2 wiz bra.l _fpsp_done
1354 1.2.4.2 wiz
1355 1.2.4.2 wiz fu_in_ena:
1356 1.2.4.2 wiz and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enabled
1357 1.2.4.2 wiz bfffo %d0{&24:&8},%d0 # find highest priority exception
1358 1.2.4.2 wiz bne.b fu_in_exc # there is at least one set
1359 1.2.4.2 wiz
1360 1.2.4.2 wiz #
1361 1.2.4.2 wiz # No exceptions occurred that were also enabled. Now:
1362 1.2.4.2 wiz #
1363 1.2.4.2 wiz # if (OVFL && ovfl_disabled && inexact_enabled) {
1364 1.2.4.2 wiz # branch to _real_inex() (even if the result was exact!);
1365 1.2.4.2 wiz # } else {
1366 1.2.4.2 wiz # save the result in the proper fp reg (unless the op is fcmp or ftst);
1367 1.2.4.2 wiz # return;
1368 1.2.4.2 wiz # }
1369 1.2.4.2 wiz #
1370 1.2.4.2 wiz btst &ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set?
1371 1.2.4.2 wiz beq.b fu_in_cont # no
1372 1.2.4.2 wiz
1373 1.2.4.2 wiz fu_in_ovflchk:
1374 1.2.4.2 wiz btst &inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled?
1375 1.2.4.2 wiz beq.b fu_in_cont # no
1376 1.2.4.2 wiz bra.w fu_in_exc_ovfl # go insert overflow frame
1377 1.2.4.2 wiz
1378 1.2.4.2 wiz #
1379 1.2.4.2 wiz # An exception occurred and that exception was enabled:
1380 1.2.4.2 wiz #
1381 1.2.4.2 wiz # shift enabled exception field into lo byte of d0;
1382 1.2.4.2 wiz # if (((INEX2 || INEX1) && inex_enabled && OVFL && ovfl_disabled) ||
1383 1.2.4.2 wiz # ((INEX2 || INEX1) && inex_enabled && UNFL && unfl_disabled)) {
1384 1.2.4.2 wiz # /*
1385 1.2.4.2 wiz # * this is the case where we must call _real_inex() now or else
1386 1.2.4.2 wiz # * there will be no other way to pass it the exceptional operand
1387 1.2.4.2 wiz # */
1388 1.2.4.2 wiz # call _real_inex();
1389 1.2.4.2 wiz # } else {
1390 1.2.4.2 wiz # restore exc state (SNAN||OPERR||OVFL||UNFL||DZ||INEX) into the FPU;
1391 1.2.4.2 wiz # }
1392 1.2.4.2 wiz #
1393 1.2.4.2 wiz fu_in_exc:
1394 1.2.4.2 wiz subi.l &24,%d0 # fix offset to be 0-8
1395 1.2.4.2 wiz cmpi.b %d0,&0x6 # is exception INEX? (6)
1396 1.2.4.2 wiz bne.b fu_in_exc_exit # no
1397 1.2.4.2 wiz
1398 1.2.4.2 wiz # the enabled exception was inexact
1399 1.2.4.2 wiz btst &unfl_bit,FPSR_EXCEPT(%a6) # did disabled underflow occur?
1400 1.2.4.2 wiz bne.w fu_in_exc_unfl # yes
1401 1.2.4.2 wiz btst &ovfl_bit,FPSR_EXCEPT(%a6) # did disabled overflow occur?
1402 1.2.4.2 wiz bne.w fu_in_exc_ovfl # yes
1403 1.2.4.2 wiz
1404 1.2.4.2 wiz # here, we insert the correct fsave status value into the fsave frame for the
1405 1.2.4.2 wiz # corresponding exception. the operand in the fsave frame should be the original
1406 1.2.4.2 wiz # src operand.
1407 1.2.4.2 wiz fu_in_exc_exit:
1408 1.2.4.2 wiz mov.l %d0,-(%sp) # save d0
1409 1.2.4.2 wiz bsr.l funimp_skew # skew sgl or dbl inputs
1410 1.2.4.2 wiz mov.l (%sp)+,%d0 # restore d0
1411 1.2.4.2 wiz
1412 1.2.4.2 wiz mov.w (tbl_except.b,%pc,%d0.w*2),2+FP_SRC(%a6) # create exc status
1413 1.2.4.2 wiz
1414 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1415 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1416 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1417 1.2.4.2 wiz
1418 1.2.4.2 wiz frestore FP_SRC(%a6) # restore src op
1419 1.2.4.2 wiz
1420 1.2.4.2 wiz unlk %a6
1421 1.2.4.2 wiz
1422 1.2.4.2 wiz bra.l _fpsp_done
1423 1.2.4.2 wiz
1424 1.2.4.2 wiz tbl_except:
1425 1.2.4.2 wiz short 0xe000,0xe006,0xe004,0xe005
1426 1.2.4.2 wiz short 0xe003,0xe002,0xe001,0xe001
1427 1.2.4.2 wiz
1428 1.2.4.2 wiz fu_in_exc_unfl:
1429 1.2.4.2 wiz mov.w &0x4,%d0
1430 1.2.4.2 wiz bra.b fu_in_exc_exit
1431 1.2.4.2 wiz fu_in_exc_ovfl:
1432 1.2.4.2 wiz mov.w &0x03,%d0
1433 1.2.4.2 wiz bra.b fu_in_exc_exit
1434 1.2.4.2 wiz
1435 1.2.4.2 wiz # If the input operand to this operation was opclass two and a single
1436 1.2.4.2 wiz # or double precision denorm, inf, or nan, the operand needs to be
1437 1.2.4.2 wiz # "corrected" in order to have the proper equivalent extended precision
1438 1.2.4.2 wiz # number.
1439 1.2.4.2 wiz global fix_skewed_ops
1440 1.2.4.2 wiz fix_skewed_ops:
1441 1.2.4.2 wiz bfextu EXC_CMDREG(%a6){&0:&6},%d0 # extract opclass,src fmt
1442 1.2.4.2 wiz cmpi.b %d0,&0x11 # is class = 2 & fmt = sgl?
1443 1.2.4.2 wiz beq.b fso_sgl # yes
1444 1.2.4.2 wiz cmpi.b %d0,&0x15 # is class = 2 & fmt = dbl?
1445 1.2.4.2 wiz beq.b fso_dbl # yes
1446 1.2.4.2 wiz rts # no
1447 1.2.4.2 wiz
1448 1.2.4.2 wiz fso_sgl:
1449 1.2.4.2 wiz mov.w LOCAL_EX(%a0),%d0 # fetch src exponent
1450 1.2.4.2 wiz andi.w &0x7fff,%d0 # strip sign
1451 1.2.4.2 wiz cmpi.w %d0,&0x3f80 # is |exp| == $3f80?
1452 1.2.4.2 wiz beq.b fso_sgl_dnrm_zero # yes
1453 1.2.4.2 wiz cmpi.w %d0,&0x407f # no; is |exp| == $407f?
1454 1.2.4.2 wiz beq.b fso_infnan # yes
1455 1.2.4.2 wiz rts # no
1456 1.2.4.2 wiz
1457 1.2.4.2 wiz fso_sgl_dnrm_zero:
1458 1.2.4.2 wiz andi.l &0x7fffffff,LOCAL_HI(%a0) # clear j-bit
1459 1.2.4.2 wiz beq.b fso_zero # it's a skewed zero
1460 1.2.4.2 wiz fso_sgl_dnrm:
1461 1.2.4.2 wiz # here, we count on norm not to alter a0...
1462 1.2.4.2 wiz bsr.l norm # normalize mantissa
1463 1.2.4.2 wiz neg.w %d0 # -shft amt
1464 1.2.4.2 wiz addi.w &0x3f81,%d0 # adjust new exponent
1465 1.2.4.2 wiz andi.w &0x8000,LOCAL_EX(%a0) # clear old exponent
1466 1.2.4.2 wiz or.w %d0,LOCAL_EX(%a0) # insert new exponent
1467 1.2.4.2 wiz rts
1468 1.2.4.2 wiz
1469 1.2.4.2 wiz fso_zero:
1470 1.2.4.2 wiz andi.w &0x8000,LOCAL_EX(%a0) # clear bogus exponent
1471 1.2.4.2 wiz rts
1472 1.2.4.2 wiz
1473 1.2.4.2 wiz fso_infnan:
1474 1.2.4.2 wiz andi.b &0x7f,LOCAL_HI(%a0) # clear j-bit
1475 1.2.4.2 wiz ori.w &0x7fff,LOCAL_EX(%a0) # make exponent = $7fff
1476 1.2.4.2 wiz rts
1477 1.2.4.2 wiz
1478 1.2.4.2 wiz fso_dbl:
1479 1.2.4.2 wiz mov.w LOCAL_EX(%a0),%d0 # fetch src exponent
1480 1.2.4.2 wiz andi.w &0x7fff,%d0 # strip sign
1481 1.2.4.2 wiz cmpi.w %d0,&0x3c00 # is |exp| == $3c00?
1482 1.2.4.2 wiz beq.b fso_dbl_dnrm_zero # yes
1483 1.2.4.2 wiz cmpi.w %d0,&0x43ff # no; is |exp| == $43ff?
1484 1.2.4.2 wiz beq.b fso_infnan # yes
1485 1.2.4.2 wiz rts # no
1486 1.2.4.2 wiz
1487 1.2.4.2 wiz fso_dbl_dnrm_zero:
1488 1.2.4.2 wiz andi.l &0x7fffffff,LOCAL_HI(%a0) # clear j-bit
1489 1.2.4.2 wiz bne.b fso_dbl_dnrm # it's a skewed denorm
1490 1.2.4.2 wiz tst.l LOCAL_LO(%a0) # is it a zero?
1491 1.2.4.2 wiz beq.b fso_zero # yes
1492 1.2.4.2 wiz fso_dbl_dnrm:
1493 1.2.4.2 wiz # here, we count on norm not to alter a0...
1494 1.2.4.2 wiz bsr.l norm # normalize mantissa
1495 1.2.4.2 wiz neg.w %d0 # -shft amt
1496 1.2.4.2 wiz addi.w &0x3c01,%d0 # adjust new exponent
1497 1.2.4.2 wiz andi.w &0x8000,LOCAL_EX(%a0) # clear old exponent
1498 1.2.4.2 wiz or.w %d0,LOCAL_EX(%a0) # insert new exponent
1499 1.2.4.2 wiz rts
1500 1.2.4.2 wiz
1501 1.2.4.2 wiz #################################################################
1502 1.2.4.2 wiz
1503 1.2.4.2 wiz # fmove out took an unimplemented data type exception.
1504 1.2.4.2 wiz # the src operand is in FP_SRC. Call _fout() to write out the result and
1505 1.2.4.2 wiz # to determine which exceptions, if any, to take.
1506 1.2.4.2 wiz fu_out:
1507 1.2.4.2 wiz
1508 1.2.4.2 wiz # Separate packed move outs from the UNNORM and DENORM move outs.
1509 1.2.4.2 wiz bfextu EXC_CMDREG(%a6){&3:&3},%d0
1510 1.2.4.2 wiz cmpi.b %d0,&0x3
1511 1.2.4.2 wiz beq.w fu_out_pack
1512 1.2.4.2 wiz cmpi.b %d0,&0x7
1513 1.2.4.2 wiz beq.w fu_out_pack
1514 1.2.4.2 wiz
1515 1.2.4.2 wiz
1516 1.2.4.2 wiz # I'm not sure at this point what FPSR bits are valid for this instruction.
1517 1.2.4.2 wiz # so, since the emulation routines re-create them anyways, zero exception field.
1518 1.2.4.2 wiz # fmove out doesn't affect ccodes.
1519 1.2.4.2 wiz and.l &0xffff00ff,USER_FPSR(%a6) # zero exception field
1520 1.2.4.2 wiz
1521 1.2.4.2 wiz fmov.l &0x0,%fpcr # zero current control regs
1522 1.2.4.2 wiz fmov.l &0x0,%fpsr
1523 1.2.4.2 wiz
1524 1.2.4.2 wiz # the src can ONLY be a DENORM or an UNNORM! so, don't make any big subroutine
1525 1.2.4.2 wiz # call here. just figure out what it is...
1526 1.2.4.2 wiz mov.w FP_SRC_EX(%a6),%d0 # get exponent
1527 1.2.4.2 wiz andi.w &0x7fff,%d0 # strip sign
1528 1.2.4.2 wiz beq.b fu_out_denorm # it's a DENORM
1529 1.2.4.2 wiz
1530 1.2.4.2 wiz lea FP_SRC(%a6),%a0
1531 1.2.4.2 wiz bsr.l unnorm_fix # yes; fix it
1532 1.2.4.2 wiz
1533 1.2.4.2 wiz mov.b %d0,STAG(%a6)
1534 1.2.4.2 wiz
1535 1.2.4.2 wiz bra.b fu_out_cont
1536 1.2.4.2 wiz fu_out_denorm:
1537 1.2.4.2 wiz mov.b &DENORM,STAG(%a6)
1538 1.2.4.2 wiz fu_out_cont:
1539 1.2.4.2 wiz
1540 1.2.4.2 wiz clr.l %d0
1541 1.2.4.2 wiz mov.b FPCR_MODE(%a6),%d0 # fetch rnd mode/prec
1542 1.2.4.2 wiz
1543 1.2.4.2 wiz lea FP_SRC(%a6),%a0 # pass ptr to src operand
1544 1.2.4.2 wiz
1545 1.2.4.2 wiz mov.l (%a6),EXC_A6(%a6) # in case a6 changes
1546 1.2.4.2 wiz bsr.l fout # call fmove out routine
1547 1.2.4.2 wiz
1548 1.2.4.2 wiz # Exceptions in order of precedence:
1549 1.2.4.2 wiz # BSUN : none
1550 1.2.4.2 wiz # SNAN : none
1551 1.2.4.2 wiz # OPERR : fmove.{b,w,l} out of large UNNORM
1552 1.2.4.2 wiz # OVFL : fmove.{s,d}
1553 1.2.4.2 wiz # UNFL : fmove.{s,d,x}
1554 1.2.4.2 wiz # DZ : none
1555 1.2.4.2 wiz # INEX2 : all
1556 1.2.4.2 wiz # INEX1 : none (packed doesn't travel through here)
1557 1.2.4.2 wiz
1558 1.2.4.2 wiz # determine the highest priority exception(if any) set by the
1559 1.2.4.2 wiz # emulation routine that has also been enabled by the user.
1560 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions enabled
1561 1.2.4.2 wiz bne.w fu_out_ena # some are enabled
1562 1.2.4.2 wiz
1563 1.2.4.2 wiz fu_out_done:
1564 1.2.4.2 wiz
1565 1.2.4.2 wiz mov.l EXC_A6(%a6),(%a6) # in case a6 changed
1566 1.2.4.2 wiz
1567 1.2.4.2 wiz # on extended precision opclass three instructions using pre-decrement or
1568 1.2.4.2 wiz # post-increment addressing mode, the address register is not updated. is the
1569 1.2.4.2 wiz # address register was the stack pointer used from user mode, then let's update
1570 1.2.4.2 wiz # it here. if it was used from supervisor mode, then we have to handle this
1571 1.2.4.2 wiz # as a special case.
1572 1.2.4.2 wiz btst &0x5,EXC_SR(%a6)
1573 1.2.4.2 wiz bne.b fu_out_done_s
1574 1.2.4.2 wiz
1575 1.2.4.2 wiz mov.l EXC_A7(%a6),%a0 # restore a7
1576 1.2.4.2 wiz mov.l %a0,%usp
1577 1.2.4.2 wiz
1578 1.2.4.2 wiz fu_out_done_cont:
1579 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1580 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1581 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1582 1.2.4.2 wiz
1583 1.2.4.2 wiz unlk %a6
1584 1.2.4.2 wiz
1585 1.2.4.2 wiz btst &0x7,(%sp) # is trace on?
1586 1.2.4.2 wiz bne.b fu_out_trace # yes
1587 1.2.4.2 wiz
1588 1.2.4.2 wiz bra.l _fpsp_done
1589 1.2.4.2 wiz
1590 1.2.4.2 wiz # is the ea mode pre-decrement of the stack pointer from supervisor mode?
1591 1.2.4.2 wiz # ("fmov.x fpm,-(a7)") if so,
1592 1.2.4.2 wiz fu_out_done_s:
1593 1.2.4.2 wiz cmpi.b SPCOND_FLG(%a6),&mda7_flg
1594 1.2.4.2 wiz bne.b fu_out_done_cont
1595 1.2.4.2 wiz
1596 1.2.4.2 wiz # the extended precision result is still in fp0. but, we need to save it
1597 1.2.4.2 wiz # somewhere on the stack until we can copy it to its final resting place.
1598 1.2.4.2 wiz # here, we're counting on the top of the stack to be the old place-holders
1599 1.2.4.2 wiz # for fp0/fp1 which have already been restored. that way, we can write
1600 1.2.4.2 wiz # over those destinations with the shifted stack frame.
1601 1.2.4.2 wiz fmovm.x &0x80,FP_SRC(%a6) # put answer on stack
1602 1.2.4.2 wiz
1603 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1604 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1605 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1606 1.2.4.2 wiz
1607 1.2.4.2 wiz mov.l (%a6),%a6 # restore frame pointer
1608 1.2.4.2 wiz
1609 1.2.4.2 wiz mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
1610 1.2.4.2 wiz mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
1611 1.2.4.2 wiz
1612 1.2.4.2 wiz # now, copy the result to the proper place on the stack
1613 1.2.4.2 wiz mov.l LOCAL_SIZE+FP_SRC_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp)
1614 1.2.4.2 wiz mov.l LOCAL_SIZE+FP_SRC_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp)
1615 1.2.4.2 wiz mov.l LOCAL_SIZE+FP_SRC_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp)
1616 1.2.4.2 wiz
1617 1.2.4.2 wiz add.l &LOCAL_SIZE-0x8,%sp
1618 1.2.4.2 wiz
1619 1.2.4.2 wiz btst &0x7,(%sp)
1620 1.2.4.2 wiz bne.b fu_out_trace
1621 1.2.4.2 wiz
1622 1.2.4.2 wiz bra.l _fpsp_done
1623 1.2.4.2 wiz
1624 1.2.4.2 wiz fu_out_ena:
1625 1.2.4.2 wiz and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enabled
1626 1.2.4.2 wiz bfffo %d0{&24:&8},%d0 # find highest priority exception
1627 1.2.4.2 wiz bne.b fu_out_exc # there is at least one set
1628 1.2.4.2 wiz
1629 1.2.4.2 wiz # no exceptions were set.
1630 1.2.4.2 wiz # if a disabled overflow occurred and inexact was enabled but the result
1631 1.2.4.2 wiz # was exact, then a branch to _real_inex() is made.
1632 1.2.4.2 wiz btst &ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set?
1633 1.2.4.2 wiz beq.w fu_out_done # no
1634 1.2.4.2 wiz
1635 1.2.4.2 wiz fu_out_ovflchk:
1636 1.2.4.2 wiz btst &inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled?
1637 1.2.4.2 wiz beq.w fu_out_done # no
1638 1.2.4.2 wiz bra.w fu_inex # yes
1639 1.2.4.2 wiz
1640 1.2.4.2 wiz #
1641 1.2.4.2 wiz # The fp move out that took the "Unimplemented Data Type" exception was
1642 1.2.4.2 wiz # being traced. Since the stack frames are similar, get the "current" PC
1643 1.2.4.2 wiz # from FPIAR and put it in the trace stack frame then jump to _real_trace().
1644 1.2.4.2 wiz #
1645 1.2.4.2 wiz # UNSUPP FRAME TRACE FRAME
1646 1.2.4.2 wiz # ***************** *****************
1647 1.2.4.2 wiz # * EA * * Current *
1648 1.2.4.2 wiz # * * * PC *
1649 1.2.4.2 wiz # ***************** *****************
1650 1.2.4.2 wiz # * 0x3 * 0x0dc * * 0x2 * 0x024 *
1651 1.2.4.2 wiz # ***************** *****************
1652 1.2.4.2 wiz # * Next * * Next *
1653 1.2.4.2 wiz # * PC * * PC *
1654 1.2.4.2 wiz # ***************** *****************
1655 1.2.4.2 wiz # * SR * * SR *
1656 1.2.4.2 wiz # ***************** *****************
1657 1.2.4.2 wiz #
1658 1.2.4.2 wiz fu_out_trace:
1659 1.2.4.2 wiz mov.w &0x2024,0x6(%sp)
1660 1.2.4.2 wiz fmov.l %fpiar,0x8(%sp)
1661 1.2.4.2 wiz bra.l _real_trace
1662 1.2.4.2 wiz
1663 1.2.4.2 wiz # an exception occurred and that exception was enabled.
1664 1.2.4.2 wiz fu_out_exc:
1665 1.2.4.2 wiz subi.l &24,%d0 # fix offset to be 0-8
1666 1.2.4.2 wiz
1667 1.2.4.2 wiz # we don't mess with the existing fsave frame. just re-insert it and
1668 1.2.4.2 wiz # jump to the "_real_{}()" handler...
1669 1.2.4.2 wiz mov.w (tbl_fu_out.b,%pc,%d0.w*2),%d0
1670 1.2.4.2 wiz jmp (tbl_fu_out.b,%pc,%d0.w*1)
1671 1.2.4.2 wiz
1672 1.2.4.2 wiz swbeg &0x8
1673 1.2.4.2 wiz tbl_fu_out:
1674 1.2.4.2 wiz short tbl_fu_out - tbl_fu_out # BSUN can't happen
1675 1.2.4.2 wiz short tbl_fu_out - tbl_fu_out # SNAN can't happen
1676 1.2.4.2 wiz short fu_operr - tbl_fu_out # OPERR
1677 1.2.4.2 wiz short fu_ovfl - tbl_fu_out # OVFL
1678 1.2.4.2 wiz short fu_unfl - tbl_fu_out # UNFL
1679 1.2.4.2 wiz short tbl_fu_out - tbl_fu_out # DZ can't happen
1680 1.2.4.2 wiz short fu_inex - tbl_fu_out # INEX2
1681 1.2.4.2 wiz short tbl_fu_out - tbl_fu_out # INEX1 won't make it here
1682 1.2.4.2 wiz
1683 1.2.4.2 wiz # for snan,operr,ovfl,unfl, src op is still in FP_SRC so just
1684 1.2.4.2 wiz # frestore it.
1685 1.2.4.2 wiz fu_snan:
1686 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1687 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1688 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1689 1.2.4.2 wiz
1690 1.2.4.2 wiz mov.w &0x30d8,EXC_VOFF(%a6) # vector offset = 0xd8
1691 1.2.4.2 wiz mov.w &0xe006,2+FP_SRC(%a6)
1692 1.2.4.2 wiz
1693 1.2.4.2 wiz frestore FP_SRC(%a6)
1694 1.2.4.2 wiz
1695 1.2.4.2 wiz unlk %a6
1696 1.2.4.2 wiz
1697 1.2.4.2 wiz
1698 1.2.4.2 wiz bra.l _real_snan
1699 1.2.4.2 wiz
1700 1.2.4.2 wiz fu_operr:
1701 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1702 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1703 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1704 1.2.4.2 wiz
1705 1.2.4.2 wiz mov.w &0x30d0,EXC_VOFF(%a6) # vector offset = 0xd0
1706 1.2.4.2 wiz mov.w &0xe004,2+FP_SRC(%a6)
1707 1.2.4.2 wiz
1708 1.2.4.2 wiz frestore FP_SRC(%a6)
1709 1.2.4.2 wiz
1710 1.2.4.2 wiz unlk %a6
1711 1.2.4.2 wiz
1712 1.2.4.2 wiz
1713 1.2.4.2 wiz bra.l _real_operr
1714 1.2.4.2 wiz
1715 1.2.4.2 wiz fu_ovfl:
1716 1.2.4.2 wiz fmovm.x &0x40,FP_SRC(%a6) # save EXOP to the stack
1717 1.2.4.2 wiz
1718 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1719 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1720 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1721 1.2.4.2 wiz
1722 1.2.4.2 wiz mov.w &0x30d4,EXC_VOFF(%a6) # vector offset = 0xd4
1723 1.2.4.2 wiz mov.w &0xe005,2+FP_SRC(%a6)
1724 1.2.4.2 wiz
1725 1.2.4.2 wiz frestore FP_SRC(%a6) # restore EXOP
1726 1.2.4.2 wiz
1727 1.2.4.2 wiz unlk %a6
1728 1.2.4.2 wiz
1729 1.2.4.2 wiz bra.l _real_ovfl
1730 1.2.4.2 wiz
1731 1.2.4.2 wiz # underflow can happen for extended precision. extended precision opclass
1732 1.2.4.2 wiz # three instruction exceptions don't update the stack pointer. so, if the
1733 1.2.4.2 wiz # exception occurred from user mode, then simply update a7 and exit normally.
1734 1.2.4.2 wiz # if the exception occurred from supervisor mode, check if
1735 1.2.4.2 wiz fu_unfl:
1736 1.2.4.2 wiz mov.l EXC_A6(%a6),(%a6) # restore a6
1737 1.2.4.2 wiz
1738 1.2.4.2 wiz btst &0x5,EXC_SR(%a6)
1739 1.2.4.2 wiz bne.w fu_unfl_s
1740 1.2.4.2 wiz
1741 1.2.4.2 wiz mov.l EXC_A7(%a6),%a0 # restore a7 whether we need
1742 1.2.4.2 wiz mov.l %a0,%usp # to or not...
1743 1.2.4.2 wiz
1744 1.2.4.2 wiz fu_unfl_cont:
1745 1.2.4.2 wiz fmovm.x &0x40,FP_SRC(%a6) # save EXOP to the stack
1746 1.2.4.2 wiz
1747 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1748 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1749 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1750 1.2.4.2 wiz
1751 1.2.4.2 wiz mov.w &0x30cc,EXC_VOFF(%a6) # vector offset = 0xcc
1752 1.2.4.2 wiz mov.w &0xe003,2+FP_SRC(%a6)
1753 1.2.4.2 wiz
1754 1.2.4.2 wiz frestore FP_SRC(%a6) # restore EXOP
1755 1.2.4.2 wiz
1756 1.2.4.2 wiz unlk %a6
1757 1.2.4.2 wiz
1758 1.2.4.2 wiz bra.l _real_unfl
1759 1.2.4.2 wiz
1760 1.2.4.2 wiz fu_unfl_s:
1761 1.2.4.2 wiz cmpi.b SPCOND_FLG(%a6),&mda7_flg # was the <ea> mode -(sp)?
1762 1.2.4.2 wiz bne.b fu_unfl_cont
1763 1.2.4.2 wiz
1764 1.2.4.2 wiz # the extended precision result is still in fp0. but, we need to save it
1765 1.2.4.2 wiz # somewhere on the stack until we can copy it to its final resting place
1766 1.2.4.2 wiz # (where the exc frame is currently). make sure it's not at the top of the
1767 1.2.4.2 wiz # frame or it will get overwritten when the exc stack frame is shifted "down".
1768 1.2.4.2 wiz fmovm.x &0x80,FP_SRC(%a6) # put answer on stack
1769 1.2.4.2 wiz fmovm.x &0x40,FP_DST(%a6) # put EXOP on stack
1770 1.2.4.2 wiz
1771 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1772 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1773 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1774 1.2.4.2 wiz
1775 1.2.4.2 wiz mov.w &0x30cc,EXC_VOFF(%a6) # vector offset = 0xcc
1776 1.2.4.2 wiz mov.w &0xe003,2+FP_DST(%a6)
1777 1.2.4.2 wiz
1778 1.2.4.2 wiz frestore FP_DST(%a6) # restore EXOP
1779 1.2.4.2 wiz
1780 1.2.4.2 wiz mov.l (%a6),%a6 # restore frame pointer
1781 1.2.4.2 wiz
1782 1.2.4.2 wiz mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
1783 1.2.4.2 wiz mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
1784 1.2.4.2 wiz mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
1785 1.2.4.2 wiz
1786 1.2.4.2 wiz # now, copy the result to the proper place on the stack
1787 1.2.4.2 wiz mov.l LOCAL_SIZE+FP_SRC_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp)
1788 1.2.4.2 wiz mov.l LOCAL_SIZE+FP_SRC_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp)
1789 1.2.4.2 wiz mov.l LOCAL_SIZE+FP_SRC_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp)
1790 1.2.4.2 wiz
1791 1.2.4.2 wiz add.l &LOCAL_SIZE-0x8,%sp
1792 1.2.4.2 wiz
1793 1.2.4.2 wiz bra.l _real_unfl
1794 1.2.4.2 wiz
1795 1.2.4.2 wiz # fmove in and out enter here.
1796 1.2.4.2 wiz fu_inex:
1797 1.2.4.2 wiz fmovm.x &0x40,FP_SRC(%a6) # save EXOP to the stack
1798 1.2.4.2 wiz
1799 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1800 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1801 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1802 1.2.4.2 wiz
1803 1.2.4.2 wiz mov.w &0x30c4,EXC_VOFF(%a6) # vector offset = 0xc4
1804 1.2.4.2 wiz mov.w &0xe001,2+FP_SRC(%a6)
1805 1.2.4.2 wiz
1806 1.2.4.2 wiz frestore FP_SRC(%a6) # restore EXOP
1807 1.2.4.2 wiz
1808 1.2.4.2 wiz unlk %a6
1809 1.2.4.2 wiz
1810 1.2.4.2 wiz
1811 1.2.4.2 wiz bra.l _real_inex
1812 1.2.4.2 wiz
1813 1.2.4.2 wiz #########################################################################
1814 1.2.4.2 wiz #########################################################################
1815 1.2.4.2 wiz fu_in_pack:
1816 1.2.4.2 wiz
1817 1.2.4.2 wiz
1818 1.2.4.2 wiz # I'm not sure at this point what FPSR bits are valid for this instruction.
1819 1.2.4.2 wiz # so, since the emulation routines re-create them anyways, zero exception field
1820 1.2.4.2 wiz andi.l &0x0ff00ff,USER_FPSR(%a6) # zero exception field
1821 1.2.4.2 wiz
1822 1.2.4.2 wiz fmov.l &0x0,%fpcr # zero current control regs
1823 1.2.4.2 wiz fmov.l &0x0,%fpsr
1824 1.2.4.2 wiz
1825 1.2.4.2 wiz bsr.l get_packed # fetch packed src operand
1826 1.2.4.2 wiz
1827 1.2.4.2 wiz lea FP_SRC(%a6),%a0 # pass ptr to src
1828 1.2.4.2 wiz bsr.l set_tag_x # set src optype tag
1829 1.2.4.2 wiz
1830 1.2.4.2 wiz mov.b %d0,STAG(%a6) # save src optype tag
1831 1.2.4.2 wiz
1832 1.2.4.2 wiz bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
1833 1.2.4.2 wiz
1834 1.2.4.2 wiz # bit five of the fp extension word separates the monadic and dyadic operations
1835 1.2.4.2 wiz # at this point
1836 1.2.4.2 wiz btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic?
1837 1.2.4.2 wiz beq.b fu_extract_p # monadic
1838 1.2.4.2 wiz cmpi.b 1+EXC_CMDREG(%a6),&0x3a # is operation an ftst?
1839 1.2.4.2 wiz beq.b fu_extract_p # yes, so it's monadic, too
1840 1.2.4.2 wiz
1841 1.2.4.2 wiz bsr.l load_fpn2 # load dst into FP_DST
1842 1.2.4.2 wiz
1843 1.2.4.2 wiz lea FP_DST(%a6),%a0 # pass: ptr to dst op
1844 1.2.4.2 wiz bsr.l set_tag_x # tag the operand type
1845 1.2.4.2 wiz cmpi.b %d0,&UNNORM # is operand an UNNORM?
1846 1.2.4.2 wiz bne.b fu_op2_done_p # no
1847 1.2.4.2 wiz bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
1848 1.2.4.2 wiz fu_op2_done_p:
1849 1.2.4.2 wiz mov.b %d0,DTAG(%a6) # save dst optype tag
1850 1.2.4.2 wiz
1851 1.2.4.2 wiz fu_extract_p:
1852 1.2.4.2 wiz clr.l %d0
1853 1.2.4.2 wiz mov.b FPCR_MODE(%a6),%d0 # fetch rnd mode/prec
1854 1.2.4.2 wiz
1855 1.2.4.2 wiz bfextu 1+EXC_CMDREG(%a6){&1:&7},%d1 # extract extension
1856 1.2.4.2 wiz
1857 1.2.4.2 wiz lea FP_SRC(%a6),%a0
1858 1.2.4.2 wiz lea FP_DST(%a6),%a1
1859 1.2.4.2 wiz
1860 1.2.4.2 wiz mov.l (tbl_unsupp.l,%pc,%d1.l*4),%d1 # fetch routine addr
1861 1.2.4.2 wiz jsr (tbl_unsupp.l,%pc,%d1.l*1)
1862 1.2.4.2 wiz
1863 1.2.4.2 wiz #
1864 1.2.4.2 wiz # Exceptions in order of precedence:
1865 1.2.4.2 wiz # BSUN : none
1866 1.2.4.2 wiz # SNAN : all dyadic ops
1867 1.2.4.2 wiz # OPERR : fsqrt(-NORM)
1868 1.2.4.2 wiz # OVFL : all except ftst,fcmp
1869 1.2.4.2 wiz # UNFL : all except ftst,fcmp
1870 1.2.4.2 wiz # DZ : fdiv
1871 1.2.4.2 wiz # INEX2 : all except ftst,fcmp
1872 1.2.4.2 wiz # INEX1 : all
1873 1.2.4.2 wiz #
1874 1.2.4.2 wiz
1875 1.2.4.2 wiz # we determine the highest priority exception(if any) set by the
1876 1.2.4.2 wiz # emulation routine that has also been enabled by the user.
1877 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions enabled
1878 1.2.4.2 wiz bne.w fu_in_ena_p # some are enabled
1879 1.2.4.2 wiz
1880 1.2.4.2 wiz fu_in_cont_p:
1881 1.2.4.2 wiz # fcmp and ftst do not store any result.
1882 1.2.4.2 wiz mov.b 1+EXC_CMDREG(%a6),%d0 # fetch extension
1883 1.2.4.2 wiz andi.b &0x38,%d0 # extract bits 3-5
1884 1.2.4.2 wiz cmpi.b %d0,&0x38 # is instr fcmp or ftst?
1885 1.2.4.2 wiz beq.b fu_in_exit_p # yes
1886 1.2.4.2 wiz
1887 1.2.4.2 wiz bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
1888 1.2.4.2 wiz bsr.l store_fpreg # store the result
1889 1.2.4.2 wiz
1890 1.2.4.2 wiz fu_in_exit_p:
1891 1.2.4.2 wiz
1892 1.2.4.2 wiz btst &0x5,EXC_SR(%a6) # user or supervisor?
1893 1.2.4.2 wiz bne.w fu_in_exit_s_p # supervisor
1894 1.2.4.2 wiz
1895 1.2.4.2 wiz mov.l EXC_A7(%a6),%a0 # update user a7
1896 1.2.4.2 wiz mov.l %a0,%usp
1897 1.2.4.2 wiz
1898 1.2.4.2 wiz fu_in_exit_cont_p:
1899 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1900 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1901 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1902 1.2.4.2 wiz
1903 1.2.4.2 wiz unlk %a6 # unravel stack frame
1904 1.2.4.2 wiz
1905 1.2.4.2 wiz btst &0x7,(%sp) # is trace on?
1906 1.2.4.2 wiz bne.w fu_trace_p # yes
1907 1.2.4.2 wiz
1908 1.2.4.2 wiz bra.l _fpsp_done # exit to os
1909 1.2.4.2 wiz
1910 1.2.4.2 wiz # the exception occurred in supervisor mode. check to see if the
1911 1.2.4.2 wiz # addressing mode was (a7)+. if so, we'll need to shift the
1912 1.2.4.2 wiz # stack frame "up".
1913 1.2.4.2 wiz fu_in_exit_s_p:
1914 1.2.4.2 wiz btst &mia7_bit,SPCOND_FLG(%a6) # was ea mode (a7)+
1915 1.2.4.2 wiz beq.b fu_in_exit_cont_p # no
1916 1.2.4.2 wiz
1917 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1918 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1919 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1920 1.2.4.2 wiz
1921 1.2.4.2 wiz unlk %a6 # unravel stack frame
1922 1.2.4.2 wiz
1923 1.2.4.2 wiz # shift the stack frame "up". we don't really care about the <ea> field.
1924 1.2.4.2 wiz mov.l 0x4(%sp),0x10(%sp)
1925 1.2.4.2 wiz mov.l 0x0(%sp),0xc(%sp)
1926 1.2.4.2 wiz add.l &0xc,%sp
1927 1.2.4.2 wiz
1928 1.2.4.2 wiz btst &0x7,(%sp) # is trace on?
1929 1.2.4.2 wiz bne.w fu_trace_p # yes
1930 1.2.4.2 wiz
1931 1.2.4.2 wiz bra.l _fpsp_done # exit to os
1932 1.2.4.2 wiz
1933 1.2.4.2 wiz fu_in_ena_p:
1934 1.2.4.2 wiz and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enabled & set
1935 1.2.4.2 wiz bfffo %d0{&24:&8},%d0 # find highest priority exception
1936 1.2.4.2 wiz bne.b fu_in_exc_p # at least one was set
1937 1.2.4.2 wiz
1938 1.2.4.2 wiz #
1939 1.2.4.2 wiz # No exceptions occurred that were also enabled. Now:
1940 1.2.4.2 wiz #
1941 1.2.4.2 wiz # if (OVFL && ovfl_disabled && inexact_enabled) {
1942 1.2.4.2 wiz # branch to _real_inex() (even if the result was exact!);
1943 1.2.4.2 wiz # } else {
1944 1.2.4.2 wiz # save the result in the proper fp reg (unless the op is fcmp or ftst);
1945 1.2.4.2 wiz # return;
1946 1.2.4.2 wiz # }
1947 1.2.4.2 wiz #
1948 1.2.4.2 wiz btst &ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set?
1949 1.2.4.2 wiz beq.w fu_in_cont_p # no
1950 1.2.4.2 wiz
1951 1.2.4.2 wiz fu_in_ovflchk_p:
1952 1.2.4.2 wiz btst &inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled?
1953 1.2.4.2 wiz beq.w fu_in_cont_p # no
1954 1.2.4.2 wiz bra.w fu_in_exc_ovfl_p # do _real_inex() now
1955 1.2.4.2 wiz
1956 1.2.4.2 wiz #
1957 1.2.4.2 wiz # An exception occurred and that exception was enabled:
1958 1.2.4.2 wiz #
1959 1.2.4.2 wiz # shift enabled exception field into lo byte of d0;
1960 1.2.4.2 wiz # if (((INEX2 || INEX1) && inex_enabled && OVFL && ovfl_disabled) ||
1961 1.2.4.2 wiz # ((INEX2 || INEX1) && inex_enabled && UNFL && unfl_disabled)) {
1962 1.2.4.2 wiz # /*
1963 1.2.4.2 wiz # * this is the case where we must call _real_inex() now or else
1964 1.2.4.2 wiz # * there will be no other way to pass it the exceptional operand
1965 1.2.4.2 wiz # */
1966 1.2.4.2 wiz # call _real_inex();
1967 1.2.4.2 wiz # } else {
1968 1.2.4.2 wiz # restore exc state (SNAN||OPERR||OVFL||UNFL||DZ||INEX) into the FPU;
1969 1.2.4.2 wiz # }
1970 1.2.4.2 wiz #
1971 1.2.4.2 wiz fu_in_exc_p:
1972 1.2.4.2 wiz subi.l &24,%d0 # fix offset to be 0-8
1973 1.2.4.2 wiz cmpi.b %d0,&0x6 # is exception INEX? (6 or 7)
1974 1.2.4.2 wiz blt.b fu_in_exc_exit_p # no
1975 1.2.4.2 wiz
1976 1.2.4.2 wiz # the enabled exception was inexact
1977 1.2.4.2 wiz btst &unfl_bit,FPSR_EXCEPT(%a6) # did disabled underflow occur?
1978 1.2.4.2 wiz bne.w fu_in_exc_unfl_p # yes
1979 1.2.4.2 wiz btst &ovfl_bit,FPSR_EXCEPT(%a6) # did disabled overflow occur?
1980 1.2.4.2 wiz bne.w fu_in_exc_ovfl_p # yes
1981 1.2.4.2 wiz
1982 1.2.4.2 wiz # here, we insert the correct fsave status value into the fsave frame for the
1983 1.2.4.2 wiz # corresponding exception. the operand in the fsave frame should be the original
1984 1.2.4.2 wiz # src operand.
1985 1.2.4.2 wiz # as a reminder for future predicted pain and agony, we are passing in fsave the
1986 1.2.4.2 wiz # "non-skewed" operand for cases of sgl and dbl src INFs,NANs, and DENORMs.
1987 1.2.4.2 wiz # this is INCORRECT for enabled SNAN which would give to the user the skewed SNAN!!!
1988 1.2.4.2 wiz fu_in_exc_exit_p:
1989 1.2.4.2 wiz btst &0x5,EXC_SR(%a6) # user or supervisor?
1990 1.2.4.2 wiz bne.w fu_in_exc_exit_s_p # supervisor
1991 1.2.4.2 wiz
1992 1.2.4.2 wiz mov.l EXC_A7(%a6),%a0 # update user a7
1993 1.2.4.2 wiz mov.l %a0,%usp
1994 1.2.4.2 wiz
1995 1.2.4.2 wiz fu_in_exc_exit_cont_p:
1996 1.2.4.2 wiz mov.w (tbl_except_p.b,%pc,%d0.w*2),2+FP_SRC(%a6)
1997 1.2.4.2 wiz
1998 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
1999 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2000 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2001 1.2.4.2 wiz
2002 1.2.4.2 wiz frestore FP_SRC(%a6) # restore src op
2003 1.2.4.2 wiz
2004 1.2.4.2 wiz unlk %a6
2005 1.2.4.2 wiz
2006 1.2.4.2 wiz btst &0x7,(%sp) # is trace enabled?
2007 1.2.4.2 wiz bne.w fu_trace_p # yes
2008 1.2.4.2 wiz
2009 1.2.4.2 wiz bra.l _fpsp_done
2010 1.2.4.2 wiz
2011 1.2.4.2 wiz tbl_except_p:
2012 1.2.4.2 wiz short 0xe000,0xe006,0xe004,0xe005
2013 1.2.4.2 wiz short 0xe003,0xe002,0xe001,0xe001
2014 1.2.4.2 wiz
2015 1.2.4.2 wiz fu_in_exc_ovfl_p:
2016 1.2.4.2 wiz mov.w &0x3,%d0
2017 1.2.4.2 wiz bra.w fu_in_exc_exit_p
2018 1.2.4.2 wiz
2019 1.2.4.2 wiz fu_in_exc_unfl_p:
2020 1.2.4.2 wiz mov.w &0x4,%d0
2021 1.2.4.2 wiz bra.w fu_in_exc_exit_p
2022 1.2.4.2 wiz
2023 1.2.4.2 wiz fu_in_exc_exit_s_p:
2024 1.2.4.2 wiz btst &mia7_bit,SPCOND_FLG(%a6)
2025 1.2.4.2 wiz beq.b fu_in_exc_exit_cont_p
2026 1.2.4.2 wiz
2027 1.2.4.2 wiz mov.w (tbl_except_p.b,%pc,%d0.w*2),2+FP_SRC(%a6)
2028 1.2.4.2 wiz
2029 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
2030 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2031 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2032 1.2.4.2 wiz
2033 1.2.4.2 wiz frestore FP_SRC(%a6) # restore src op
2034 1.2.4.2 wiz
2035 1.2.4.2 wiz unlk %a6 # unravel stack frame
2036 1.2.4.2 wiz
2037 1.2.4.2 wiz # shift stack frame "up". who cares about <ea> field.
2038 1.2.4.2 wiz mov.l 0x4(%sp),0x10(%sp)
2039 1.2.4.2 wiz mov.l 0x0(%sp),0xc(%sp)
2040 1.2.4.2 wiz add.l &0xc,%sp
2041 1.2.4.2 wiz
2042 1.2.4.2 wiz btst &0x7,(%sp) # is trace on?
2043 1.2.4.2 wiz bne.b fu_trace_p # yes
2044 1.2.4.2 wiz
2045 1.2.4.2 wiz bra.l _fpsp_done # exit to os
2046 1.2.4.2 wiz
2047 1.2.4.2 wiz #
2048 1.2.4.2 wiz # The opclass two PACKED instruction that took an "Unimplemented Data Type"
2049 1.2.4.2 wiz # exception was being traced. Make the "current" PC the FPIAR and put it in the
2050 1.2.4.2 wiz # trace stack frame then jump to _real_trace().
2051 1.2.4.2 wiz #
2052 1.2.4.2 wiz # UNSUPP FRAME TRACE FRAME
2053 1.2.4.2 wiz # ***************** *****************
2054 1.2.4.2 wiz # * EA * * Current *
2055 1.2.4.2 wiz # * * * PC *
2056 1.2.4.2 wiz # ***************** *****************
2057 1.2.4.2 wiz # * 0x2 * 0x0dc * * 0x2 * 0x024 *
2058 1.2.4.2 wiz # ***************** *****************
2059 1.2.4.2 wiz # * Next * * Next *
2060 1.2.4.2 wiz # * PC * * PC *
2061 1.2.4.2 wiz # ***************** *****************
2062 1.2.4.2 wiz # * SR * * SR *
2063 1.2.4.2 wiz # ***************** *****************
2064 1.2.4.2 wiz fu_trace_p:
2065 1.2.4.2 wiz mov.w &0x2024,0x6(%sp)
2066 1.2.4.2 wiz fmov.l %fpiar,0x8(%sp)
2067 1.2.4.2 wiz
2068 1.2.4.2 wiz bra.l _real_trace
2069 1.2.4.2 wiz
2070 1.2.4.2 wiz #########################################################
2071 1.2.4.2 wiz #########################################################
2072 1.2.4.2 wiz fu_out_pack:
2073 1.2.4.2 wiz
2074 1.2.4.2 wiz
2075 1.2.4.2 wiz # I'm not sure at this point what FPSR bits are valid for this instruction.
2076 1.2.4.2 wiz # so, since the emulation routines re-create them anyways, zero exception field.
2077 1.2.4.2 wiz # fmove out doesn't affect ccodes.
2078 1.2.4.2 wiz and.l &0xffff00ff,USER_FPSR(%a6) # zero exception field
2079 1.2.4.2 wiz
2080 1.2.4.2 wiz fmov.l &0x0,%fpcr # zero current control regs
2081 1.2.4.2 wiz fmov.l &0x0,%fpsr
2082 1.2.4.2 wiz
2083 1.2.4.2 wiz bfextu EXC_CMDREG(%a6){&6:&3},%d0
2084 1.2.4.2 wiz bsr.l load_fpn1
2085 1.2.4.2 wiz
2086 1.2.4.2 wiz # unlike other opclass 3, unimplemented data type exceptions, packed must be
2087 1.2.4.2 wiz # able to detect all operand types.
2088 1.2.4.2 wiz lea FP_SRC(%a6),%a0
2089 1.2.4.2 wiz bsr.l set_tag_x # tag the operand type
2090 1.2.4.2 wiz cmpi.b %d0,&UNNORM # is operand an UNNORM?
2091 1.2.4.2 wiz bne.b fu_op2_p # no
2092 1.2.4.2 wiz bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
2093 1.2.4.2 wiz
2094 1.2.4.2 wiz fu_op2_p:
2095 1.2.4.2 wiz mov.b %d0,STAG(%a6) # save src optype tag
2096 1.2.4.2 wiz
2097 1.2.4.2 wiz clr.l %d0
2098 1.2.4.2 wiz mov.b FPCR_MODE(%a6),%d0 # fetch rnd mode/prec
2099 1.2.4.2 wiz
2100 1.2.4.2 wiz lea FP_SRC(%a6),%a0 # pass ptr to src operand
2101 1.2.4.2 wiz
2102 1.2.4.2 wiz mov.l (%a6),EXC_A6(%a6) # in case a6 changes
2103 1.2.4.2 wiz bsr.l fout # call fmove out routine
2104 1.2.4.2 wiz
2105 1.2.4.2 wiz # Exceptions in order of precedence:
2106 1.2.4.2 wiz # BSUN : no
2107 1.2.4.2 wiz # SNAN : yes
2108 1.2.4.2 wiz # OPERR : if ((k_factor > +17) || (dec. exp exceeds 3 digits))
2109 1.2.4.2 wiz # OVFL : no
2110 1.2.4.2 wiz # UNFL : no
2111 1.2.4.2 wiz # DZ : no
2112 1.2.4.2 wiz # INEX2 : yes
2113 1.2.4.2 wiz # INEX1 : no
2114 1.2.4.2 wiz
2115 1.2.4.2 wiz # determine the highest priority exception(if any) set by the
2116 1.2.4.2 wiz # emulation routine that has also been enabled by the user.
2117 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions enabled
2118 1.2.4.2 wiz bne.w fu_out_ena_p # some are enabled
2119 1.2.4.2 wiz
2120 1.2.4.2 wiz fu_out_exit_p:
2121 1.2.4.2 wiz mov.l EXC_A6(%a6),(%a6) # restore a6
2122 1.2.4.2 wiz
2123 1.2.4.2 wiz btst &0x5,EXC_SR(%a6) # user or supervisor?
2124 1.2.4.2 wiz bne.b fu_out_exit_s_p # supervisor
2125 1.2.4.2 wiz
2126 1.2.4.2 wiz mov.l EXC_A7(%a6),%a0 # update user a7
2127 1.2.4.2 wiz mov.l %a0,%usp
2128 1.2.4.2 wiz
2129 1.2.4.2 wiz fu_out_exit_cont_p:
2130 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
2131 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2132 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2133 1.2.4.2 wiz
2134 1.2.4.2 wiz unlk %a6 # unravel stack frame
2135 1.2.4.2 wiz
2136 1.2.4.2 wiz btst &0x7,(%sp) # is trace on?
2137 1.2.4.2 wiz bne.w fu_trace_p # yes
2138 1.2.4.2 wiz
2139 1.2.4.2 wiz bra.l _fpsp_done # exit to os
2140 1.2.4.2 wiz
2141 1.2.4.2 wiz # the exception occurred in supervisor mode. check to see if the
2142 1.2.4.2 wiz # addressing mode was -(a7). if so, we'll need to shift the
2143 1.2.4.2 wiz # stack frame "down".
2144 1.2.4.2 wiz fu_out_exit_s_p:
2145 1.2.4.2 wiz btst &mda7_bit,SPCOND_FLG(%a6) # was ea mode -(a7)
2146 1.2.4.2 wiz beq.b fu_out_exit_cont_p # no
2147 1.2.4.2 wiz
2148 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
2149 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2150 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2151 1.2.4.2 wiz
2152 1.2.4.2 wiz mov.l (%a6),%a6 # restore frame pointer
2153 1.2.4.2 wiz
2154 1.2.4.2 wiz mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
2155 1.2.4.2 wiz mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
2156 1.2.4.2 wiz
2157 1.2.4.2 wiz # now, copy the result to the proper place on the stack
2158 1.2.4.2 wiz mov.l LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp)
2159 1.2.4.2 wiz mov.l LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp)
2160 1.2.4.2 wiz mov.l LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp)
2161 1.2.4.2 wiz
2162 1.2.4.2 wiz add.l &LOCAL_SIZE-0x8,%sp
2163 1.2.4.2 wiz
2164 1.2.4.2 wiz btst &0x7,(%sp)
2165 1.2.4.2 wiz bne.w fu_trace_p
2166 1.2.4.2 wiz
2167 1.2.4.2 wiz bra.l _fpsp_done
2168 1.2.4.2 wiz
2169 1.2.4.2 wiz fu_out_ena_p:
2170 1.2.4.2 wiz and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enabled
2171 1.2.4.2 wiz bfffo %d0{&24:&8},%d0 # find highest priority exception
2172 1.2.4.2 wiz beq.w fu_out_exit_p
2173 1.2.4.2 wiz
2174 1.2.4.2 wiz mov.l EXC_A6(%a6),(%a6) # restore a6
2175 1.2.4.2 wiz
2176 1.2.4.2 wiz # an exception occurred and that exception was enabled.
2177 1.2.4.2 wiz # the only exception possible on packed move out are INEX, OPERR, and SNAN.
2178 1.2.4.2 wiz fu_out_exc_p:
2179 1.2.4.2 wiz cmpi.b %d0,&0x1a
2180 1.2.4.2 wiz bgt.w fu_inex_p2
2181 1.2.4.2 wiz beq.w fu_operr_p
2182 1.2.4.2 wiz
2183 1.2.4.2 wiz fu_snan_p:
2184 1.2.4.2 wiz btst &0x5,EXC_SR(%a6)
2185 1.2.4.2 wiz bne.b fu_snan_s_p
2186 1.2.4.2 wiz
2187 1.2.4.2 wiz mov.l EXC_A7(%a6),%a0
2188 1.2.4.2 wiz mov.l %a0,%usp
2189 1.2.4.2 wiz bra.w fu_snan
2190 1.2.4.2 wiz
2191 1.2.4.2 wiz fu_snan_s_p:
2192 1.2.4.2 wiz cmpi.b SPCOND_FLG(%a6),&mda7_flg
2193 1.2.4.2 wiz bne.w fu_snan
2194 1.2.4.2 wiz
2195 1.2.4.2 wiz # the instruction was "fmove.p fpn,-(a7)" from supervisor mode.
2196 1.2.4.2 wiz # the strategy is to move the exception frame "down" 12 bytes. then, we
2197 1.2.4.2 wiz # can store the default result where the exception frame was.
2198 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
2199 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2200 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2201 1.2.4.2 wiz
2202 1.2.4.2 wiz mov.w &0x30d8,EXC_VOFF(%a6) # vector offset = 0xd0
2203 1.2.4.2 wiz mov.w &0xe006,2+FP_SRC(%a6) # set fsave status
2204 1.2.4.2 wiz
2205 1.2.4.2 wiz frestore FP_SRC(%a6) # restore src operand
2206 1.2.4.2 wiz
2207 1.2.4.2 wiz mov.l (%a6),%a6 # restore frame pointer
2208 1.2.4.2 wiz
2209 1.2.4.2 wiz mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
2210 1.2.4.2 wiz mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
2211 1.2.4.2 wiz mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
2212 1.2.4.2 wiz
2213 1.2.4.2 wiz # now, we copy the default result to it's proper location
2214 1.2.4.2 wiz mov.l LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+0x4(%sp)
2215 1.2.4.2 wiz mov.l LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+0x8(%sp)
2216 1.2.4.2 wiz mov.l LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+0xc(%sp)
2217 1.2.4.2 wiz
2218 1.2.4.2 wiz add.l &LOCAL_SIZE-0x8,%sp
2219 1.2.4.2 wiz
2220 1.2.4.2 wiz
2221 1.2.4.2 wiz bra.l _real_snan
2222 1.2.4.2 wiz
2223 1.2.4.2 wiz fu_operr_p:
2224 1.2.4.2 wiz btst &0x5,EXC_SR(%a6)
2225 1.2.4.2 wiz bne.w fu_operr_p_s
2226 1.2.4.2 wiz
2227 1.2.4.2 wiz mov.l EXC_A7(%a6),%a0
2228 1.2.4.2 wiz mov.l %a0,%usp
2229 1.2.4.2 wiz bra.w fu_operr
2230 1.2.4.2 wiz
2231 1.2.4.2 wiz fu_operr_p_s:
2232 1.2.4.2 wiz cmpi.b SPCOND_FLG(%a6),&mda7_flg
2233 1.2.4.2 wiz bne.w fu_operr
2234 1.2.4.2 wiz
2235 1.2.4.2 wiz # the instruction was "fmove.p fpn,-(a7)" from supervisor mode.
2236 1.2.4.2 wiz # the strategy is to move the exception frame "down" 12 bytes. then, we
2237 1.2.4.2 wiz # can store the default result where the exception frame was.
2238 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
2239 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2240 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2241 1.2.4.2 wiz
2242 1.2.4.2 wiz mov.w &0x30d0,EXC_VOFF(%a6) # vector offset = 0xd0
2243 1.2.4.2 wiz mov.w &0xe004,2+FP_SRC(%a6) # set fsave status
2244 1.2.4.2 wiz
2245 1.2.4.2 wiz frestore FP_SRC(%a6) # restore src operand
2246 1.2.4.2 wiz
2247 1.2.4.2 wiz mov.l (%a6),%a6 # restore frame pointer
2248 1.2.4.2 wiz
2249 1.2.4.2 wiz mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
2250 1.2.4.2 wiz mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
2251 1.2.4.2 wiz mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
2252 1.2.4.2 wiz
2253 1.2.4.2 wiz # now, we copy the default result to it's proper location
2254 1.2.4.2 wiz mov.l LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+0x4(%sp)
2255 1.2.4.2 wiz mov.l LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+0x8(%sp)
2256 1.2.4.2 wiz mov.l LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+0xc(%sp)
2257 1.2.4.2 wiz
2258 1.2.4.2 wiz add.l &LOCAL_SIZE-0x8,%sp
2259 1.2.4.2 wiz
2260 1.2.4.2 wiz
2261 1.2.4.2 wiz bra.l _real_operr
2262 1.2.4.2 wiz
2263 1.2.4.2 wiz fu_inex_p2:
2264 1.2.4.2 wiz btst &0x5,EXC_SR(%a6)
2265 1.2.4.2 wiz bne.w fu_inex_s_p2
2266 1.2.4.2 wiz
2267 1.2.4.2 wiz mov.l EXC_A7(%a6),%a0
2268 1.2.4.2 wiz mov.l %a0,%usp
2269 1.2.4.2 wiz bra.w fu_inex
2270 1.2.4.2 wiz
2271 1.2.4.2 wiz fu_inex_s_p2:
2272 1.2.4.2 wiz cmpi.b SPCOND_FLG(%a6),&mda7_flg
2273 1.2.4.2 wiz bne.w fu_inex
2274 1.2.4.2 wiz
2275 1.2.4.2 wiz # the instruction was "fmove.p fpn,-(a7)" from supervisor mode.
2276 1.2.4.2 wiz # the strategy is to move the exception frame "down" 12 bytes. then, we
2277 1.2.4.2 wiz # can store the default result where the exception frame was.
2278 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
2279 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2280 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2281 1.2.4.2 wiz
2282 1.2.4.2 wiz mov.w &0x30c4,EXC_VOFF(%a6) # vector offset = 0xc4
2283 1.2.4.2 wiz mov.w &0xe001,2+FP_SRC(%a6) # set fsave status
2284 1.2.4.2 wiz
2285 1.2.4.2 wiz frestore FP_SRC(%a6) # restore src operand
2286 1.2.4.2 wiz
2287 1.2.4.2 wiz mov.l (%a6),%a6 # restore frame pointer
2288 1.2.4.2 wiz
2289 1.2.4.2 wiz mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
2290 1.2.4.2 wiz mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
2291 1.2.4.2 wiz mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
2292 1.2.4.2 wiz
2293 1.2.4.2 wiz # now, we copy the default result to it's proper location
2294 1.2.4.2 wiz mov.l LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+0x4(%sp)
2295 1.2.4.2 wiz mov.l LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+0x8(%sp)
2296 1.2.4.2 wiz mov.l LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+0xc(%sp)
2297 1.2.4.2 wiz
2298 1.2.4.2 wiz add.l &LOCAL_SIZE-0x8,%sp
2299 1.2.4.2 wiz
2300 1.2.4.2 wiz
2301 1.2.4.2 wiz bra.l _real_inex
2302 1.2.4.2 wiz
2303 1.2.4.2 wiz #########################################################################
2304 1.2.4.2 wiz
2305 1.2.4.2 wiz #
2306 1.2.4.2 wiz # if we're stuffing a source operand back into an fsave frame then we
2307 1.2.4.2 wiz # have to make sure that for single or double source operands that the
2308 1.2.4.2 wiz # format stuffed is as weird as the hardware usually makes it.
2309 1.2.4.2 wiz #
2310 1.2.4.2 wiz global funimp_skew
2311 1.2.4.2 wiz funimp_skew:
2312 1.2.4.2 wiz bfextu EXC_EXTWORD(%a6){&3:&3},%d0 # extract src specifier
2313 1.2.4.2 wiz cmpi.b %d0,&0x1 # was src sgl?
2314 1.2.4.2 wiz beq.b funimp_skew_sgl # yes
2315 1.2.4.2 wiz cmpi.b %d0,&0x5 # was src dbl?
2316 1.2.4.2 wiz beq.b funimp_skew_dbl # yes
2317 1.2.4.2 wiz rts
2318 1.2.4.2 wiz
2319 1.2.4.2 wiz funimp_skew_sgl:
2320 1.2.4.2 wiz mov.w FP_SRC_EX(%a6),%d0 # fetch DENORM exponent
2321 1.2.4.2 wiz andi.w &0x7fff,%d0 # strip sign
2322 1.2.4.2 wiz beq.b funimp_skew_sgl_not
2323 1.2.4.2 wiz cmpi.w %d0,&0x3f80
2324 1.2.4.2 wiz bgt.b funimp_skew_sgl_not
2325 1.2.4.2 wiz neg.w %d0 # make exponent negative
2326 1.2.4.2 wiz addi.w &0x3f81,%d0 # find amt to shift
2327 1.2.4.2 wiz mov.l FP_SRC_HI(%a6),%d1 # fetch DENORM hi(man)
2328 1.2.4.2 wiz lsr.l %d0,%d1 # shift it
2329 1.2.4.2 wiz bset &31,%d1 # set j-bit
2330 1.2.4.2 wiz mov.l %d1,FP_SRC_HI(%a6) # insert new hi(man)
2331 1.2.4.2 wiz andi.w &0x8000,FP_SRC_EX(%a6) # clear old exponent
2332 1.2.4.2 wiz ori.w &0x3f80,FP_SRC_EX(%a6) # insert new "skewed" exponent
2333 1.2.4.2 wiz funimp_skew_sgl_not:
2334 1.2.4.2 wiz rts
2335 1.2.4.2 wiz
2336 1.2.4.2 wiz funimp_skew_dbl:
2337 1.2.4.2 wiz mov.w FP_SRC_EX(%a6),%d0 # fetch DENORM exponent
2338 1.2.4.2 wiz andi.w &0x7fff,%d0 # strip sign
2339 1.2.4.2 wiz beq.b funimp_skew_dbl_not
2340 1.2.4.2 wiz cmpi.w %d0,&0x3c00
2341 1.2.4.2 wiz bgt.b funimp_skew_dbl_not
2342 1.2.4.2 wiz
2343 1.2.4.2 wiz tst.b FP_SRC_EX(%a6) # make "internal format"
2344 1.2.4.2 wiz smi.b 0x2+FP_SRC(%a6)
2345 1.2.4.2 wiz mov.w %d0,FP_SRC_EX(%a6) # insert exponent with cleared sign
2346 1.2.4.2 wiz clr.l %d0 # clear g,r,s
2347 1.2.4.2 wiz lea FP_SRC(%a6),%a0 # pass ptr to src op
2348 1.2.4.2 wiz mov.w &0x3c01,%d1 # pass denorm threshold
2349 1.2.4.2 wiz bsr.l dnrm_lp # denorm it
2350 1.2.4.2 wiz mov.w &0x3c00,%d0 # new exponent
2351 1.2.4.2 wiz tst.b 0x2+FP_SRC(%a6) # is sign set?
2352 1.2.4.2 wiz beq.b fss_dbl_denorm_done # no
2353 1.2.4.2 wiz bset &15,%d0 # set sign
2354 1.2.4.2 wiz fss_dbl_denorm_done:
2355 1.2.4.2 wiz bset &0x7,FP_SRC_HI(%a6) # set j-bit
2356 1.2.4.2 wiz mov.w %d0,FP_SRC_EX(%a6) # insert new exponent
2357 1.2.4.2 wiz funimp_skew_dbl_not:
2358 1.2.4.2 wiz rts
2359 1.2.4.2 wiz
2360 1.2.4.2 wiz #########################################################################
2361 1.2.4.2 wiz global _mem_write2
2362 1.2.4.2 wiz _mem_write2:
2363 1.2.4.2 wiz btst &0x5,EXC_SR(%a6)
2364 1.2.4.2 wiz beq.l _dmem_write
2365 1.2.4.2 wiz mov.l 0x0(%a0),FP_DST_EX(%a6)
2366 1.2.4.2 wiz mov.l 0x4(%a0),FP_DST_HI(%a6)
2367 1.2.4.2 wiz mov.l 0x8(%a0),FP_DST_LO(%a6)
2368 1.2.4.2 wiz clr.l %d1
2369 1.2.4.2 wiz rts
2370 1.2.4.2 wiz
2371 1.2.4.2 wiz #########################################################################
2372 1.2.4.2 wiz # XDEF **************************************************************** #
2373 1.2.4.2 wiz # _fpsp_effadd(): 060FPSP entry point for FP "Unimplemented #
2374 1.2.4.2 wiz # effective address" exception. #
2375 1.2.4.2 wiz # #
2376 1.2.4.2 wiz # This handler should be the first code executed upon taking the #
2377 1.2.4.2 wiz # FP Unimplemented Effective Address exception in an operating #
2378 1.2.4.2 wiz # system. #
2379 1.2.4.2 wiz # #
2380 1.2.4.2 wiz # XREF **************************************************************** #
2381 1.2.4.2 wiz # _imem_read_long() - read instruction longword #
2382 1.2.4.2 wiz # fix_skewed_ops() - adjust src operand in fsave frame #
2383 1.2.4.2 wiz # set_tag_x() - determine optype of src/dst operands #
2384 1.2.4.2 wiz # store_fpreg() - store opclass 0 or 2 result to FP regfile #
2385 1.2.4.2 wiz # unnorm_fix() - change UNNORM operands to NORM or ZERO #
2386 1.2.4.2 wiz # load_fpn2() - load dst operand from FP regfile #
2387 1.2.4.2 wiz # tbl_unsupp - add of table of emulation routines for opclass 0,2 #
2388 1.2.4.2 wiz # decbin() - convert packed data to FP binary data #
2389 1.2.4.2 wiz # _real_fpu_disabled() - "callout" for "FPU disabled" exception #
2390 1.2.4.2 wiz # _real_access() - "callout" for access error exception #
2391 1.2.4.2 wiz # _mem_read() - read extended immediate operand from memory #
2392 1.2.4.2 wiz # _fpsp_done() - "callout" for exit; work all done #
2393 1.2.4.2 wiz # _real_trace() - "callout" for Trace enabled exception #
2394 1.2.4.2 wiz # fmovm_dynamic() - emulate dynamic fmovm instruction #
2395 1.2.4.2 wiz # fmovm_ctrl() - emulate fmovm control instruction #
2396 1.2.4.2 wiz # #
2397 1.2.4.2 wiz # INPUT *************************************************************** #
2398 1.2.4.2 wiz # - The system stack contains the "Unimplemented <ea>" stk frame #
2399 1.2.4.2 wiz # #
2400 1.2.4.2 wiz # OUTPUT ************************************************************** #
2401 1.2.4.2 wiz # If access error: #
2402 1.2.4.2 wiz # - The system stack is changed to an access error stack frame #
2403 1.2.4.2 wiz # If FPU disabled: #
2404 1.2.4.2 wiz # - The system stack is changed to an FPU disabled stack frame #
2405 1.2.4.2 wiz # If Trace exception enabled: #
2406 1.2.4.2 wiz # - The system stack is changed to a Trace exception stack frame #
2407 1.2.4.2 wiz # Else: (normal case) #
2408 1.2.4.2 wiz # - None (correct result has been stored as appropriate) #
2409 1.2.4.2 wiz # #
2410 1.2.4.2 wiz # ALGORITHM *********************************************************** #
2411 1.2.4.2 wiz # This exception handles 3 types of operations: #
2412 1.2.4.2 wiz # (1) FP Instructions using extended precision or packed immediate #
2413 1.2.4.2 wiz # addressing mode. #
2414 1.2.4.2 wiz # (2) The "fmovm.x" instruction w/ dynamic register specification. #
2415 1.2.4.2 wiz # (3) The "fmovm.l" instruction w/ 2 or 3 control registers. #
2416 1.2.4.2 wiz # #
2417 1.2.4.2 wiz # For immediate data operations, the data is read in w/ a #
2418 1.2.4.2 wiz # _mem_read() "callout", converted to FP binary (if packed), and used #
2419 1.2.4.2 wiz # as the source operand to the instruction specified by the instruction #
2420 1.2.4.2 wiz # word. If no FP exception should be reported ads a result of the #
2421 1.2.4.2 wiz # emulation, then the result is stored to the destination register and #
2422 1.2.4.2 wiz # the handler exits through _fpsp_done(). If an enabled exc has been #
2423 1.2.4.2 wiz # signalled as a result of emulation, then an fsave state frame #
2424 1.2.4.2 wiz # corresponding to the FP exception type must be entered into the 060 #
2425 1.2.4.2 wiz # FPU before exiting. In either the enabled or disabled cases, we #
2426 1.2.4.2 wiz # must also check if a Trace exception is pending, in which case, we #
2427 1.2.4.2 wiz # must create a Trace exception stack frame from the current exception #
2428 1.2.4.2 wiz # stack frame. If no Trace is pending, we simply exit through #
2429 1.2.4.2 wiz # _fpsp_done(). #
2430 1.2.4.2 wiz # For "fmovm.x", call the routine fmovm_dynamic() which will #
2431 1.2.4.2 wiz # decode and emulate the instruction. No FP exceptions can be pending #
2432 1.2.4.2 wiz # as a result of this operation emulation. A Trace exception can be #
2433 1.2.4.2 wiz # pending, though, which means the current stack frame must be changed #
2434 1.2.4.2 wiz # to a Trace stack frame and an exit made through _real_trace(). #
2435 1.2.4.2 wiz # For the case of "fmovm.x Dn,-(a7)", where the offending instruction #
2436 1.2.4.2 wiz # was executed from supervisor mode, this handler must store the FP #
2437 1.2.4.2 wiz # register file values to the system stack by itself since #
2438 1.2.4.2 wiz # fmovm_dynamic() can't handle this. A normal exit is made through #
2439 1.2.4.2 wiz # fpsp_done(). #
2440 1.2.4.2 wiz # For "fmovm.l", fmovm_ctrl() is used to emulate the instruction. #
2441 1.2.4.2 wiz # Again, a Trace exception may be pending and an exit made through #
2442 1.2.4.2 wiz # _real_trace(). Else, a normal exit is made through _fpsp_done(). #
2443 1.2.4.2 wiz # #
2444 1.2.4.2 wiz # Before any of the above is attempted, it must be checked to #
2445 1.2.4.2 wiz # see if the FPU is disabled. Since the "Unimp <ea>" exception is taken #
2446 1.2.4.2 wiz # before the "FPU disabled" exception, but the "FPU disabled" exception #
2447 1.2.4.2 wiz # has higher priority, we check the disabled bit in the PCR. If set, #
2448 1.2.4.2 wiz # then we must create an 8 word "FPU disabled" exception stack frame #
2449 1.2.4.2 wiz # from the current 4 word exception stack frame. This includes #
2450 1.2.4.2 wiz # reproducing the effective address of the instruction to put on the #
2451 1.2.4.2 wiz # new stack frame. #
2452 1.2.4.2 wiz # #
2453 1.2.4.2 wiz # In the process of all emulation work, if a _mem_read() #
2454 1.2.4.2 wiz # "callout" returns a failing result indicating an access error, then #
2455 1.2.4.2 wiz # we must create an access error stack frame from the current stack #
2456 1.2.4.2 wiz # frame. This information includes a faulting address and a fault- #
2457 1.2.4.2 wiz # status-longword. These are created within this handler. #
2458 1.2.4.2 wiz # #
2459 1.2.4.2 wiz #########################################################################
2460 1.2.4.2 wiz
2461 1.2.4.2 wiz global _fpsp_effadd
2462 1.2.4.2 wiz _fpsp_effadd:
2463 1.2.4.2 wiz
2464 1.2.4.2 wiz # This exception type takes priority over the "Line F Emulator"
2465 1.2.4.2 wiz # exception. Therefore, the FPU could be disabled when entering here.
2466 1.2.4.2 wiz # So, we must check to see if it's disabled and handle that case separately.
2467 1.2.4.2 wiz mov.l %d0,-(%sp) # save d0
2468 1.2.4.2 wiz movc %pcr,%d0 # load proc cr
2469 1.2.4.2 wiz btst &0x1,%d0 # is FPU disabled?
2470 1.2.4.2 wiz bne.w iea_disabled # yes
2471 1.2.4.2 wiz mov.l (%sp)+,%d0 # restore d0
2472 1.2.4.2 wiz
2473 1.2.4.2 wiz link %a6,&-LOCAL_SIZE # init stack frame
2474 1.2.4.2 wiz
2475 1.2.4.2 wiz movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2476 1.2.4.2 wiz fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
2477 1.2.4.2 wiz fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
2478 1.2.4.2 wiz
2479 1.2.4.2 wiz # PC of instruction that took the exception is the PC in the frame
2480 1.2.4.2 wiz mov.l EXC_PC(%a6),EXC_EXTWPTR(%a6)
2481 1.2.4.2 wiz
2482 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
2483 1.2.4.2 wiz addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
2484 1.2.4.2 wiz bsr.l _imem_read_long # fetch the instruction words
2485 1.2.4.2 wiz mov.l %d0,EXC_OPWORD(%a6) # store OPWORD and EXTWORD
2486 1.2.4.2 wiz
2487 1.2.4.2 wiz #########################################################################
2488 1.2.4.2 wiz
2489 1.2.4.2 wiz tst.w %d0 # is operation fmovem?
2490 1.2.4.2 wiz bmi.w iea_fmovm # yes
2491 1.2.4.2 wiz
2492 1.2.4.2 wiz #
2493 1.2.4.2 wiz # here, we will have:
2494 1.2.4.2 wiz # fabs fdabs fsabs facos fmod
2495 1.2.4.2 wiz # fadd fdadd fsadd fasin frem
2496 1.2.4.2 wiz # fcmp fatan fscale
2497 1.2.4.2 wiz # fdiv fddiv fsdiv fatanh fsin
2498 1.2.4.2 wiz # fint fcos fsincos
2499 1.2.4.2 wiz # fintrz fcosh fsinh
2500 1.2.4.2 wiz # fmove fdmove fsmove fetox ftan
2501 1.2.4.2 wiz # fmul fdmul fsmul fetoxm1 ftanh
2502 1.2.4.2 wiz # fneg fdneg fsneg fgetexp ftentox
2503 1.2.4.2 wiz # fsgldiv fgetman ftwotox
2504 1.2.4.2 wiz # fsglmul flog10
2505 1.2.4.2 wiz # fsqrt flog2
2506 1.2.4.2 wiz # fsub fdsub fssub flogn
2507 1.2.4.2 wiz # ftst flognp1
2508 1.2.4.2 wiz # which can all use f<op>.{x,p}
2509 1.2.4.2 wiz # so, now it's immediate data extended precision AND PACKED FORMAT!
2510 1.2.4.2 wiz #
2511 1.2.4.2 wiz iea_op:
2512 1.2.4.2 wiz andi.l &0x00ff00ff,USER_FPSR(%a6)
2513 1.2.4.2 wiz
2514 1.2.4.2 wiz btst &0xa,%d0 # is src fmt x or p?
2515 1.2.4.2 wiz bne.b iea_op_pack # packed
2516 1.2.4.2 wiz
2517 1.2.4.2 wiz
2518 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # pass: ptr to #<data>
2519 1.2.4.2 wiz lea FP_SRC(%a6),%a1 # pass: ptr to super addr
2520 1.2.4.2 wiz mov.l &0xc,%d0 # pass: 12 bytes
2521 1.2.4.2 wiz bsr.l _imem_read # read extended immediate
2522 1.2.4.2 wiz
2523 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
2524 1.2.4.2 wiz bne.w iea_iacc # yes
2525 1.2.4.2 wiz
2526 1.2.4.2 wiz bra.b iea_op_setsrc
2527 1.2.4.2 wiz
2528 1.2.4.2 wiz iea_op_pack:
2529 1.2.4.2 wiz
2530 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # pass: ptr to #<data>
2531 1.2.4.2 wiz lea FP_SRC(%a6),%a1 # pass: ptr to super dst
2532 1.2.4.2 wiz mov.l &0xc,%d0 # pass: 12 bytes
2533 1.2.4.2 wiz bsr.l _imem_read # read packed operand
2534 1.2.4.2 wiz
2535 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
2536 1.2.4.2 wiz bne.w iea_iacc # yes
2537 1.2.4.2 wiz
2538 1.2.4.2 wiz # The packed operand is an INF or a NAN if the exponent field is all ones.
2539 1.2.4.2 wiz bfextu FP_SRC(%a6){&1:&15},%d0 # get exp
2540 1.2.4.2 wiz cmpi.w %d0,&0x7fff # INF or NAN?
2541 1.2.4.2 wiz beq.b iea_op_setsrc # operand is an INF or NAN
2542 1.2.4.2 wiz
2543 1.2.4.2 wiz # The packed operand is a zero if the mantissa is all zero, else it's
2544 1.2.4.2 wiz # a normal packed op.
2545 1.2.4.2 wiz mov.b 3+FP_SRC(%a6),%d0 # get byte 4
2546 1.2.4.2 wiz andi.b &0x0f,%d0 # clear all but last nybble
2547 1.2.4.2 wiz bne.b iea_op_gp_not_spec # not a zero
2548 1.2.4.2 wiz tst.l FP_SRC_HI(%a6) # is lw 2 zero?
2549 1.2.4.2 wiz bne.b iea_op_gp_not_spec # not a zero
2550 1.2.4.2 wiz tst.l FP_SRC_LO(%a6) # is lw 3 zero?
2551 1.2.4.2 wiz beq.b iea_op_setsrc # operand is a ZERO
2552 1.2.4.2 wiz iea_op_gp_not_spec:
2553 1.2.4.2 wiz lea FP_SRC(%a6),%a0 # pass: ptr to packed op
2554 1.2.4.2 wiz bsr.l decbin # convert to extended
2555 1.2.4.2 wiz fmovm.x &0x80,FP_SRC(%a6) # make this the srcop
2556 1.2.4.2 wiz
2557 1.2.4.2 wiz iea_op_setsrc:
2558 1.2.4.2 wiz addi.l &0xc,EXC_EXTWPTR(%a6) # update extension word pointer
2559 1.2.4.2 wiz
2560 1.2.4.2 wiz # FP_SRC now holds the src operand.
2561 1.2.4.2 wiz lea FP_SRC(%a6),%a0 # pass: ptr to src op
2562 1.2.4.2 wiz bsr.l set_tag_x # tag the operand type
2563 1.2.4.2 wiz mov.b %d0,STAG(%a6) # could be ANYTHING!!!
2564 1.2.4.2 wiz cmpi.b %d0,&UNNORM # is operand an UNNORM?
2565 1.2.4.2 wiz bne.b iea_op_getdst # no
2566 1.2.4.2 wiz bsr.l unnorm_fix # yes; convert to NORM/DENORM/ZERO
2567 1.2.4.2 wiz mov.b %d0,STAG(%a6) # set new optype tag
2568 1.2.4.2 wiz iea_op_getdst:
2569 1.2.4.2 wiz clr.b STORE_FLG(%a6) # clear "store result" boolean
2570 1.2.4.2 wiz
2571 1.2.4.2 wiz btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic?
2572 1.2.4.2 wiz beq.b iea_op_extract # monadic
2573 1.2.4.2 wiz btst &0x4,1+EXC_CMDREG(%a6) # is operation fsincos,ftst,fcmp?
2574 1.2.4.2 wiz bne.b iea_op_spec # yes
2575 1.2.4.2 wiz
2576 1.2.4.2 wiz iea_op_loaddst:
2577 1.2.4.2 wiz bfextu EXC_CMDREG(%a6){&6:&3},%d0 # fetch dst regno
2578 1.2.4.2 wiz bsr.l load_fpn2 # load dst operand
2579 1.2.4.2 wiz
2580 1.2.4.2 wiz lea FP_DST(%a6),%a0 # pass: ptr to dst op
2581 1.2.4.2 wiz bsr.l set_tag_x # tag the operand type
2582 1.2.4.2 wiz mov.b %d0,DTAG(%a6) # could be ANYTHING!!!
2583 1.2.4.2 wiz cmpi.b %d0,&UNNORM # is operand an UNNORM?
2584 1.2.4.2 wiz bne.b iea_op_extract # no
2585 1.2.4.2 wiz bsr.l unnorm_fix # yes; convert to NORM/DENORM/ZERO
2586 1.2.4.2 wiz mov.b %d0,DTAG(%a6) # set new optype tag
2587 1.2.4.2 wiz bra.b iea_op_extract
2588 1.2.4.2 wiz
2589 1.2.4.2 wiz # the operation is fsincos, ftst, or fcmp. only fcmp is dyadic
2590 1.2.4.2 wiz iea_op_spec:
2591 1.2.4.2 wiz btst &0x3,1+EXC_CMDREG(%a6) # is operation fsincos?
2592 1.2.4.2 wiz beq.b iea_op_extract # yes
2593 1.2.4.2 wiz # now, we're left with ftst and fcmp. so, first let's tag them so that they don't
2594 1.2.4.2 wiz # store a result. then, only fcmp will branch back and pick up a dst operand.
2595 1.2.4.2 wiz st STORE_FLG(%a6) # don't store a final result
2596 1.2.4.2 wiz btst &0x1,1+EXC_CMDREG(%a6) # is operation fcmp?
2597 1.2.4.2 wiz beq.b iea_op_loaddst # yes
2598 1.2.4.2 wiz
2599 1.2.4.2 wiz iea_op_extract:
2600 1.2.4.2 wiz clr.l %d0
2601 1.2.4.2 wiz mov.b FPCR_MODE(%a6),%d0 # pass: rnd mode,prec
2602 1.2.4.2 wiz
2603 1.2.4.2 wiz mov.b 1+EXC_CMDREG(%a6),%d1
2604 1.2.4.2 wiz andi.w &0x007f,%d1 # extract extension
2605 1.2.4.2 wiz
2606 1.2.4.2 wiz fmov.l &0x0,%fpcr
2607 1.2.4.2 wiz fmov.l &0x0,%fpsr
2608 1.2.4.2 wiz
2609 1.2.4.2 wiz lea FP_SRC(%a6),%a0
2610 1.2.4.2 wiz lea FP_DST(%a6),%a1
2611 1.2.4.2 wiz
2612 1.2.4.2 wiz mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
2613 1.2.4.2 wiz jsr (tbl_unsupp.l,%pc,%d1.l*1)
2614 1.2.4.2 wiz
2615 1.2.4.2 wiz #
2616 1.2.4.2 wiz # Exceptions in order of precedence:
2617 1.2.4.2 wiz # BSUN : none
2618 1.2.4.2 wiz # SNAN : all operations
2619 1.2.4.2 wiz # OPERR : all reg-reg or mem-reg operations that can normally operr
2620 1.2.4.2 wiz # OVFL : same as OPERR
2621 1.2.4.2 wiz # UNFL : same as OPERR
2622 1.2.4.2 wiz # DZ : same as OPERR
2623 1.2.4.2 wiz # INEX2 : same as OPERR
2624 1.2.4.2 wiz # INEX1 : all packed immediate operations
2625 1.2.4.2 wiz #
2626 1.2.4.2 wiz
2627 1.2.4.2 wiz # we determine the highest priority exception(if any) set by the
2628 1.2.4.2 wiz # emulation routine that has also been enabled by the user.
2629 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions enabled
2630 1.2.4.2 wiz bne.b iea_op_ena # some are enabled
2631 1.2.4.2 wiz
2632 1.2.4.2 wiz # now, we save the result, unless, of course, the operation was ftst or fcmp.
2633 1.2.4.2 wiz # these don't save results.
2634 1.2.4.2 wiz iea_op_save:
2635 1.2.4.2 wiz tst.b STORE_FLG(%a6) # does this op store a result?
2636 1.2.4.2 wiz bne.b iea_op_exit1 # exit with no frestore
2637 1.2.4.2 wiz
2638 1.2.4.2 wiz iea_op_store:
2639 1.2.4.2 wiz bfextu EXC_CMDREG(%a6){&6:&3},%d0 # fetch dst regno
2640 1.2.4.2 wiz bsr.l store_fpreg # store the result
2641 1.2.4.2 wiz
2642 1.2.4.2 wiz iea_op_exit1:
2643 1.2.4.2 wiz mov.l EXC_PC(%a6),USER_FPIAR(%a6) # set FPIAR to "Current PC"
2644 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),EXC_PC(%a6) # set "Next PC" in exc frame
2645 1.2.4.2 wiz
2646 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
2647 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2648 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2649 1.2.4.2 wiz
2650 1.2.4.2 wiz unlk %a6 # unravel the frame
2651 1.2.4.2 wiz
2652 1.2.4.2 wiz btst &0x7,(%sp) # is trace on?
2653 1.2.4.2 wiz bne.w iea_op_trace # yes
2654 1.2.4.2 wiz
2655 1.2.4.2 wiz bra.l _fpsp_done # exit to os
2656 1.2.4.2 wiz
2657 1.2.4.2 wiz iea_op_ena:
2658 1.2.4.2 wiz and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enable and set
2659 1.2.4.2 wiz bfffo %d0{&24:&8},%d0 # find highest priority exception
2660 1.2.4.2 wiz bne.b iea_op_exc # at least one was set
2661 1.2.4.2 wiz
2662 1.2.4.2 wiz # no exception occurred. now, did a disabled, exact overflow occur with inexact
2663 1.2.4.2 wiz # enabled? if so, then we have to stuff an overflow frame into the FPU.
2664 1.2.4.2 wiz btst &ovfl_bit,FPSR_EXCEPT(%a6) # did overflow occur?
2665 1.2.4.2 wiz beq.b iea_op_save
2666 1.2.4.2 wiz
2667 1.2.4.2 wiz iea_op_ovfl:
2668 1.2.4.2 wiz btst &inex2_bit,FPCR_ENABLE(%a6) # is inexact enabled?
2669 1.2.4.2 wiz beq.b iea_op_store # no
2670 1.2.4.2 wiz bra.b iea_op_exc_ovfl # yes
2671 1.2.4.2 wiz
2672 1.2.4.2 wiz # an enabled exception occurred. we have to insert the exception type back into
2673 1.2.4.2 wiz # the machine.
2674 1.2.4.2 wiz iea_op_exc:
2675 1.2.4.2 wiz subi.l &24,%d0 # fix offset to be 0-8
2676 1.2.4.2 wiz cmpi.b %d0,&0x6 # is exception INEX?
2677 1.2.4.2 wiz bne.b iea_op_exc_force # no
2678 1.2.4.2 wiz
2679 1.2.4.2 wiz # the enabled exception was inexact. so, if it occurs with an overflow
2680 1.2.4.2 wiz # or underflow that was disabled, then we have to force an overflow or
2681 1.2.4.2 wiz # underflow frame.
2682 1.2.4.2 wiz btst &ovfl_bit,FPSR_EXCEPT(%a6) # did overflow occur?
2683 1.2.4.2 wiz bne.b iea_op_exc_ovfl # yes
2684 1.2.4.2 wiz btst &unfl_bit,FPSR_EXCEPT(%a6) # did underflow occur?
2685 1.2.4.2 wiz bne.b iea_op_exc_unfl # yes
2686 1.2.4.2 wiz
2687 1.2.4.2 wiz iea_op_exc_force:
2688 1.2.4.2 wiz mov.w (tbl_iea_except.b,%pc,%d0.w*2),2+FP_SRC(%a6)
2689 1.2.4.2 wiz bra.b iea_op_exit2 # exit with frestore
2690 1.2.4.2 wiz
2691 1.2.4.2 wiz tbl_iea_except:
2692 1.2.4.2 wiz short 0xe002, 0xe006, 0xe004, 0xe005
2693 1.2.4.2 wiz short 0xe003, 0xe002, 0xe001, 0xe001
2694 1.2.4.2 wiz
2695 1.2.4.2 wiz iea_op_exc_ovfl:
2696 1.2.4.2 wiz mov.w &0xe005,2+FP_SRC(%a6)
2697 1.2.4.2 wiz bra.b iea_op_exit2
2698 1.2.4.2 wiz
2699 1.2.4.2 wiz iea_op_exc_unfl:
2700 1.2.4.2 wiz mov.w &0xe003,2+FP_SRC(%a6)
2701 1.2.4.2 wiz
2702 1.2.4.2 wiz iea_op_exit2:
2703 1.2.4.2 wiz mov.l EXC_PC(%a6),USER_FPIAR(%a6) # set FPIAR to "Current PC"
2704 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),EXC_PC(%a6) # set "Next PC" in exc frame
2705 1.2.4.2 wiz
2706 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
2707 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2708 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2709 1.2.4.2 wiz
2710 1.2.4.2 wiz frestore FP_SRC(%a6) # restore exceptional state
2711 1.2.4.2 wiz
2712 1.2.4.2 wiz unlk %a6 # unravel the frame
2713 1.2.4.2 wiz
2714 1.2.4.2 wiz btst &0x7,(%sp) # is trace on?
2715 1.2.4.2 wiz bne.b iea_op_trace # yes
2716 1.2.4.2 wiz
2717 1.2.4.2 wiz bra.l _fpsp_done # exit to os
2718 1.2.4.2 wiz
2719 1.2.4.2 wiz #
2720 1.2.4.2 wiz # The opclass two instruction that took an "Unimplemented Effective Address"
2721 1.2.4.2 wiz # exception was being traced. Make the "current" PC the FPIAR and put it in
2722 1.2.4.2 wiz # the trace stack frame then jump to _real_trace().
2723 1.2.4.2 wiz #
2724 1.2.4.2 wiz # UNIMP EA FRAME TRACE FRAME
2725 1.2.4.2 wiz # ***************** *****************
2726 1.2.4.2 wiz # * 0x0 * 0x0f0 * * Current *
2727 1.2.4.2 wiz # ***************** * PC *
2728 1.2.4.2 wiz # * Current * *****************
2729 1.2.4.2 wiz # * PC * * 0x2 * 0x024 *
2730 1.2.4.2 wiz # ***************** *****************
2731 1.2.4.2 wiz # * SR * * Next *
2732 1.2.4.2 wiz # ***************** * PC *
2733 1.2.4.2 wiz # *****************
2734 1.2.4.2 wiz # * SR *
2735 1.2.4.2 wiz # *****************
2736 1.2.4.2 wiz iea_op_trace:
2737 1.2.4.2 wiz mov.l (%sp),-(%sp) # shift stack frame "down"
2738 1.2.4.2 wiz mov.w 0x8(%sp),0x4(%sp)
2739 1.2.4.2 wiz mov.w &0x2024,0x6(%sp) # stk fmt = 0x2; voff = 0x024
2740 1.2.4.2 wiz fmov.l %fpiar,0x8(%sp) # "Current PC" is in FPIAR
2741 1.2.4.2 wiz
2742 1.2.4.2 wiz bra.l _real_trace
2743 1.2.4.2 wiz
2744 1.2.4.2 wiz #########################################################################
2745 1.2.4.2 wiz iea_fmovm:
2746 1.2.4.2 wiz btst &14,%d0 # ctrl or data reg
2747 1.2.4.2 wiz beq.w iea_fmovm_ctrl
2748 1.2.4.2 wiz
2749 1.2.4.2 wiz iea_fmovm_data:
2750 1.2.4.2 wiz
2751 1.2.4.2 wiz btst &0x5,EXC_SR(%a6) # user or supervisor mode
2752 1.2.4.2 wiz bne.b iea_fmovm_data_s
2753 1.2.4.2 wiz
2754 1.2.4.2 wiz iea_fmovm_data_u:
2755 1.2.4.2 wiz mov.l %usp,%a0
2756 1.2.4.2 wiz mov.l %a0,EXC_A7(%a6) # store current a7
2757 1.2.4.2 wiz bsr.l fmovm_dynamic # do dynamic fmovm
2758 1.2.4.2 wiz mov.l EXC_A7(%a6),%a0 # load possibly new a7
2759 1.2.4.2 wiz mov.l %a0,%usp # update usp
2760 1.2.4.2 wiz bra.w iea_fmovm_exit
2761 1.2.4.2 wiz
2762 1.2.4.2 wiz iea_fmovm_data_s:
2763 1.2.4.2 wiz clr.b SPCOND_FLG(%a6)
2764 1.2.4.2 wiz lea 0x2+EXC_VOFF(%a6),%a0
2765 1.2.4.2 wiz mov.l %a0,EXC_A7(%a6)
2766 1.2.4.2 wiz bsr.l fmovm_dynamic # do dynamic fmovm
2767 1.2.4.2 wiz
2768 1.2.4.2 wiz cmpi.b SPCOND_FLG(%a6),&mda7_flg
2769 1.2.4.2 wiz beq.w iea_fmovm_data_predec
2770 1.2.4.2 wiz cmpi.b SPCOND_FLG(%a6),&mia7_flg
2771 1.2.4.2 wiz bne.w iea_fmovm_exit
2772 1.2.4.2 wiz
2773 1.2.4.2 wiz # right now, d0 = the size.
2774 1.2.4.2 wiz # the data has been fetched from the supervisor stack, but we have not
2775 1.2.4.2 wiz # incremented the stack pointer by the appropriate number of bytes.
2776 1.2.4.2 wiz # do it here.
2777 1.2.4.2 wiz iea_fmovm_data_postinc:
2778 1.2.4.2 wiz btst &0x7,EXC_SR(%a6)
2779 1.2.4.2 wiz bne.b iea_fmovm_data_pi_trace
2780 1.2.4.2 wiz
2781 1.2.4.2 wiz mov.w EXC_SR(%a6),(EXC_SR,%a6,%d0)
2782 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),(EXC_PC,%a6,%d0)
2783 1.2.4.2 wiz mov.w &0x00f0,(EXC_VOFF,%a6,%d0)
2784 1.2.4.2 wiz
2785 1.2.4.2 wiz lea (EXC_SR,%a6,%d0),%a0
2786 1.2.4.2 wiz mov.l %a0,EXC_SR(%a6)
2787 1.2.4.2 wiz
2788 1.2.4.2 wiz fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1
2789 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2790 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2791 1.2.4.2 wiz
2792 1.2.4.2 wiz unlk %a6
2793 1.2.4.2 wiz mov.l (%sp)+,%sp
2794 1.2.4.2 wiz bra.l _fpsp_done
2795 1.2.4.2 wiz
2796 1.2.4.2 wiz iea_fmovm_data_pi_trace:
2797 1.2.4.2 wiz mov.w EXC_SR(%a6),(EXC_SR-0x4,%a6,%d0)
2798 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),(EXC_PC-0x4,%a6,%d0)
2799 1.2.4.2 wiz mov.w &0x2024,(EXC_VOFF-0x4,%a6,%d0)
2800 1.2.4.2 wiz mov.l EXC_PC(%a6),(EXC_VOFF+0x2-0x4,%a6,%d0)
2801 1.2.4.2 wiz
2802 1.2.4.2 wiz lea (EXC_SR-0x4,%a6,%d0),%a0
2803 1.2.4.2 wiz mov.l %a0,EXC_SR(%a6)
2804 1.2.4.2 wiz
2805 1.2.4.2 wiz fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1
2806 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2807 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2808 1.2.4.2 wiz
2809 1.2.4.2 wiz unlk %a6
2810 1.2.4.2 wiz mov.l (%sp)+,%sp
2811 1.2.4.2 wiz bra.l _real_trace
2812 1.2.4.2 wiz
2813 1.2.4.2 wiz # right now, d1 = size and d0 = the strg.
2814 1.2.4.2 wiz iea_fmovm_data_predec:
2815 1.2.4.2 wiz mov.b %d1,EXC_VOFF(%a6) # store strg
2816 1.2.4.2 wiz mov.b %d0,0x1+EXC_VOFF(%a6) # store size
2817 1.2.4.2 wiz
2818 1.2.4.2 wiz fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1
2819 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2820 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2821 1.2.4.2 wiz
2822 1.2.4.2 wiz mov.l (%a6),-(%sp) # make a copy of a6
2823 1.2.4.2 wiz mov.l %d0,-(%sp) # save d0
2824 1.2.4.2 wiz mov.l %d1,-(%sp) # save d1
2825 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),-(%sp) # make a copy of Next PC
2826 1.2.4.2 wiz
2827 1.2.4.2 wiz clr.l %d0
2828 1.2.4.2 wiz mov.b 0x1+EXC_VOFF(%a6),%d0 # fetch size
2829 1.2.4.2 wiz neg.l %d0 # get negative of size
2830 1.2.4.2 wiz
2831 1.2.4.2 wiz btst &0x7,EXC_SR(%a6) # is trace enabled?
2832 1.2.4.2 wiz beq.b iea_fmovm_data_p2
2833 1.2.4.2 wiz
2834 1.2.4.2 wiz mov.w EXC_SR(%a6),(EXC_SR-0x4,%a6,%d0)
2835 1.2.4.2 wiz mov.l EXC_PC(%a6),(EXC_VOFF-0x2,%a6,%d0)
2836 1.2.4.2 wiz mov.l (%sp)+,(EXC_PC-0x4,%a6,%d0)
2837 1.2.4.2 wiz mov.w &0x2024,(EXC_VOFF-0x4,%a6,%d0)
2838 1.2.4.2 wiz
2839 1.2.4.2 wiz pea (%a6,%d0) # create final sp
2840 1.2.4.2 wiz bra.b iea_fmovm_data_p3
2841 1.2.4.2 wiz
2842 1.2.4.2 wiz iea_fmovm_data_p2:
2843 1.2.4.2 wiz mov.w EXC_SR(%a6),(EXC_SR,%a6,%d0)
2844 1.2.4.2 wiz mov.l (%sp)+,(EXC_PC,%a6,%d0)
2845 1.2.4.2 wiz mov.w &0x00f0,(EXC_VOFF,%a6,%d0)
2846 1.2.4.2 wiz
2847 1.2.4.2 wiz pea (0x4,%a6,%d0) # create final sp
2848 1.2.4.2 wiz
2849 1.2.4.2 wiz iea_fmovm_data_p3:
2850 1.2.4.2 wiz clr.l %d1
2851 1.2.4.2 wiz mov.b EXC_VOFF(%a6),%d1 # fetch strg
2852 1.2.4.2 wiz
2853 1.2.4.2 wiz tst.b %d1
2854 1.2.4.2 wiz bpl.b fm_1
2855 1.2.4.2 wiz fmovm.x &0x80,(0x4+0x8,%a6,%d0)
2856 1.2.4.2 wiz addi.l &0xc,%d0
2857 1.2.4.2 wiz fm_1:
2858 1.2.4.2 wiz lsl.b &0x1,%d1
2859 1.2.4.2 wiz bpl.b fm_2
2860 1.2.4.2 wiz fmovm.x &0x40,(0x4+0x8,%a6,%d0)
2861 1.2.4.2 wiz addi.l &0xc,%d0
2862 1.2.4.2 wiz fm_2:
2863 1.2.4.2 wiz lsl.b &0x1,%d1
2864 1.2.4.2 wiz bpl.b fm_3
2865 1.2.4.2 wiz fmovm.x &0x20,(0x4+0x8,%a6,%d0)
2866 1.2.4.2 wiz addi.l &0xc,%d0
2867 1.2.4.2 wiz fm_3:
2868 1.2.4.2 wiz lsl.b &0x1,%d1
2869 1.2.4.2 wiz bpl.b fm_4
2870 1.2.4.2 wiz fmovm.x &0x10,(0x4+0x8,%a6,%d0)
2871 1.2.4.2 wiz addi.l &0xc,%d0
2872 1.2.4.2 wiz fm_4:
2873 1.2.4.2 wiz lsl.b &0x1,%d1
2874 1.2.4.2 wiz bpl.b fm_5
2875 1.2.4.2 wiz fmovm.x &0x08,(0x4+0x8,%a6,%d0)
2876 1.2.4.2 wiz addi.l &0xc,%d0
2877 1.2.4.2 wiz fm_5:
2878 1.2.4.2 wiz lsl.b &0x1,%d1
2879 1.2.4.2 wiz bpl.b fm_6
2880 1.2.4.2 wiz fmovm.x &0x04,(0x4+0x8,%a6,%d0)
2881 1.2.4.2 wiz addi.l &0xc,%d0
2882 1.2.4.2 wiz fm_6:
2883 1.2.4.2 wiz lsl.b &0x1,%d1
2884 1.2.4.2 wiz bpl.b fm_7
2885 1.2.4.2 wiz fmovm.x &0x02,(0x4+0x8,%a6,%d0)
2886 1.2.4.2 wiz addi.l &0xc,%d0
2887 1.2.4.2 wiz fm_7:
2888 1.2.4.2 wiz lsl.b &0x1,%d1
2889 1.2.4.2 wiz bpl.b fm_end
2890 1.2.4.2 wiz fmovm.x &0x01,(0x4+0x8,%a6,%d0)
2891 1.2.4.2 wiz fm_end:
2892 1.2.4.2 wiz mov.l 0x4(%sp),%d1
2893 1.2.4.2 wiz mov.l 0x8(%sp),%d0
2894 1.2.4.2 wiz mov.l 0xc(%sp),%a6
2895 1.2.4.2 wiz mov.l (%sp)+,%sp
2896 1.2.4.2 wiz
2897 1.2.4.2 wiz btst &0x7,(%sp) # is trace enabled?
2898 1.2.4.2 wiz beq.l _fpsp_done
2899 1.2.4.2 wiz bra.l _real_trace
2900 1.2.4.2 wiz
2901 1.2.4.2 wiz #########################################################################
2902 1.2.4.2 wiz iea_fmovm_ctrl:
2903 1.2.4.2 wiz
2904 1.2.4.2 wiz bsr.l fmovm_ctrl # load ctrl regs
2905 1.2.4.2 wiz
2906 1.2.4.2 wiz iea_fmovm_exit:
2907 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
2908 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2909 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2910 1.2.4.2 wiz
2911 1.2.4.2 wiz btst &0x7,EXC_SR(%a6) # is trace on?
2912 1.2.4.2 wiz bne.b iea_fmovm_trace # yes
2913 1.2.4.2 wiz
2914 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),EXC_PC(%a6) # set Next PC
2915 1.2.4.2 wiz
2916 1.2.4.2 wiz unlk %a6 # unravel the frame
2917 1.2.4.2 wiz
2918 1.2.4.2 wiz bra.l _fpsp_done # exit to os
2919 1.2.4.2 wiz
2920 1.2.4.2 wiz #
2921 1.2.4.2 wiz # The control reg instruction that took an "Unimplemented Effective Address"
2922 1.2.4.2 wiz # exception was being traced. The "Current PC" for the trace frame is the
2923 1.2.4.2 wiz # PC stacked for Unimp EA. The "Next PC" is in EXC_EXTWPTR.
2924 1.2.4.2 wiz # After fixing the stack frame, jump to _real_trace().
2925 1.2.4.2 wiz #
2926 1.2.4.2 wiz # UNIMP EA FRAME TRACE FRAME
2927 1.2.4.2 wiz # ***************** *****************
2928 1.2.4.2 wiz # * 0x0 * 0x0f0 * * Current *
2929 1.2.4.2 wiz # ***************** * PC *
2930 1.2.4.2 wiz # * Current * *****************
2931 1.2.4.2 wiz # * PC * * 0x2 * 0x024 *
2932 1.2.4.2 wiz # ***************** *****************
2933 1.2.4.2 wiz # * SR * * Next *
2934 1.2.4.2 wiz # ***************** * PC *
2935 1.2.4.2 wiz # *****************
2936 1.2.4.2 wiz # * SR *
2937 1.2.4.2 wiz # *****************
2938 1.2.4.2 wiz # this ain't a pretty solution, but it works:
2939 1.2.4.2 wiz # -restore a6 (not with unlk)
2940 1.2.4.2 wiz # -shift stack frame down over where old a6 used to be
2941 1.2.4.2 wiz # -add LOCAL_SIZE to stack pointer
2942 1.2.4.2 wiz iea_fmovm_trace:
2943 1.2.4.2 wiz mov.l (%a6),%a6 # restore frame pointer
2944 1.2.4.2 wiz mov.w EXC_SR+LOCAL_SIZE(%sp),0x0+LOCAL_SIZE(%sp)
2945 1.2.4.2 wiz mov.l EXC_PC+LOCAL_SIZE(%sp),0x8+LOCAL_SIZE(%sp)
2946 1.2.4.2 wiz mov.l EXC_EXTWPTR+LOCAL_SIZE(%sp),0x2+LOCAL_SIZE(%sp)
2947 1.2.4.2 wiz mov.w &0x2024,0x6+LOCAL_SIZE(%sp) # stk fmt = 0x2; voff = 0x024
2948 1.2.4.2 wiz add.l &LOCAL_SIZE,%sp # clear stack frame
2949 1.2.4.2 wiz
2950 1.2.4.2 wiz bra.l _real_trace
2951 1.2.4.2 wiz
2952 1.2.4.2 wiz #########################################################################
2953 1.2.4.2 wiz # The FPU is disabled and so we should really have taken the "Line
2954 1.2.4.2 wiz # F Emulator" exception. So, here we create an 8-word stack frame
2955 1.2.4.2 wiz # from our 4-word stack frame. This means we must calculate the length
2956 1.2.4.2 wiz # of the faulting instruction to get the "next PC". This is trivial for
2957 1.2.4.2 wiz # immediate operands but requires some extra work for fmovm dynamic
2958 1.2.4.2 wiz # which can use most addressing modes.
2959 1.2.4.2 wiz iea_disabled:
2960 1.2.4.2 wiz mov.l (%sp)+,%d0 # restore d0
2961 1.2.4.2 wiz
2962 1.2.4.2 wiz link %a6,&-LOCAL_SIZE # init stack frame
2963 1.2.4.2 wiz
2964 1.2.4.2 wiz movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2965 1.2.4.2 wiz
2966 1.2.4.2 wiz # PC of instruction that took the exception is the PC in the frame
2967 1.2.4.2 wiz mov.l EXC_PC(%a6),EXC_EXTWPTR(%a6)
2968 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
2969 1.2.4.2 wiz addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
2970 1.2.4.2 wiz bsr.l _imem_read_long # fetch the instruction words
2971 1.2.4.2 wiz mov.l %d0,EXC_OPWORD(%a6) # store OPWORD and EXTWORD
2972 1.2.4.2 wiz
2973 1.2.4.2 wiz tst.w %d0 # is instr fmovm?
2974 1.2.4.2 wiz bmi.b iea_dis_fmovm # yes
2975 1.2.4.2 wiz # instruction is using an extended precision immediate operand. therefore,
2976 1.2.4.2 wiz # the total instruction length is 16 bytes.
2977 1.2.4.2 wiz iea_dis_immed:
2978 1.2.4.2 wiz mov.l &0x10,%d0 # 16 bytes of instruction
2979 1.2.4.2 wiz bra.b iea_dis_cont
2980 1.2.4.2 wiz iea_dis_fmovm:
2981 1.2.4.2 wiz btst &0xe,%d0 # is instr fmovm ctrl
2982 1.2.4.2 wiz bne.b iea_dis_fmovm_data # no
2983 1.2.4.2 wiz # the instruction is a fmovm.l with 2 or 3 registers.
2984 1.2.4.2 wiz bfextu %d0{&19:&3},%d1
2985 1.2.4.2 wiz mov.l &0xc,%d0
2986 1.2.4.2 wiz cmpi.b %d1,&0x7 # move all regs?
2987 1.2.4.2 wiz bne.b iea_dis_cont
2988 1.2.4.2 wiz addq.l &0x4,%d0
2989 1.2.4.2 wiz bra.b iea_dis_cont
2990 1.2.4.2 wiz # the instruction is an fmovm.x dynamic which can use many addressing
2991 1.2.4.2 wiz # modes and thus can have several different total instruction lengths.
2992 1.2.4.2 wiz # call fmovm_calc_ea which will go through the ea calc process and,
2993 1.2.4.2 wiz # as a by-product, will tell us how long the instruction is.
2994 1.2.4.2 wiz iea_dis_fmovm_data:
2995 1.2.4.2 wiz clr.l %d0
2996 1.2.4.2 wiz bsr.l fmovm_calc_ea
2997 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%d0
2998 1.2.4.2 wiz sub.l EXC_PC(%a6),%d0
2999 1.2.4.2 wiz iea_dis_cont:
3000 1.2.4.2 wiz mov.w %d0,EXC_VOFF(%a6) # store stack shift value
3001 1.2.4.2 wiz
3002 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3003 1.2.4.2 wiz
3004 1.2.4.2 wiz unlk %a6
3005 1.2.4.2 wiz
3006 1.2.4.2 wiz # here, we actually create the 8-word frame from the 4-word frame,
3007 1.2.4.2 wiz # with the "next PC" as additional info.
3008 1.2.4.2 wiz # the <ea> field is let as undefined.
3009 1.2.4.2 wiz subq.l &0x8,%sp # make room for new stack
3010 1.2.4.2 wiz mov.l %d0,-(%sp) # save d0
3011 1.2.4.2 wiz mov.w 0xc(%sp),0x4(%sp) # move SR
3012 1.2.4.2 wiz mov.l 0xe(%sp),0x6(%sp) # move Current PC
3013 1.2.4.2 wiz clr.l %d0
3014 1.2.4.2 wiz mov.w 0x12(%sp),%d0
3015 1.2.4.2 wiz mov.l 0x6(%sp),0x10(%sp) # move Current PC
3016 1.2.4.2 wiz add.l %d0,0x6(%sp) # make Next PC
3017 1.2.4.2 wiz mov.w &0x402c,0xa(%sp) # insert offset,frame format
3018 1.2.4.2 wiz mov.l (%sp)+,%d0 # restore d0
3019 1.2.4.2 wiz
3020 1.2.4.2 wiz bra.l _real_fpu_disabled
3021 1.2.4.2 wiz
3022 1.2.4.2 wiz ##########
3023 1.2.4.2 wiz
3024 1.2.4.2 wiz iea_iacc:
3025 1.2.4.2 wiz movc %pcr,%d0
3026 1.2.4.2 wiz btst &0x1,%d0
3027 1.2.4.2 wiz bne.b iea_iacc_cont
3028 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
3029 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 on stack
3030 1.2.4.2 wiz iea_iacc_cont:
3031 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3032 1.2.4.2 wiz
3033 1.2.4.2 wiz unlk %a6
3034 1.2.4.2 wiz
3035 1.2.4.2 wiz subq.w &0x8,%sp # make stack frame bigger
3036 1.2.4.2 wiz mov.l 0x8(%sp),(%sp) # store SR,hi(PC)
3037 1.2.4.2 wiz mov.w 0xc(%sp),0x4(%sp) # store lo(PC)
3038 1.2.4.2 wiz mov.w &0x4008,0x6(%sp) # store voff
3039 1.2.4.2 wiz mov.l 0x2(%sp),0x8(%sp) # store ea
3040 1.2.4.2 wiz mov.l &0x09428001,0xc(%sp) # store fslw
3041 1.2.4.2 wiz
3042 1.2.4.2 wiz iea_acc_done:
3043 1.2.4.2 wiz btst &0x5,(%sp) # user or supervisor mode?
3044 1.2.4.2 wiz beq.b iea_acc_done2 # user
3045 1.2.4.2 wiz bset &0x2,0xd(%sp) # set supervisor TM bit
3046 1.2.4.2 wiz
3047 1.2.4.2 wiz iea_acc_done2:
3048 1.2.4.2 wiz bra.l _real_access
3049 1.2.4.2 wiz
3050 1.2.4.2 wiz iea_dacc:
3051 1.2.4.2 wiz lea -LOCAL_SIZE(%a6),%sp
3052 1.2.4.2 wiz
3053 1.2.4.2 wiz movc %pcr,%d1
3054 1.2.4.2 wiz btst &0x1,%d1
3055 1.2.4.2 wiz bne.b iea_dacc_cont
3056 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 on stack
3057 1.2.4.2 wiz fmovm.l LOCAL_SIZE+USER_FPCR(%sp),%fpcr,%fpsr,%fpiar # restore ctrl regs
3058 1.2.4.2 wiz iea_dacc_cont:
3059 1.2.4.2 wiz mov.l (%a6),%a6
3060 1.2.4.2 wiz
3061 1.2.4.2 wiz mov.l 0x4+LOCAL_SIZE(%sp),-0x8+0x4+LOCAL_SIZE(%sp)
3062 1.2.4.2 wiz mov.w 0x8+LOCAL_SIZE(%sp),-0x8+0x8+LOCAL_SIZE(%sp)
3063 1.2.4.2 wiz mov.w &0x4008,-0x8+0xa+LOCAL_SIZE(%sp)
3064 1.2.4.2 wiz mov.l %a0,-0x8+0xc+LOCAL_SIZE(%sp)
3065 1.2.4.2 wiz mov.w %d0,-0x8+0x10+LOCAL_SIZE(%sp)
3066 1.2.4.2 wiz mov.w &0x0001,-0x8+0x12+LOCAL_SIZE(%sp)
3067 1.2.4.2 wiz
3068 1.2.4.2 wiz movm.l LOCAL_SIZE+EXC_DREGS(%sp),&0x0303 # restore d0-d1/a0-a1
3069 1.2.4.2 wiz add.w &LOCAL_SIZE-0x4,%sp
3070 1.2.4.2 wiz
3071 1.2.4.2 wiz bra.b iea_acc_done
3072 1.2.4.2 wiz
3073 1.2.4.2 wiz #########################################################################
3074 1.2.4.2 wiz # XDEF **************************************************************** #
3075 1.2.4.2 wiz # _fpsp_operr(): 060FPSP entry point for FP Operr exception. #
3076 1.2.4.2 wiz # #
3077 1.2.4.2 wiz # This handler should be the first code executed upon taking the #
3078 1.2.4.2 wiz # FP Operand Error exception in an operating system. #
3079 1.2.4.2 wiz # #
3080 1.2.4.2 wiz # XREF **************************************************************** #
3081 1.2.4.2 wiz # _imem_read_long() - read instruction longword #
3082 1.2.4.2 wiz # fix_skewed_ops() - adjust src operand in fsave frame #
3083 1.2.4.2 wiz # _real_operr() - "callout" to operating system operr handler #
3084 1.2.4.2 wiz # _dmem_write_{byte,word,long}() - store data to mem (opclass 3) #
3085 1.2.4.2 wiz # store_dreg_{b,w,l}() - store data to data regfile (opclass 3) #
3086 1.2.4.2 wiz # facc_out_{b,w,l}() - store to memory took access error (opcl 3) #
3087 1.2.4.2 wiz # #
3088 1.2.4.2 wiz # INPUT *************************************************************** #
3089 1.2.4.2 wiz # - The system stack contains the FP Operr exception frame #
3090 1.2.4.2 wiz # - The fsave frame contains the source operand #
3091 1.2.4.2 wiz # #
3092 1.2.4.2 wiz # OUTPUT ************************************************************** #
3093 1.2.4.2 wiz # No access error: #
3094 1.2.4.2 wiz # - The system stack is unchanged #
3095 1.2.4.2 wiz # - The fsave frame contains the adjusted src op for opclass 0,2 #
3096 1.2.4.2 wiz # #
3097 1.2.4.2 wiz # ALGORITHM *********************************************************** #
3098 1.2.4.2 wiz # In a system where the FP Operr exception is enabled, the goal #
3099 1.2.4.2 wiz # is to get to the handler specified at _real_operr(). But, on the 060, #
3100 1.2.4.2 wiz # for opclass zero and two instruction taking this exception, the #
3101 1.2.4.2 wiz # input operand in the fsave frame may be incorrect for some cases #
3102 1.2.4.2 wiz # and needs to be corrected. This handler calls fix_skewed_ops() to #
3103 1.2.4.2 wiz # do just this and then exits through _real_operr(). #
3104 1.2.4.2 wiz # For opclass 3 instructions, the 060 doesn't store the default #
3105 1.2.4.2 wiz # operr result out to memory or data register file as it should. #
3106 1.2.4.2 wiz # This code must emulate the move out before finally exiting through #
3107 1.2.4.2 wiz # _real_inex(). The move out, if to memory, is performed using #
3108 1.2.4.2 wiz # _mem_write() "callout" routines that may return a failing result. #
3109 1.2.4.2 wiz # In this special case, the handler must exit through facc_out() #
3110 1.2.4.2 wiz # which creates an access error stack frame from the current operr #
3111 1.2.4.2 wiz # stack frame. #
3112 1.2.4.2 wiz # #
3113 1.2.4.2 wiz #########################################################################
3114 1.2.4.2 wiz
3115 1.2.4.2 wiz global _fpsp_operr
3116 1.2.4.2 wiz _fpsp_operr:
3117 1.2.4.2 wiz
3118 1.2.4.2 wiz link.w %a6,&-LOCAL_SIZE # init stack frame
3119 1.2.4.2 wiz
3120 1.2.4.2 wiz fsave FP_SRC(%a6) # grab the "busy" frame
3121 1.2.4.2 wiz
3122 1.2.4.2 wiz movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3123 1.2.4.2 wiz fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
3124 1.2.4.2 wiz fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
3125 1.2.4.2 wiz
3126 1.2.4.2 wiz # the FPIAR holds the "current PC" of the faulting instruction
3127 1.2.4.2 wiz mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
3128 1.2.4.2 wiz
3129 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
3130 1.2.4.2 wiz addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
3131 1.2.4.2 wiz bsr.l _imem_read_long # fetch the instruction words
3132 1.2.4.2 wiz mov.l %d0,EXC_OPWORD(%a6)
3133 1.2.4.2 wiz
3134 1.2.4.2 wiz ##############################################################################
3135 1.2.4.2 wiz
3136 1.2.4.2 wiz btst &13,%d0 # is instr an fmove out?
3137 1.2.4.2 wiz bne.b foperr_out # fmove out
3138 1.2.4.2 wiz
3139 1.2.4.2 wiz
3140 1.2.4.2 wiz # here, we simply see if the operand in the fsave frame needs to be "unskewed".
3141 1.2.4.2 wiz # this would be the case for opclass two operations with a source infinity or
3142 1.2.4.2 wiz # denorm operand in the sgl or dbl format. NANs also become skewed, but can't
3143 1.2.4.2 wiz # cause an operr so we don't need to check for them here.
3144 1.2.4.2 wiz lea FP_SRC(%a6),%a0 # pass: ptr to src op
3145 1.2.4.2 wiz bsr.l fix_skewed_ops # fix src op
3146 1.2.4.2 wiz
3147 1.2.4.2 wiz foperr_exit:
3148 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
3149 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
3150 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3151 1.2.4.2 wiz
3152 1.2.4.2 wiz frestore FP_SRC(%a6)
3153 1.2.4.2 wiz
3154 1.2.4.2 wiz unlk %a6
3155 1.2.4.2 wiz bra.l _real_operr
3156 1.2.4.2 wiz
3157 1.2.4.2 wiz ########################################################################
3158 1.2.4.2 wiz
3159 1.2.4.2 wiz #
3160 1.2.4.2 wiz # the hardware does not save the default result to memory on enabled
3161 1.2.4.2 wiz # operand error exceptions. we do this here before passing control to
3162 1.2.4.2 wiz # the user operand error handler.
3163 1.2.4.2 wiz #
3164 1.2.4.2 wiz # byte, word, and long destination format operations can pass
3165 1.2.4.2 wiz # through here. we simply need to test the sign of the src
3166 1.2.4.2 wiz # operand and save the appropriate minimum or maximum integer value
3167 1.2.4.2 wiz # to the effective address as pointed to by the stacked effective address.
3168 1.2.4.2 wiz #
3169 1.2.4.2 wiz # although packed opclass three operations can take operand error
3170 1.2.4.2 wiz # exceptions, they won't pass through here since they are caught
3171 1.2.4.2 wiz # first by the unsupported data format exception handler. that handler
3172 1.2.4.2 wiz # sends them directly to _real_operr() if necessary.
3173 1.2.4.2 wiz #
3174 1.2.4.2 wiz foperr_out:
3175 1.2.4.2 wiz
3176 1.2.4.2 wiz mov.w FP_SRC_EX(%a6),%d1 # fetch exponent
3177 1.2.4.2 wiz andi.w &0x7fff,%d1
3178 1.2.4.2 wiz cmpi.w %d1,&0x7fff
3179 1.2.4.2 wiz bne.b foperr_out_not_qnan
3180 1.2.4.2 wiz # the operand is either an infinity or a QNAN.
3181 1.2.4.2 wiz tst.l FP_SRC_LO(%a6)
3182 1.2.4.2 wiz bne.b foperr_out_qnan
3183 1.2.4.2 wiz mov.l FP_SRC_HI(%a6),%d1
3184 1.2.4.2 wiz andi.l &0x7fffffff,%d1
3185 1.2.4.2 wiz beq.b foperr_out_not_qnan
3186 1.2.4.2 wiz foperr_out_qnan:
3187 1.2.4.2 wiz mov.l FP_SRC_HI(%a6),L_SCR1(%a6)
3188 1.2.4.2 wiz bra.b foperr_out_jmp
3189 1.2.4.2 wiz
3190 1.2.4.2 wiz foperr_out_not_qnan:
3191 1.2.4.2 wiz mov.l &0x7fffffff,%d1
3192 1.2.4.2 wiz tst.b FP_SRC_EX(%a6)
3193 1.2.4.2 wiz bpl.b foperr_out_not_qnan2
3194 1.2.4.2 wiz addq.l &0x1,%d1
3195 1.2.4.2 wiz foperr_out_not_qnan2:
3196 1.2.4.2 wiz mov.l %d1,L_SCR1(%a6)
3197 1.2.4.2 wiz
3198 1.2.4.2 wiz foperr_out_jmp:
3199 1.2.4.2 wiz bfextu %d0{&19:&3},%d0 # extract dst format field
3200 1.2.4.2 wiz mov.b 1+EXC_OPWORD(%a6),%d1 # extract <ea> mode,reg
3201 1.2.4.2 wiz mov.w (tbl_operr.b,%pc,%d0.w*2),%a0
3202 1.2.4.2 wiz jmp (tbl_operr.b,%pc,%a0)
3203 1.2.4.2 wiz
3204 1.2.4.2 wiz tbl_operr:
3205 1.2.4.2 wiz short foperr_out_l - tbl_operr # long word integer
3206 1.2.4.2 wiz short tbl_operr - tbl_operr # sgl prec shouldn't happen
3207 1.2.4.2 wiz short tbl_operr - tbl_operr # ext prec shouldn't happen
3208 1.2.4.2 wiz short foperr_exit - tbl_operr # packed won't enter here
3209 1.2.4.2 wiz short foperr_out_w - tbl_operr # word integer
3210 1.2.4.2 wiz short tbl_operr - tbl_operr # dbl prec shouldn't happen
3211 1.2.4.2 wiz short foperr_out_b - tbl_operr # byte integer
3212 1.2.4.2 wiz short tbl_operr - tbl_operr # packed won't enter here
3213 1.2.4.2 wiz
3214 1.2.4.2 wiz foperr_out_b:
3215 1.2.4.2 wiz mov.b L_SCR1(%a6),%d0 # load positive default result
3216 1.2.4.2 wiz cmpi.b %d1,&0x7 # is <ea> mode a data reg?
3217 1.2.4.2 wiz ble.b foperr_out_b_save_dn # yes
3218 1.2.4.2 wiz mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
3219 1.2.4.2 wiz bsr.l _dmem_write_byte # write the default result
3220 1.2.4.2 wiz
3221 1.2.4.2 wiz tst.l %d1 # did dstore fail?
3222 1.2.4.2 wiz bne.l facc_out_b # yes
3223 1.2.4.2 wiz
3224 1.2.4.2 wiz bra.w foperr_exit
3225 1.2.4.2 wiz foperr_out_b_save_dn:
3226 1.2.4.2 wiz andi.w &0x0007,%d1
3227 1.2.4.2 wiz bsr.l store_dreg_b # store result to regfile
3228 1.2.4.2 wiz bra.w foperr_exit
3229 1.2.4.2 wiz
3230 1.2.4.2 wiz foperr_out_w:
3231 1.2.4.2 wiz mov.w L_SCR1(%a6),%d0 # load positive default result
3232 1.2.4.2 wiz cmpi.b %d1,&0x7 # is <ea> mode a data reg?
3233 1.2.4.2 wiz ble.b foperr_out_w_save_dn # yes
3234 1.2.4.2 wiz mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
3235 1.2.4.2 wiz bsr.l _dmem_write_word # write the default result
3236 1.2.4.2 wiz
3237 1.2.4.2 wiz tst.l %d1 # did dstore fail?
3238 1.2.4.2 wiz bne.l facc_out_w # yes
3239 1.2.4.2 wiz
3240 1.2.4.2 wiz bra.w foperr_exit
3241 1.2.4.2 wiz foperr_out_w_save_dn:
3242 1.2.4.2 wiz andi.w &0x0007,%d1
3243 1.2.4.2 wiz bsr.l store_dreg_w # store result to regfile
3244 1.2.4.2 wiz bra.w foperr_exit
3245 1.2.4.2 wiz
3246 1.2.4.2 wiz foperr_out_l:
3247 1.2.4.2 wiz mov.l L_SCR1(%a6),%d0 # load positive default result
3248 1.2.4.2 wiz cmpi.b %d1,&0x7 # is <ea> mode a data reg?
3249 1.2.4.2 wiz ble.b foperr_out_l_save_dn # yes
3250 1.2.4.2 wiz mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
3251 1.2.4.2 wiz bsr.l _dmem_write_long # write the default result
3252 1.2.4.2 wiz
3253 1.2.4.2 wiz tst.l %d1 # did dstore fail?
3254 1.2.4.2 wiz bne.l facc_out_l # yes
3255 1.2.4.2 wiz
3256 1.2.4.2 wiz bra.w foperr_exit
3257 1.2.4.2 wiz foperr_out_l_save_dn:
3258 1.2.4.2 wiz andi.w &0x0007,%d1
3259 1.2.4.2 wiz bsr.l store_dreg_l # store result to regfile
3260 1.2.4.2 wiz bra.w foperr_exit
3261 1.2.4.2 wiz
3262 1.2.4.2 wiz #########################################################################
3263 1.2.4.2 wiz # XDEF **************************************************************** #
3264 1.2.4.2 wiz # _fpsp_snan(): 060FPSP entry point for FP SNAN exception. #
3265 1.2.4.2 wiz # #
3266 1.2.4.2 wiz # This handler should be the first code executed upon taking the #
3267 1.2.4.2 wiz # FP Signalling NAN exception in an operating system. #
3268 1.2.4.2 wiz # #
3269 1.2.4.2 wiz # XREF **************************************************************** #
3270 1.2.4.2 wiz # _imem_read_long() - read instruction longword #
3271 1.2.4.2 wiz # fix_skewed_ops() - adjust src operand in fsave frame #
3272 1.2.4.2 wiz # _real_snan() - "callout" to operating system SNAN handler #
3273 1.2.4.2 wiz # _dmem_write_{byte,word,long}() - store data to mem (opclass 3) #
3274 1.2.4.2 wiz # store_dreg_{b,w,l}() - store data to data regfile (opclass 3) #
3275 1.2.4.2 wiz # facc_out_{b,w,l,d,x}() - store to mem took acc error (opcl 3) #
3276 1.2.4.2 wiz # _calc_ea_fout() - fix An if <ea> is -() or ()+; also get <ea> #
3277 1.2.4.2 wiz # #
3278 1.2.4.2 wiz # INPUT *************************************************************** #
3279 1.2.4.2 wiz # - The system stack contains the FP SNAN exception frame #
3280 1.2.4.2 wiz # - The fsave frame contains the source operand #
3281 1.2.4.2 wiz # #
3282 1.2.4.2 wiz # OUTPUT ************************************************************** #
3283 1.2.4.2 wiz # No access error: #
3284 1.2.4.2 wiz # - The system stack is unchanged #
3285 1.2.4.2 wiz # - The fsave frame contains the adjusted src op for opclass 0,2 #
3286 1.2.4.2 wiz # #
3287 1.2.4.2 wiz # ALGORITHM *********************************************************** #
3288 1.2.4.2 wiz # In a system where the FP SNAN exception is enabled, the goal #
3289 1.2.4.2 wiz # is to get to the handler specified at _real_snan(). But, on the 060, #
3290 1.2.4.2 wiz # for opclass zero and two instructions taking this exception, the #
3291 1.2.4.2 wiz # input operand in the fsave frame may be incorrect for some cases #
3292 1.2.4.2 wiz # and needs to be corrected. This handler calls fix_skewed_ops() to #
3293 1.2.4.2 wiz # do just this and then exits through _real_snan(). #
3294 1.2.4.2 wiz # For opclass 3 instructions, the 060 doesn't store the default #
3295 1.2.4.2 wiz # SNAN result out to memory or data register file as it should. #
3296 1.2.4.2 wiz # This code must emulate the move out before finally exiting through #
3297 1.2.4.2 wiz # _real_snan(). The move out, if to memory, is performed using #
3298 1.2.4.2 wiz # _mem_write() "callout" routines that may return a failing result. #
3299 1.2.4.2 wiz # In this special case, the handler must exit through facc_out() #
3300 1.2.4.2 wiz # which creates an access error stack frame from the current SNAN #
3301 1.2.4.2 wiz # stack frame. #
3302 1.2.4.2 wiz # For the case of an extended precision opclass 3 instruction, #
3303 1.2.4.2 wiz # if the effective addressing mode was -() or ()+, then the address #
3304 1.2.4.2 wiz # register must get updated by calling _calc_ea_fout(). If the <ea> #
3305 1.2.4.2 wiz # was -(a7) from supervisor mode, then the exception frame currently #
3306 1.2.4.2 wiz # on the system stack must be carefully moved "down" to make room #
3307 1.2.4.2 wiz # for the operand being moved. #
3308 1.2.4.2 wiz # #
3309 1.2.4.2 wiz #########################################################################
3310 1.2.4.2 wiz
3311 1.2.4.2 wiz global _fpsp_snan
3312 1.2.4.2 wiz _fpsp_snan:
3313 1.2.4.2 wiz
3314 1.2.4.2 wiz link.w %a6,&-LOCAL_SIZE # init stack frame
3315 1.2.4.2 wiz
3316 1.2.4.2 wiz fsave FP_SRC(%a6) # grab the "busy" frame
3317 1.2.4.2 wiz
3318 1.2.4.2 wiz movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3319 1.2.4.2 wiz fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
3320 1.2.4.2 wiz fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
3321 1.2.4.2 wiz
3322 1.2.4.2 wiz # the FPIAR holds the "current PC" of the faulting instruction
3323 1.2.4.2 wiz mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
3324 1.2.4.2 wiz
3325 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
3326 1.2.4.2 wiz addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
3327 1.2.4.2 wiz bsr.l _imem_read_long # fetch the instruction words
3328 1.2.4.2 wiz mov.l %d0,EXC_OPWORD(%a6)
3329 1.2.4.2 wiz
3330 1.2.4.2 wiz ##############################################################################
3331 1.2.4.2 wiz
3332 1.2.4.2 wiz btst &13,%d0 # is instr an fmove out?
3333 1.2.4.2 wiz bne.w fsnan_out # fmove out
3334 1.2.4.2 wiz
3335 1.2.4.2 wiz
3336 1.2.4.2 wiz # here, we simply see if the operand in the fsave frame needs to be "unskewed".
3337 1.2.4.2 wiz # this would be the case for opclass two operations with a source infinity or
3338 1.2.4.2 wiz # denorm operand in the sgl or dbl format. NANs also become skewed and must be
3339 1.2.4.2 wiz # fixed here.
3340 1.2.4.2 wiz lea FP_SRC(%a6),%a0 # pass: ptr to src op
3341 1.2.4.2 wiz bsr.l fix_skewed_ops # fix src op
3342 1.2.4.2 wiz
3343 1.2.4.2 wiz fsnan_exit:
3344 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
3345 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
3346 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3347 1.2.4.2 wiz
3348 1.2.4.2 wiz frestore FP_SRC(%a6)
3349 1.2.4.2 wiz
3350 1.2.4.2 wiz unlk %a6
3351 1.2.4.2 wiz bra.l _real_snan
3352 1.2.4.2 wiz
3353 1.2.4.2 wiz ########################################################################
3354 1.2.4.2 wiz
3355 1.2.4.2 wiz #
3356 1.2.4.2 wiz # the hardware does not save the default result to memory on enabled
3357 1.2.4.2 wiz # snan exceptions. we do this here before passing control to
3358 1.2.4.2 wiz # the user snan handler.
3359 1.2.4.2 wiz #
3360 1.2.4.2 wiz # byte, word, long, and packed destination format operations can pass
3361 1.2.4.2 wiz # through here. since packed format operations already were handled by
3362 1.2.4.2 wiz # fpsp_unsupp(), then we need to do nothing else for them here.
3363 1.2.4.2 wiz # for byte, word, and long, we simply need to test the sign of the src
3364 1.2.4.2 wiz # operand and save the appropriate minimum or maximum integer value
3365 1.2.4.2 wiz # to the effective address as pointed to by the stacked effective address.
3366 1.2.4.2 wiz #
3367 1.2.4.2 wiz fsnan_out:
3368 1.2.4.2 wiz
3369 1.2.4.2 wiz bfextu %d0{&19:&3},%d0 # extract dst format field
3370 1.2.4.2 wiz mov.b 1+EXC_OPWORD(%a6),%d1 # extract <ea> mode,reg
3371 1.2.4.2 wiz mov.w (tbl_snan.b,%pc,%d0.w*2),%a0
3372 1.2.4.2 wiz jmp (tbl_snan.b,%pc,%a0)
3373 1.2.4.2 wiz
3374 1.2.4.2 wiz tbl_snan:
3375 1.2.4.2 wiz short fsnan_out_l - tbl_snan # long word integer
3376 1.2.4.2 wiz short fsnan_out_s - tbl_snan # sgl prec shouldn't happen
3377 1.2.4.2 wiz short fsnan_out_x - tbl_snan # ext prec shouldn't happen
3378 1.2.4.2 wiz short tbl_snan - tbl_snan # packed needs no help
3379 1.2.4.2 wiz short fsnan_out_w - tbl_snan # word integer
3380 1.2.4.2 wiz short fsnan_out_d - tbl_snan # dbl prec shouldn't happen
3381 1.2.4.2 wiz short fsnan_out_b - tbl_snan # byte integer
3382 1.2.4.2 wiz short tbl_snan - tbl_snan # packed needs no help
3383 1.2.4.2 wiz
3384 1.2.4.2 wiz fsnan_out_b:
3385 1.2.4.2 wiz mov.b FP_SRC_HI(%a6),%d0 # load upper byte of SNAN
3386 1.2.4.2 wiz bset &6,%d0 # set SNAN bit
3387 1.2.4.2 wiz cmpi.b %d1,&0x7 # is <ea> mode a data reg?
3388 1.2.4.2 wiz ble.b fsnan_out_b_dn # yes
3389 1.2.4.2 wiz mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
3390 1.2.4.2 wiz bsr.l _dmem_write_byte # write the default result
3391 1.2.4.2 wiz
3392 1.2.4.2 wiz tst.l %d1 # did dstore fail?
3393 1.2.4.2 wiz bne.l facc_out_b # yes
3394 1.2.4.2 wiz
3395 1.2.4.2 wiz bra.w fsnan_exit
3396 1.2.4.2 wiz fsnan_out_b_dn:
3397 1.2.4.2 wiz andi.w &0x0007,%d1
3398 1.2.4.2 wiz bsr.l store_dreg_b # store result to regfile
3399 1.2.4.2 wiz bra.w fsnan_exit
3400 1.2.4.2 wiz
3401 1.2.4.2 wiz fsnan_out_w:
3402 1.2.4.2 wiz mov.w FP_SRC_HI(%a6),%d0 # load upper word of SNAN
3403 1.2.4.2 wiz bset &14,%d0 # set SNAN bit
3404 1.2.4.2 wiz cmpi.b %d1,&0x7 # is <ea> mode a data reg?
3405 1.2.4.2 wiz ble.b fsnan_out_w_dn # yes
3406 1.2.4.2 wiz mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
3407 1.2.4.2 wiz bsr.l _dmem_write_word # write the default result
3408 1.2.4.2 wiz
3409 1.2.4.2 wiz tst.l %d1 # did dstore fail?
3410 1.2.4.2 wiz bne.l facc_out_w # yes
3411 1.2.4.2 wiz
3412 1.2.4.2 wiz bra.w fsnan_exit
3413 1.2.4.2 wiz fsnan_out_w_dn:
3414 1.2.4.2 wiz andi.w &0x0007,%d1
3415 1.2.4.2 wiz bsr.l store_dreg_w # store result to regfile
3416 1.2.4.2 wiz bra.w fsnan_exit
3417 1.2.4.2 wiz
3418 1.2.4.2 wiz fsnan_out_l:
3419 1.2.4.2 wiz mov.l FP_SRC_HI(%a6),%d0 # load upper longword of SNAN
3420 1.2.4.2 wiz bset &30,%d0 # set SNAN bit
3421 1.2.4.2 wiz cmpi.b %d1,&0x7 # is <ea> mode a data reg?
3422 1.2.4.2 wiz ble.b fsnan_out_l_dn # yes
3423 1.2.4.2 wiz mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
3424 1.2.4.2 wiz bsr.l _dmem_write_long # write the default result
3425 1.2.4.2 wiz
3426 1.2.4.2 wiz tst.l %d1 # did dstore fail?
3427 1.2.4.2 wiz bne.l facc_out_l # yes
3428 1.2.4.2 wiz
3429 1.2.4.2 wiz bra.w fsnan_exit
3430 1.2.4.2 wiz fsnan_out_l_dn:
3431 1.2.4.2 wiz andi.w &0x0007,%d1
3432 1.2.4.2 wiz bsr.l store_dreg_l # store result to regfile
3433 1.2.4.2 wiz bra.w fsnan_exit
3434 1.2.4.2 wiz
3435 1.2.4.2 wiz fsnan_out_s:
3436 1.2.4.2 wiz cmpi.b %d1,&0x7 # is <ea> mode a data reg?
3437 1.2.4.2 wiz ble.b fsnan_out_d_dn # yes
3438 1.2.4.2 wiz mov.l FP_SRC_EX(%a6),%d0 # fetch SNAN sign
3439 1.2.4.2 wiz andi.l &0x80000000,%d0 # keep sign
3440 1.2.4.2 wiz ori.l &0x7fc00000,%d0 # insert new exponent,SNAN bit
3441 1.2.4.2 wiz mov.l FP_SRC_HI(%a6),%d1 # load mantissa
3442 1.2.4.2 wiz lsr.l &0x8,%d1 # shift mantissa for sgl
3443 1.2.4.2 wiz or.l %d1,%d0 # create sgl SNAN
3444 1.2.4.2 wiz mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
3445 1.2.4.2 wiz bsr.l _dmem_write_long # write the default result
3446 1.2.4.2 wiz
3447 1.2.4.2 wiz tst.l %d1 # did dstore fail?
3448 1.2.4.2 wiz bne.l facc_out_l # yes
3449 1.2.4.2 wiz
3450 1.2.4.2 wiz bra.w fsnan_exit
3451 1.2.4.2 wiz fsnan_out_d_dn:
3452 1.2.4.2 wiz mov.l FP_SRC_EX(%a6),%d0 # fetch SNAN sign
3453 1.2.4.2 wiz andi.l &0x80000000,%d0 # keep sign
3454 1.2.4.2 wiz ori.l &0x7fc00000,%d0 # insert new exponent,SNAN bit
3455 1.2.4.2 wiz mov.l %d1,-(%sp)
3456 1.2.4.2 wiz mov.l FP_SRC_HI(%a6),%d1 # load mantissa
3457 1.2.4.2 wiz lsr.l &0x8,%d1 # shift mantissa for sgl
3458 1.2.4.2 wiz or.l %d1,%d0 # create sgl SNAN
3459 1.2.4.2 wiz mov.l (%sp)+,%d1
3460 1.2.4.2 wiz andi.w &0x0007,%d1
3461 1.2.4.2 wiz bsr.l store_dreg_l # store result to regfile
3462 1.2.4.2 wiz bra.w fsnan_exit
3463 1.2.4.2 wiz
3464 1.2.4.2 wiz fsnan_out_d:
3465 1.2.4.2 wiz mov.l FP_SRC_EX(%a6),%d0 # fetch SNAN sign
3466 1.2.4.2 wiz andi.l &0x80000000,%d0 # keep sign
3467 1.2.4.2 wiz ori.l &0x7ff80000,%d0 # insert new exponent,SNAN bit
3468 1.2.4.2 wiz mov.l FP_SRC_HI(%a6),%d1 # load hi mantissa
3469 1.2.4.2 wiz mov.l %d0,FP_SCR0_EX(%a6) # store to temp space
3470 1.2.4.2 wiz mov.l &11,%d0 # load shift amt
3471 1.2.4.2 wiz lsr.l %d0,%d1
3472 1.2.4.2 wiz or.l %d1,FP_SCR0_EX(%a6) # create dbl hi
3473 1.2.4.2 wiz mov.l FP_SRC_HI(%a6),%d1 # load hi mantissa
3474 1.2.4.2 wiz andi.l &0x000007ff,%d1
3475 1.2.4.2 wiz ror.l %d0,%d1
3476 1.2.4.2 wiz mov.l %d1,FP_SCR0_HI(%a6) # store to temp space
3477 1.2.4.2 wiz mov.l FP_SRC_LO(%a6),%d1 # load lo mantissa
3478 1.2.4.2 wiz lsr.l %d0,%d1
3479 1.2.4.2 wiz or.l %d1,FP_SCR0_HI(%a6) # create dbl lo
3480 1.2.4.2 wiz lea FP_SCR0(%a6),%a0 # pass: ptr to operand
3481 1.2.4.2 wiz mov.l EXC_EA(%a6),%a1 # pass: dst addr
3482 1.2.4.2 wiz movq.l &0x8,%d0 # pass: size of 8 bytes
3483 1.2.4.2 wiz bsr.l _dmem_write # write the default result
3484 1.2.4.2 wiz
3485 1.2.4.2 wiz tst.l %d1 # did dstore fail?
3486 1.2.4.2 wiz bne.l facc_out_d # yes
3487 1.2.4.2 wiz
3488 1.2.4.2 wiz bra.w fsnan_exit
3489 1.2.4.2 wiz
3490 1.2.4.2 wiz # for extended precision, if the addressing mode is pre-decrement or
3491 1.2.4.2 wiz # post-increment, then the address register did not get updated.
3492 1.2.4.2 wiz # in addition, for pre-decrement, the stacked <ea> is incorrect.
3493 1.2.4.2 wiz fsnan_out_x:
3494 1.2.4.2 wiz clr.b SPCOND_FLG(%a6) # clear special case flag
3495 1.2.4.2 wiz
3496 1.2.4.2 wiz mov.w FP_SRC_EX(%a6),FP_SCR0_EX(%a6)
3497 1.2.4.2 wiz clr.w 2+FP_SCR0(%a6)
3498 1.2.4.2 wiz mov.l FP_SRC_HI(%a6),%d0
3499 1.2.4.2 wiz bset &30,%d0
3500 1.2.4.2 wiz mov.l %d0,FP_SCR0_HI(%a6)
3501 1.2.4.2 wiz mov.l FP_SRC_LO(%a6),FP_SCR0_LO(%a6)
3502 1.2.4.2 wiz
3503 1.2.4.2 wiz btst &0x5,EXC_SR(%a6) # supervisor mode exception?
3504 1.2.4.2 wiz bne.b fsnan_out_x_s # yes
3505 1.2.4.2 wiz
3506 1.2.4.2 wiz mov.l %usp,%a0 # fetch user stack pointer
3507 1.2.4.2 wiz mov.l %a0,EXC_A7(%a6) # save on stack for calc_ea()
3508 1.2.4.2 wiz mov.l (%a6),EXC_A6(%a6)
3509 1.2.4.2 wiz
3510 1.2.4.2 wiz bsr.l _calc_ea_fout # find the correct ea,update An
3511 1.2.4.2 wiz mov.l %a0,%a1
3512 1.2.4.2 wiz mov.l %a0,EXC_EA(%a6) # stack correct <ea>
3513 1.2.4.2 wiz
3514 1.2.4.2 wiz mov.l EXC_A7(%a6),%a0
3515 1.2.4.2 wiz mov.l %a0,%usp # restore user stack pointer
3516 1.2.4.2 wiz mov.l EXC_A6(%a6),(%a6)
3517 1.2.4.2 wiz
3518 1.2.4.2 wiz fsnan_out_x_save:
3519 1.2.4.2 wiz lea FP_SCR0(%a6),%a0 # pass: ptr to operand
3520 1.2.4.2 wiz movq.l &0xc,%d0 # pass: size of extended
3521 1.2.4.2 wiz bsr.l _dmem_write # write the default result
3522 1.2.4.2 wiz
3523 1.2.4.2 wiz tst.l %d1 # did dstore fail?
3524 1.2.4.2 wiz bne.l facc_out_x # yes
3525 1.2.4.2 wiz
3526 1.2.4.2 wiz bra.w fsnan_exit
3527 1.2.4.2 wiz
3528 1.2.4.2 wiz fsnan_out_x_s:
3529 1.2.4.2 wiz mov.l (%a6),EXC_A6(%a6)
3530 1.2.4.2 wiz
3531 1.2.4.2 wiz bsr.l _calc_ea_fout # find the correct ea,update An
3532 1.2.4.2 wiz mov.l %a0,%a1
3533 1.2.4.2 wiz mov.l %a0,EXC_EA(%a6) # stack correct <ea>
3534 1.2.4.2 wiz
3535 1.2.4.2 wiz mov.l EXC_A6(%a6),(%a6)
3536 1.2.4.2 wiz
3537 1.2.4.2 wiz cmpi.b SPCOND_FLG(%a6),&mda7_flg # is <ea> mode -(a7)?
3538 1.2.4.2 wiz bne.b fsnan_out_x_save # no
3539 1.2.4.2 wiz
3540 1.2.4.2 wiz # the operation was "fmove.x SNAN,-(a7)" from supervisor mode.
3541 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
3542 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
3543 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3544 1.2.4.2 wiz
3545 1.2.4.2 wiz frestore FP_SRC(%a6)
3546 1.2.4.2 wiz
3547 1.2.4.2 wiz mov.l EXC_A6(%a6),%a6 # restore frame pointer
3548 1.2.4.2 wiz
3549 1.2.4.2 wiz mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
3550 1.2.4.2 wiz mov.l LOCAL_SIZE+EXC_PC+0x2(%sp),LOCAL_SIZE+EXC_PC+0x2-0xc(%sp)
3551 1.2.4.2 wiz mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
3552 1.2.4.2 wiz
3553 1.2.4.2 wiz mov.l LOCAL_SIZE+FP_SCR0_EX(%sp),LOCAL_SIZE+EXC_SR(%sp)
3554 1.2.4.2 wiz mov.l LOCAL_SIZE+FP_SCR0_HI(%sp),LOCAL_SIZE+EXC_PC+0x2(%sp)
3555 1.2.4.2 wiz mov.l LOCAL_SIZE+FP_SCR0_LO(%sp),LOCAL_SIZE+EXC_EA(%sp)
3556 1.2.4.2 wiz
3557 1.2.4.2 wiz add.l &LOCAL_SIZE-0x8,%sp
3558 1.2.4.2 wiz
3559 1.2.4.2 wiz bra.l _real_snan
3560 1.2.4.2 wiz
3561 1.2.4.2 wiz #########################################################################
3562 1.2.4.2 wiz # XDEF **************************************************************** #
3563 1.2.4.2 wiz # _fpsp_inex(): 060FPSP entry point for FP Inexact exception. #
3564 1.2.4.2 wiz # #
3565 1.2.4.2 wiz # This handler should be the first code executed upon taking the #
3566 1.2.4.2 wiz # FP Inexact exception in an operating system. #
3567 1.2.4.2 wiz # #
3568 1.2.4.2 wiz # XREF **************************************************************** #
3569 1.2.4.2 wiz # _imem_read_long() - read instruction longword #
3570 1.2.4.2 wiz # fix_skewed_ops() - adjust src operand in fsave frame #
3571 1.2.4.2 wiz # set_tag_x() - determine optype of src/dst operands #
3572 1.2.4.2 wiz # store_fpreg() - store opclass 0 or 2 result to FP regfile #
3573 1.2.4.2 wiz # unnorm_fix() - change UNNORM operands to NORM or ZERO #
3574 1.2.4.2 wiz # load_fpn2() - load dst operand from FP regfile #
3575 1.2.4.2 wiz # smovcr() - emulate an "fmovcr" instruction #
3576 1.2.4.2 wiz # fout() - emulate an opclass 3 instruction #
3577 1.2.4.2 wiz # tbl_unsupp - add of table of emulation routines for opclass 0,2 #
3578 1.2.4.2 wiz # _real_inex() - "callout" to operating system inexact handler #
3579 1.2.4.2 wiz # #
3580 1.2.4.2 wiz # INPUT *************************************************************** #
3581 1.2.4.2 wiz # - The system stack contains the FP Inexact exception frame #
3582 1.2.4.2 wiz # - The fsave frame contains the source operand #
3583 1.2.4.2 wiz # #
3584 1.2.4.2 wiz # OUTPUT ************************************************************** #
3585 1.2.4.2 wiz # - The system stack is unchanged #
3586 1.2.4.2 wiz # - The fsave frame contains the adjusted src op for opclass 0,2 #
3587 1.2.4.2 wiz # #
3588 1.2.4.2 wiz # ALGORITHM *********************************************************** #
3589 1.2.4.2 wiz # In a system where the FP Inexact exception is enabled, the goal #
3590 1.2.4.2 wiz # is to get to the handler specified at _real_inex(). But, on the 060, #
3591 1.2.4.2 wiz # for opclass zero and two instruction taking this exception, the #
3592 1.2.4.2 wiz # hardware doesn't store the correct result to the destination FP #
3593 1.2.4.2 wiz # register as did the '040 and '881/2. This handler must emulate the #
3594 1.2.4.2 wiz # instruction in order to get this value and then store it to the #
3595 1.2.4.2 wiz # correct register before calling _real_inex(). #
3596 1.2.4.2 wiz # For opclass 3 instructions, the 060 doesn't store the default #
3597 1.2.4.2 wiz # inexact result out to memory or data register file as it should. #
3598 1.2.4.2 wiz # This code must emulate the move out by calling fout() before finally #
3599 1.2.4.2 wiz # exiting through _real_inex(). #
3600 1.2.4.2 wiz # #
3601 1.2.4.2 wiz #########################################################################
3602 1.2.4.2 wiz
3603 1.2.4.2 wiz global _fpsp_inex
3604 1.2.4.2 wiz _fpsp_inex:
3605 1.2.4.2 wiz
3606 1.2.4.2 wiz link.w %a6,&-LOCAL_SIZE # init stack frame
3607 1.2.4.2 wiz
3608 1.2.4.2 wiz fsave FP_SRC(%a6) # grab the "busy" frame
3609 1.2.4.2 wiz
3610 1.2.4.2 wiz movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3611 1.2.4.2 wiz fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
3612 1.2.4.2 wiz fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
3613 1.2.4.2 wiz
3614 1.2.4.2 wiz # the FPIAR holds the "current PC" of the faulting instruction
3615 1.2.4.2 wiz mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
3616 1.2.4.2 wiz
3617 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
3618 1.2.4.2 wiz addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
3619 1.2.4.2 wiz bsr.l _imem_read_long # fetch the instruction words
3620 1.2.4.2 wiz mov.l %d0,EXC_OPWORD(%a6)
3621 1.2.4.2 wiz
3622 1.2.4.2 wiz ##############################################################################
3623 1.2.4.2 wiz
3624 1.2.4.2 wiz btst &13,%d0 # is instr an fmove out?
3625 1.2.4.2 wiz bne.w finex_out # fmove out
3626 1.2.4.2 wiz
3627 1.2.4.2 wiz
3628 1.2.4.2 wiz # the hardware, for "fabs" and "fneg" w/ a long source format, puts the
3629 1.2.4.2 wiz # longword integer directly into the upper longword of the mantissa along
3630 1.2.4.2 wiz # w/ an exponent value of 0x401e. we convert this to extended precision here.
3631 1.2.4.2 wiz bfextu %d0{&19:&3},%d0 # fetch instr size
3632 1.2.4.2 wiz bne.b finex_cont # instr size is not long
3633 1.2.4.2 wiz cmpi.w FP_SRC_EX(%a6),&0x401e # is exponent 0x401e?
3634 1.2.4.2 wiz bne.b finex_cont # no
3635 1.2.4.2 wiz fmov.l &0x0,%fpcr
3636 1.2.4.2 wiz fmov.l FP_SRC_HI(%a6),%fp0 # load integer src
3637 1.2.4.2 wiz fmov.x %fp0,FP_SRC(%a6) # store integer as extended precision
3638 1.2.4.2 wiz mov.w &0xe001,0x2+FP_SRC(%a6)
3639 1.2.4.2 wiz
3640 1.2.4.2 wiz finex_cont:
3641 1.2.4.2 wiz lea FP_SRC(%a6),%a0 # pass: ptr to src op
3642 1.2.4.2 wiz bsr.l fix_skewed_ops # fix src op
3643 1.2.4.2 wiz
3644 1.2.4.2 wiz # Here, we zero the ccode and exception byte field since we're going to
3645 1.2.4.2 wiz # emulate the whole instruction. Notice, though, that we don't kill the
3646 1.2.4.2 wiz # INEX1 bit. This is because a packed op has long since been converted
3647 1.2.4.2 wiz # to extended before arriving here. Therefore, we need to retain the
3648 1.2.4.2 wiz # INEX1 bit from when the operand was first converted.
3649 1.2.4.2 wiz andi.l &0x00ff01ff,USER_FPSR(%a6) # zero all but accured field
3650 1.2.4.2 wiz
3651 1.2.4.2 wiz fmov.l &0x0,%fpcr # zero current control regs
3652 1.2.4.2 wiz fmov.l &0x0,%fpsr
3653 1.2.4.2 wiz
3654 1.2.4.2 wiz bfextu EXC_EXTWORD(%a6){&0:&6},%d1 # extract upper 6 of cmdreg
3655 1.2.4.2 wiz cmpi.b %d1,&0x17 # is op an fmovecr?
3656 1.2.4.2 wiz beq.w finex_fmovcr # yes
3657 1.2.4.2 wiz
3658 1.2.4.2 wiz lea FP_SRC(%a6),%a0 # pass: ptr to src op
3659 1.2.4.2 wiz bsr.l set_tag_x # tag the operand type
3660 1.2.4.2 wiz mov.b %d0,STAG(%a6) # maybe NORM,DENORM
3661 1.2.4.2 wiz
3662 1.2.4.2 wiz # bits four and five of the fp extension word separate the monadic and dyadic
3663 1.2.4.2 wiz # operations that can pass through fpsp_inex(). remember that fcmp and ftst
3664 1.2.4.2 wiz # will never take this exception, but fsincos will.
3665 1.2.4.2 wiz btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic?
3666 1.2.4.2 wiz beq.b finex_extract # monadic
3667 1.2.4.2 wiz
3668 1.2.4.2 wiz btst &0x4,1+EXC_CMDREG(%a6) # is operation an fsincos?
3669 1.2.4.2 wiz bne.b finex_extract # yes
3670 1.2.4.2 wiz
3671 1.2.4.2 wiz bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
3672 1.2.4.2 wiz bsr.l load_fpn2 # load dst into FP_DST
3673 1.2.4.2 wiz
3674 1.2.4.2 wiz lea FP_DST(%a6),%a0 # pass: ptr to dst op
3675 1.2.4.2 wiz bsr.l set_tag_x # tag the operand type
3676 1.2.4.2 wiz cmpi.b %d0,&UNNORM # is operand an UNNORM?
3677 1.2.4.2 wiz bne.b finex_op2_done # no
3678 1.2.4.2 wiz bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
3679 1.2.4.2 wiz finex_op2_done:
3680 1.2.4.2 wiz mov.b %d0,DTAG(%a6) # save dst optype tag
3681 1.2.4.2 wiz
3682 1.2.4.2 wiz finex_extract:
3683 1.2.4.2 wiz clr.l %d0
3684 1.2.4.2 wiz mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
3685 1.2.4.2 wiz
3686 1.2.4.2 wiz mov.b 1+EXC_CMDREG(%a6),%d1
3687 1.2.4.2 wiz andi.w &0x007f,%d1 # extract extension
3688 1.2.4.2 wiz
3689 1.2.4.2 wiz lea FP_SRC(%a6),%a0
3690 1.2.4.2 wiz lea FP_DST(%a6),%a1
3691 1.2.4.2 wiz
3692 1.2.4.2 wiz mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
3693 1.2.4.2 wiz jsr (tbl_unsupp.l,%pc,%d1.l*1)
3694 1.2.4.2 wiz
3695 1.2.4.2 wiz # the operation has been emulated. the result is in fp0.
3696 1.2.4.2 wiz finex_save:
3697 1.2.4.2 wiz bfextu EXC_CMDREG(%a6){&6:&3},%d0
3698 1.2.4.2 wiz bsr.l store_fpreg
3699 1.2.4.2 wiz
3700 1.2.4.2 wiz finex_exit:
3701 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
3702 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
3703 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3704 1.2.4.2 wiz
3705 1.2.4.2 wiz frestore FP_SRC(%a6)
3706 1.2.4.2 wiz
3707 1.2.4.2 wiz unlk %a6
3708 1.2.4.2 wiz bra.l _real_inex
3709 1.2.4.2 wiz
3710 1.2.4.2 wiz finex_fmovcr:
3711 1.2.4.2 wiz clr.l %d0
3712 1.2.4.2 wiz mov.b FPCR_MODE(%a6),%d0 # pass rnd prec,mode
3713 1.2.4.2 wiz mov.b 1+EXC_CMDREG(%a6),%d1
3714 1.2.4.2 wiz andi.l &0x0000007f,%d1 # pass rom offset
3715 1.2.4.2 wiz bsr.l smovcr
3716 1.2.4.2 wiz bra.b finex_save
3717 1.2.4.2 wiz
3718 1.2.4.2 wiz ########################################################################
3719 1.2.4.2 wiz
3720 1.2.4.2 wiz #
3721 1.2.4.2 wiz # the hardware does not save the default result to memory on enabled
3722 1.2.4.2 wiz # inexact exceptions. we do this here before passing control to
3723 1.2.4.2 wiz # the user inexact handler.
3724 1.2.4.2 wiz #
3725 1.2.4.2 wiz # byte, word, and long destination format operations can pass
3726 1.2.4.2 wiz # through here. so can double and single precision.
3727 1.2.4.2 wiz # although packed opclass three operations can take inexact
3728 1.2.4.2 wiz # exceptions, they won't pass through here since they are caught
3729 1.2.4.2 wiz # first by the unsupported data format exception handler. that handler
3730 1.2.4.2 wiz # sends them directly to _real_inex() if necessary.
3731 1.2.4.2 wiz #
3732 1.2.4.2 wiz finex_out:
3733 1.2.4.2 wiz
3734 1.2.4.2 wiz mov.b &NORM,STAG(%a6) # src is a NORM
3735 1.2.4.2 wiz
3736 1.2.4.2 wiz clr.l %d0
3737 1.2.4.2 wiz mov.b FPCR_MODE(%a6),%d0 # pass rnd prec,mode
3738 1.2.4.2 wiz
3739 1.2.4.2 wiz andi.l &0xffff00ff,USER_FPSR(%a6) # zero exception field
3740 1.2.4.2 wiz
3741 1.2.4.2 wiz lea FP_SRC(%a6),%a0 # pass ptr to src operand
3742 1.2.4.2 wiz
3743 1.2.4.2 wiz bsr.l fout # store the default result
3744 1.2.4.2 wiz
3745 1.2.4.2 wiz bra.b finex_exit
3746 1.2.4.2 wiz
3747 1.2.4.2 wiz #########################################################################
3748 1.2.4.2 wiz # XDEF **************************************************************** #
3749 1.2.4.2 wiz # _fpsp_dz(): 060FPSP entry point for FP DZ exception. #
3750 1.2.4.2 wiz # #
3751 1.2.4.2 wiz # This handler should be the first code executed upon taking #
3752 1.2.4.2 wiz # the FP DZ exception in an operating system. #
3753 1.2.4.2 wiz # #
3754 1.2.4.2 wiz # XREF **************************************************************** #
3755 1.2.4.2 wiz # _imem_read_long() - read instruction longword from memory #
3756 1.2.4.2 wiz # fix_skewed_ops() - adjust fsave operand #
3757 1.2.4.2 wiz # _real_dz() - "callout" exit point from FP DZ handler #
3758 1.2.4.2 wiz # #
3759 1.2.4.2 wiz # INPUT *************************************************************** #
3760 1.2.4.2 wiz # - The system stack contains the FP DZ exception stack. #
3761 1.2.4.2 wiz # - The fsave frame contains the source operand. #
3762 1.2.4.2 wiz # #
3763 1.2.4.2 wiz # OUTPUT ************************************************************** #
3764 1.2.4.2 wiz # - The system stack contains the FP DZ exception stack. #
3765 1.2.4.2 wiz # - The fsave frame contains the adjusted source operand. #
3766 1.2.4.2 wiz # #
3767 1.2.4.2 wiz # ALGORITHM *********************************************************** #
3768 1.2.4.2 wiz # In a system where the DZ exception is enabled, the goal is to #
3769 1.2.4.2 wiz # get to the handler specified at _real_dz(). But, on the 060, when the #
3770 1.2.4.2 wiz # exception is taken, the input operand in the fsave state frame may #
3771 1.2.4.2 wiz # be incorrect for some cases and need to be adjusted. So, this package #
3772 1.2.4.2 wiz # adjusts the operand using fix_skewed_ops() and then branches to #
3773 1.2.4.2 wiz # _real_dz(). #
3774 1.2.4.2 wiz # #
3775 1.2.4.2 wiz #########################################################################
3776 1.2.4.2 wiz
3777 1.2.4.2 wiz global _fpsp_dz
3778 1.2.4.2 wiz _fpsp_dz:
3779 1.2.4.2 wiz
3780 1.2.4.2 wiz link.w %a6,&-LOCAL_SIZE # init stack frame
3781 1.2.4.2 wiz
3782 1.2.4.2 wiz fsave FP_SRC(%a6) # grab the "busy" frame
3783 1.2.4.2 wiz
3784 1.2.4.2 wiz movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3785 1.2.4.2 wiz fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
3786 1.2.4.2 wiz fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
3787 1.2.4.2 wiz
3788 1.2.4.2 wiz # the FPIAR holds the "current PC" of the faulting instruction
3789 1.2.4.2 wiz mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
3790 1.2.4.2 wiz
3791 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
3792 1.2.4.2 wiz addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
3793 1.2.4.2 wiz bsr.l _imem_read_long # fetch the instruction words
3794 1.2.4.2 wiz mov.l %d0,EXC_OPWORD(%a6)
3795 1.2.4.2 wiz
3796 1.2.4.2 wiz ##############################################################################
3797 1.2.4.2 wiz
3798 1.2.4.2 wiz
3799 1.2.4.2 wiz # here, we simply see if the operand in the fsave frame needs to be "unskewed".
3800 1.2.4.2 wiz # this would be the case for opclass two operations with a source zero
3801 1.2.4.2 wiz # in the sgl or dbl format.
3802 1.2.4.2 wiz lea FP_SRC(%a6),%a0 # pass: ptr to src op
3803 1.2.4.2 wiz bsr.l fix_skewed_ops # fix src op
3804 1.2.4.2 wiz
3805 1.2.4.2 wiz fdz_exit:
3806 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
3807 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
3808 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3809 1.2.4.2 wiz
3810 1.2.4.2 wiz frestore FP_SRC(%a6)
3811 1.2.4.2 wiz
3812 1.2.4.2 wiz unlk %a6
3813 1.2.4.2 wiz bra.l _real_dz
3814 1.2.4.2 wiz
3815 1.2.4.2 wiz #########################################################################
3816 1.2.4.2 wiz # XDEF **************************************************************** #
3817 1.2.4.2 wiz # _fpsp_fline(): 060FPSP entry point for "Line F emulator" #
3818 1.2.4.2 wiz # exception when the "reduced" version of the #
3819 1.2.4.2 wiz # FPSP is implemented that does not emulate #
3820 1.2.4.2 wiz # FP unimplemented instructions. #
3821 1.2.4.2 wiz # #
3822 1.2.4.2 wiz # This handler should be the first code executed upon taking a #
3823 1.2.4.2 wiz # "Line F Emulator" exception in an operating system integrating #
3824 1.2.4.2 wiz # the reduced version of 060FPSP. #
3825 1.2.4.2 wiz # #
3826 1.2.4.2 wiz # XREF **************************************************************** #
3827 1.2.4.2 wiz # _real_fpu_disabled() - Handle "FPU disabled" exceptions #
3828 1.2.4.2 wiz # _real_fline() - Handle all other cases (treated equally) #
3829 1.2.4.2 wiz # #
3830 1.2.4.2 wiz # INPUT *************************************************************** #
3831 1.2.4.2 wiz # - The system stack contains a "Line F Emulator" exception #
3832 1.2.4.2 wiz # stack frame. #
3833 1.2.4.2 wiz # #
3834 1.2.4.2 wiz # OUTPUT ************************************************************** #
3835 1.2.4.2 wiz # - The system stack is unchanged. #
3836 1.2.4.2 wiz # #
3837 1.2.4.2 wiz # ALGORITHM *********************************************************** #
3838 1.2.4.2 wiz # When a "Line F Emulator" exception occurs in a system where #
3839 1.2.4.2 wiz # "FPU Unimplemented" instructions will not be emulated, the exception #
3840 1.2.4.2 wiz # can occur because then FPU is disabled or the instruction is to be #
3841 1.2.4.2 wiz # classifed as "Line F". This module determines which case exists and #
3842 1.2.4.2 wiz # calls the appropriate "callout". #
3843 1.2.4.2 wiz # #
3844 1.2.4.2 wiz #########################################################################
3845 1.2.4.2 wiz
3846 1.2.4.2 wiz global _fpsp_fline
3847 1.2.4.2 wiz _fpsp_fline:
3848 1.2.4.2 wiz
3849 1.2.4.2 wiz # check to see if the FPU is disabled. if so, jump to the OS entry
3850 1.2.4.2 wiz # point for that condition.
3851 1.2.4.2 wiz cmpi.w 0x6(%sp),&0x402c
3852 1.2.4.2 wiz beq.l _real_fpu_disabled
3853 1.2.4.2 wiz
3854 1.2.4.2 wiz bra.l _real_fline
3855 1.2.4.2 wiz
3856 1.2.4.2 wiz #########################################################################
3857 1.2.4.2 wiz # XDEF **************************************************************** #
3858 1.2.4.2 wiz # _dcalc_ea(): calc correct <ea> from <ea> stacked on exception #
3859 1.2.4.2 wiz # #
3860 1.2.4.2 wiz # XREF **************************************************************** #
3861 1.2.4.2 wiz # inc_areg() - increment an address register #
3862 1.2.4.2 wiz # dec_areg() - decrement an address register #
3863 1.2.4.2 wiz # #
3864 1.2.4.2 wiz # INPUT *************************************************************** #
3865 1.2.4.2 wiz # d0 = number of bytes to adjust <ea> by #
3866 1.2.4.2 wiz # #
3867 1.2.4.2 wiz # OUTPUT ************************************************************** #
3868 1.2.4.2 wiz # None #
3869 1.2.4.2 wiz # #
3870 1.2.4.2 wiz # ALGORITHM *********************************************************** #
3871 1.2.4.2 wiz # "Dummy" CALCulate Effective Address: #
3872 1.2.4.2 wiz # The stacked <ea> for FP unimplemented instructions and opclass #
3873 1.2.4.2 wiz # two packed instructions is correct with the exception of... #
3874 1.2.4.2 wiz # #
3875 1.2.4.2 wiz # 1) -(An) : The register is not updated regardless of size. #
3876 1.2.4.2 wiz # Also, for extended precision and packed, the #
3877 1.2.4.2 wiz # stacked <ea> value is 8 bytes too big #
3878 1.2.4.2 wiz # 2) (An)+ : The register is not updated. #
3879 1.2.4.2 wiz # 3) #<data> : The upper longword of the immediate operand is #
3880 1.2.4.2 wiz # stacked b,w,l and s sizes are completely stacked. #
3881 1.2.4.2 wiz # d,x, and p are not. #
3882 1.2.4.2 wiz # #
3883 1.2.4.2 wiz #########################################################################
3884 1.2.4.2 wiz
3885 1.2.4.2 wiz global _dcalc_ea
3886 1.2.4.2 wiz _dcalc_ea:
3887 1.2.4.2 wiz mov.l %d0, %a0 # move # bytes to %a0
3888 1.2.4.2 wiz
3889 1.2.4.2 wiz mov.b 1+EXC_OPWORD(%a6), %d0 # fetch opcode word
3890 1.2.4.2 wiz mov.l %d0, %d1 # make a copy
3891 1.2.4.2 wiz
3892 1.2.4.2 wiz andi.w &0x38, %d0 # extract mode field
3893 1.2.4.2 wiz andi.l &0x7, %d1 # extract reg field
3894 1.2.4.2 wiz
3895 1.2.4.2 wiz cmpi.b %d0,&0x18 # is mode (An)+ ?
3896 1.2.4.2 wiz beq.b dcea_pi # yes
3897 1.2.4.2 wiz
3898 1.2.4.2 wiz cmpi.b %d0,&0x20 # is mode -(An) ?
3899 1.2.4.2 wiz beq.b dcea_pd # yes
3900 1.2.4.2 wiz
3901 1.2.4.2 wiz or.w %d1,%d0 # concat mode,reg
3902 1.2.4.2 wiz cmpi.b %d0,&0x3c # is mode #<data>?
3903 1.2.4.2 wiz
3904 1.2.4.2 wiz beq.b dcea_imm # yes
3905 1.2.4.2 wiz
3906 1.2.4.2 wiz mov.l EXC_EA(%a6),%a0 # return <ea>
3907 1.2.4.2 wiz rts
3908 1.2.4.2 wiz
3909 1.2.4.2 wiz # need to set immediate data flag here since we'll need to do
3910 1.2.4.2 wiz # an imem_read to fetch this later.
3911 1.2.4.2 wiz dcea_imm:
3912 1.2.4.2 wiz mov.b &immed_flg,SPCOND_FLG(%a6)
3913 1.2.4.2 wiz lea ([USER_FPIAR,%a6],0x4),%a0 # no; return <ea>
3914 1.2.4.2 wiz rts
3915 1.2.4.2 wiz
3916 1.2.4.2 wiz # here, the <ea> is stacked correctly. however, we must update the
3917 1.2.4.2 wiz # address register...
3918 1.2.4.2 wiz dcea_pi:
3919 1.2.4.2 wiz mov.l %a0,%d0 # pass amt to inc by
3920 1.2.4.2 wiz bsr.l inc_areg # inc addr register
3921 1.2.4.2 wiz
3922 1.2.4.2 wiz mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
3923 1.2.4.2 wiz rts
3924 1.2.4.2 wiz
3925 1.2.4.2 wiz # the <ea> is stacked correctly for all but extended and packed which
3926 1.2.4.2 wiz # the <ea>s are 8 bytes too large.
3927 1.2.4.2 wiz # it would make no sense to have a pre-decrement to a7 in supervisor
3928 1.2.4.2 wiz # mode so we don't even worry about this tricky case here : )
3929 1.2.4.2 wiz dcea_pd:
3930 1.2.4.2 wiz mov.l %a0,%d0 # pass amt to dec by
3931 1.2.4.2 wiz bsr.l dec_areg # dec addr register
3932 1.2.4.2 wiz
3933 1.2.4.2 wiz mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
3934 1.2.4.2 wiz
3935 1.2.4.2 wiz cmpi.b %d0,&0xc # is opsize ext or packed?
3936 1.2.4.2 wiz beq.b dcea_pd2 # yes
3937 1.2.4.2 wiz rts
3938 1.2.4.2 wiz dcea_pd2:
3939 1.2.4.2 wiz sub.l &0x8,%a0 # correct <ea>
3940 1.2.4.2 wiz mov.l %a0,EXC_EA(%a6) # put correct <ea> on stack
3941 1.2.4.2 wiz rts
3942 1.2.4.2 wiz
3943 1.2.4.2 wiz #########################################################################
3944 1.2.4.2 wiz # XDEF **************************************************************** #
3945 1.2.4.2 wiz # _calc_ea_fout(): calculate correct stacked <ea> for extended #
3946 1.2.4.2 wiz # and packed data opclass 3 operations. #
3947 1.2.4.2 wiz # #
3948 1.2.4.2 wiz # XREF **************************************************************** #
3949 1.2.4.2 wiz # None #
3950 1.2.4.2 wiz # #
3951 1.2.4.2 wiz # INPUT *************************************************************** #
3952 1.2.4.2 wiz # None #
3953 1.2.4.2 wiz # #
3954 1.2.4.2 wiz # OUTPUT ************************************************************** #
3955 1.2.4.2 wiz # a0 = return correct effective address #
3956 1.2.4.2 wiz # #
3957 1.2.4.2 wiz # ALGORITHM *********************************************************** #
3958 1.2.4.2 wiz # For opclass 3 extended and packed data operations, the <ea> #
3959 1.2.4.2 wiz # stacked for the exception is incorrect for -(an) and (an)+ addressing #
3960 1.2.4.2 wiz # modes. Also, while we're at it, the index register itself must get #
3961 1.2.4.2 wiz # updated. #
3962 1.2.4.2 wiz # So, for -(an), we must subtract 8 off of the stacked <ea> value #
3963 1.2.4.2 wiz # and return that value as the correct <ea> and store that value in An. #
3964 1.2.4.2 wiz # For (an)+, the stacked <ea> is correct but we must adjust An by +12. #
3965 1.2.4.2 wiz # #
3966 1.2.4.2 wiz #########################################################################
3967 1.2.4.2 wiz
3968 1.2.4.2 wiz # This calc_ea is currently used to retrieve the correct <ea>
3969 1.2.4.2 wiz # for fmove outs of type extended and packed.
3970 1.2.4.2 wiz global _calc_ea_fout
3971 1.2.4.2 wiz _calc_ea_fout:
3972 1.2.4.2 wiz mov.b 1+EXC_OPWORD(%a6),%d0 # fetch opcode word
3973 1.2.4.2 wiz mov.l %d0,%d1 # make a copy
3974 1.2.4.2 wiz
3975 1.2.4.2 wiz andi.w &0x38,%d0 # extract mode field
3976 1.2.4.2 wiz andi.l &0x7,%d1 # extract reg field
3977 1.2.4.2 wiz
3978 1.2.4.2 wiz cmpi.b %d0,&0x18 # is mode (An)+ ?
3979 1.2.4.2 wiz beq.b ceaf_pi # yes
3980 1.2.4.2 wiz
3981 1.2.4.2 wiz cmpi.b %d0,&0x20 # is mode -(An) ?
3982 1.2.4.2 wiz beq.w ceaf_pd # yes
3983 1.2.4.2 wiz
3984 1.2.4.2 wiz mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
3985 1.2.4.2 wiz rts
3986 1.2.4.2 wiz
3987 1.2.4.2 wiz # (An)+ : extended and packed fmove out
3988 1.2.4.2 wiz # : stacked <ea> is correct
3989 1.2.4.2 wiz # : "An" not updated
3990 1.2.4.2 wiz ceaf_pi:
3991 1.2.4.2 wiz mov.w (tbl_ceaf_pi.b,%pc,%d1.w*2),%d1
3992 1.2.4.2 wiz mov.l EXC_EA(%a6),%a0
3993 1.2.4.2 wiz jmp (tbl_ceaf_pi.b,%pc,%d1.w*1)
3994 1.2.4.2 wiz
3995 1.2.4.2 wiz swbeg &0x8
3996 1.2.4.2 wiz tbl_ceaf_pi:
3997 1.2.4.2 wiz short ceaf_pi0 - tbl_ceaf_pi
3998 1.2.4.2 wiz short ceaf_pi1 - tbl_ceaf_pi
3999 1.2.4.2 wiz short ceaf_pi2 - tbl_ceaf_pi
4000 1.2.4.2 wiz short ceaf_pi3 - tbl_ceaf_pi
4001 1.2.4.2 wiz short ceaf_pi4 - tbl_ceaf_pi
4002 1.2.4.2 wiz short ceaf_pi5 - tbl_ceaf_pi
4003 1.2.4.2 wiz short ceaf_pi6 - tbl_ceaf_pi
4004 1.2.4.2 wiz short ceaf_pi7 - tbl_ceaf_pi
4005 1.2.4.2 wiz
4006 1.2.4.2 wiz ceaf_pi0:
4007 1.2.4.2 wiz addi.l &0xc,EXC_DREGS+0x8(%a6)
4008 1.2.4.2 wiz rts
4009 1.2.4.2 wiz ceaf_pi1:
4010 1.2.4.2 wiz addi.l &0xc,EXC_DREGS+0xc(%a6)
4011 1.2.4.2 wiz rts
4012 1.2.4.2 wiz ceaf_pi2:
4013 1.2.4.2 wiz add.l &0xc,%a2
4014 1.2.4.2 wiz rts
4015 1.2.4.2 wiz ceaf_pi3:
4016 1.2.4.2 wiz add.l &0xc,%a3
4017 1.2.4.2 wiz rts
4018 1.2.4.2 wiz ceaf_pi4:
4019 1.2.4.2 wiz add.l &0xc,%a4
4020 1.2.4.2 wiz rts
4021 1.2.4.2 wiz ceaf_pi5:
4022 1.2.4.2 wiz add.l &0xc,%a5
4023 1.2.4.2 wiz rts
4024 1.2.4.2 wiz ceaf_pi6:
4025 1.2.4.2 wiz addi.l &0xc,EXC_A6(%a6)
4026 1.2.4.2 wiz rts
4027 1.2.4.2 wiz ceaf_pi7:
4028 1.2.4.2 wiz mov.b &mia7_flg,SPCOND_FLG(%a6)
4029 1.2.4.2 wiz addi.l &0xc,EXC_A7(%a6)
4030 1.2.4.2 wiz rts
4031 1.2.4.2 wiz
4032 1.2.4.2 wiz # -(An) : extended and packed fmove out
4033 1.2.4.2 wiz # : stacked <ea> = actual <ea> + 8
4034 1.2.4.2 wiz # : "An" not updated
4035 1.2.4.2 wiz ceaf_pd:
4036 1.2.4.2 wiz mov.w (tbl_ceaf_pd.b,%pc,%d1.w*2),%d1
4037 1.2.4.2 wiz mov.l EXC_EA(%a6),%a0
4038 1.2.4.2 wiz sub.l &0x8,%a0
4039 1.2.4.2 wiz sub.l &0x8,EXC_EA(%a6)
4040 1.2.4.2 wiz jmp (tbl_ceaf_pd.b,%pc,%d1.w*1)
4041 1.2.4.2 wiz
4042 1.2.4.2 wiz swbeg &0x8
4043 1.2.4.2 wiz tbl_ceaf_pd:
4044 1.2.4.2 wiz short ceaf_pd0 - tbl_ceaf_pd
4045 1.2.4.2 wiz short ceaf_pd1 - tbl_ceaf_pd
4046 1.2.4.2 wiz short ceaf_pd2 - tbl_ceaf_pd
4047 1.2.4.2 wiz short ceaf_pd3 - tbl_ceaf_pd
4048 1.2.4.2 wiz short ceaf_pd4 - tbl_ceaf_pd
4049 1.2.4.2 wiz short ceaf_pd5 - tbl_ceaf_pd
4050 1.2.4.2 wiz short ceaf_pd6 - tbl_ceaf_pd
4051 1.2.4.2 wiz short ceaf_pd7 - tbl_ceaf_pd
4052 1.2.4.2 wiz
4053 1.2.4.2 wiz ceaf_pd0:
4054 1.2.4.2 wiz mov.l %a0,EXC_DREGS+0x8(%a6)
4055 1.2.4.2 wiz rts
4056 1.2.4.2 wiz ceaf_pd1:
4057 1.2.4.2 wiz mov.l %a0,EXC_DREGS+0xc(%a6)
4058 1.2.4.2 wiz rts
4059 1.2.4.2 wiz ceaf_pd2:
4060 1.2.4.2 wiz mov.l %a0,%a2
4061 1.2.4.2 wiz rts
4062 1.2.4.2 wiz ceaf_pd3:
4063 1.2.4.2 wiz mov.l %a0,%a3
4064 1.2.4.2 wiz rts
4065 1.2.4.2 wiz ceaf_pd4:
4066 1.2.4.2 wiz mov.l %a0,%a4
4067 1.2.4.2 wiz rts
4068 1.2.4.2 wiz ceaf_pd5:
4069 1.2.4.2 wiz mov.l %a0,%a5
4070 1.2.4.2 wiz rts
4071 1.2.4.2 wiz ceaf_pd6:
4072 1.2.4.2 wiz mov.l %a0,EXC_A6(%a6)
4073 1.2.4.2 wiz rts
4074 1.2.4.2 wiz ceaf_pd7:
4075 1.2.4.2 wiz mov.l %a0,EXC_A7(%a6)
4076 1.2.4.2 wiz mov.b &mda7_flg,SPCOND_FLG(%a6)
4077 1.2.4.2 wiz rts
4078 1.2.4.2 wiz
4079 1.2.4.2 wiz #
4080 1.2.4.2 wiz # This table holds the offsets of the emulation routines for each individual
4081 1.2.4.2 wiz # math operation relative to the address of this table. Included are
4082 1.2.4.2 wiz # routines like fadd/fmul/fabs. The transcendentals ARE NOT. This is because
4083 1.2.4.2 wiz # this table is for the version if the 060FPSP without transcendentals.
4084 1.2.4.2 wiz # The location within the table is determined by the extension bits of the
4085 1.2.4.2 wiz # operation longword.
4086 1.2.4.2 wiz #
4087 1.2.4.2 wiz
4088 1.2.4.2 wiz swbeg &109
4089 1.2.4.2 wiz tbl_unsupp:
4090 1.2.4.2 wiz long fin - tbl_unsupp # 00: fmove
4091 1.2.4.2 wiz long fint - tbl_unsupp # 01: fint
4092 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 02: fsinh
4093 1.2.4.2 wiz long fintrz - tbl_unsupp # 03: fintrz
4094 1.2.4.2 wiz long fsqrt - tbl_unsupp # 04: fsqrt
4095 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4096 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 06: flognp1
4097 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4098 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 08: fetoxm1
4099 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 09: ftanh
4100 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 0a: fatan
4101 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4102 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 0c: fasin
4103 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 0d: fatanh
4104 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 0e: fsin
4105 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 0f: ftan
4106 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 10: fetox
4107 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 11: ftwotox
4108 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 12: ftentox
4109 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4110 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 14: flogn
4111 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 15: flog10
4112 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 16: flog2
4113 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4114 1.2.4.2 wiz long fabs - tbl_unsupp # 18: fabs
4115 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 19: fcosh
4116 1.2.4.2 wiz long fneg - tbl_unsupp # 1a: fneg
4117 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4118 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 1c: facos
4119 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 1d: fcos
4120 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 1e: fgetexp
4121 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 1f: fgetman
4122 1.2.4.2 wiz long fdiv - tbl_unsupp # 20: fdiv
4123 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 21: fmod
4124 1.2.4.2 wiz long fadd - tbl_unsupp # 22: fadd
4125 1.2.4.2 wiz long fmul - tbl_unsupp # 23: fmul
4126 1.2.4.2 wiz long fsgldiv - tbl_unsupp # 24: fsgldiv
4127 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 25: frem
4128 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 26: fscale
4129 1.2.4.2 wiz long fsglmul - tbl_unsupp # 27: fsglmul
4130 1.2.4.2 wiz long fsub - tbl_unsupp # 28: fsub
4131 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4132 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4133 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4134 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4135 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4136 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4137 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4138 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 30: fsincos
4139 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 31: fsincos
4140 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 32: fsincos
4141 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 33: fsincos
4142 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 34: fsincos
4143 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 35: fsincos
4144 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 36: fsincos
4145 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp # 37: fsincos
4146 1.2.4.2 wiz long fcmp - tbl_unsupp # 38: fcmp
4147 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4148 1.2.4.2 wiz long ftst - tbl_unsupp # 3a: ftst
4149 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4150 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4151 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4152 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4153 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4154 1.2.4.2 wiz long fsin - tbl_unsupp # 40: fsmove
4155 1.2.4.2 wiz long fssqrt - tbl_unsupp # 41: fssqrt
4156 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4157 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4158 1.2.4.2 wiz long fdin - tbl_unsupp # 44: fdmove
4159 1.2.4.2 wiz long fdsqrt - tbl_unsupp # 45: fdsqrt
4160 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4161 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4162 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4163 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4164 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4165 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4166 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4167 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4168 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4169 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4170 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4171 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4172 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4173 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4174 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4175 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4176 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4177 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4178 1.2.4.2 wiz long fsabs - tbl_unsupp # 58: fsabs
4179 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4180 1.2.4.2 wiz long fsneg - tbl_unsupp # 5a: fsneg
4181 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4182 1.2.4.2 wiz long fdabs - tbl_unsupp # 5c: fdabs
4183 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4184 1.2.4.2 wiz long fdneg - tbl_unsupp # 5e: fdneg
4185 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4186 1.2.4.2 wiz long fsdiv - tbl_unsupp # 60: fsdiv
4187 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4188 1.2.4.2 wiz long fsadd - tbl_unsupp # 62: fsadd
4189 1.2.4.2 wiz long fsmul - tbl_unsupp # 63: fsmul
4190 1.2.4.2 wiz long fddiv - tbl_unsupp # 64: fddiv
4191 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4192 1.2.4.2 wiz long fdadd - tbl_unsupp # 66: fdadd
4193 1.2.4.2 wiz long fdmul - tbl_unsupp # 67: fdmul
4194 1.2.4.2 wiz long fssub - tbl_unsupp # 68: fssub
4195 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4196 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4197 1.2.4.2 wiz long tbl_unsupp - tbl_unsupp
4198 1.2.4.2 wiz long fdsub - tbl_unsupp # 6c: fdsub
4199 1.2.4.2 wiz
4200 1.2.4.2 wiz #################################################
4201 1.2.4.2 wiz # Add this here so non-fp modules can compile.
4202 1.2.4.2 wiz # (smovcr is called from fpsp_inex.)
4203 1.2.4.2 wiz global smovcr
4204 1.2.4.2 wiz smovcr:
4205 1.2.4.2 wiz bra.b smovcr
4206 1.2.4.2 wiz
4207 1.2.4.2 wiz #########################################################################
4208 1.2.4.2 wiz # XDEF **************************************************************** #
4209 1.2.4.2 wiz # fmovm_dynamic(): emulate "fmovm" dynamic instruction #
4210 1.2.4.2 wiz # #
4211 1.2.4.2 wiz # XREF **************************************************************** #
4212 1.2.4.2 wiz # fetch_dreg() - fetch data register #
4213 1.2.4.2 wiz # {i,d,}mem_read() - fetch data from memory #
4214 1.2.4.2 wiz # _mem_write() - write data to memory #
4215 1.2.4.2 wiz # iea_iacc() - instruction memory access error occurred #
4216 1.2.4.2 wiz # iea_dacc() - data memory access error occurred #
4217 1.2.4.2 wiz # restore() - restore An index regs if access error occurred #
4218 1.2.4.2 wiz # #
4219 1.2.4.2 wiz # INPUT *************************************************************** #
4220 1.2.4.2 wiz # None #
4221 1.2.4.2 wiz # #
4222 1.2.4.2 wiz # OUTPUT ************************************************************** #
4223 1.2.4.2 wiz # If instr is "fmovm Dn,-(A7)" from supervisor mode, #
4224 1.2.4.2 wiz # d0 = size of dump #
4225 1.2.4.2 wiz # d1 = Dn #
4226 1.2.4.2 wiz # Else if instruction access error, #
4227 1.2.4.2 wiz # d0 = FSLW #
4228 1.2.4.2 wiz # Else if data access error, #
4229 1.2.4.2 wiz # d0 = FSLW #
4230 1.2.4.2 wiz # a0 = address of fault #
4231 1.2.4.2 wiz # Else #
4232 1.2.4.2 wiz # none. #
4233 1.2.4.2 wiz # #
4234 1.2.4.2 wiz # ALGORITHM *********************************************************** #
4235 1.2.4.2 wiz # The effective address must be calculated since this is entered #
4236 1.2.4.2 wiz # from an "Unimplemented Effective Address" exception handler. So, we #
4237 1.2.4.2 wiz # have our own fcalc_ea() routine here. If an access error is flagged #
4238 1.2.4.2 wiz # by a _{i,d,}mem_read() call, we must exit through the special #
4239 1.2.4.2 wiz # handler. #
4240 1.2.4.2 wiz # The data register is determined and its value loaded to get the #
4241 1.2.4.2 wiz # string of FP registers affected. This value is used as an index into #
4242 1.2.4.2 wiz # a lookup table such that we can determine the number of bytes #
4243 1.2.4.2 wiz # involved. #
4244 1.2.4.2 wiz # If the instruction is "fmovm.x <ea>,Dn", a _mem_read() is used #
4245 1.2.4.2 wiz # to read in all FP values. Again, _mem_read() may fail and require a #
4246 1.2.4.2 wiz # special exit. #
4247 1.2.4.2 wiz # If the instruction is "fmovm.x DN,<ea>", a _mem_write() is used #
4248 1.2.4.2 wiz # to write all FP values. _mem_write() may also fail. #
4249 1.2.4.2 wiz # If the instruction is "fmovm.x DN,-(a7)" from supervisor mode, #
4250 1.2.4.2 wiz # then we return the size of the dump and the string to the caller #
4251 1.2.4.2 wiz # so that the move can occur outside of this routine. This special #
4252 1.2.4.2 wiz # case is required so that moves to the system stack are handled #
4253 1.2.4.2 wiz # correctly. #
4254 1.2.4.2 wiz # #
4255 1.2.4.2 wiz # DYNAMIC: #
4256 1.2.4.2 wiz # fmovm.x dn, <ea> #
4257 1.2.4.2 wiz # fmovm.x <ea>, dn #
4258 1.2.4.2 wiz # #
4259 1.2.4.2 wiz # <WORD 1> <WORD2> #
4260 1.2.4.2 wiz # 1111 0010 00 |<ea>| 11@& 1000 0$$$ 0000 #
4261 1.2.4.2 wiz # #
4262 1.2.4.2 wiz # & = (0): predecrement addressing mode #
4263 1.2.4.2 wiz # (1): postincrement or control addressing mode #
4264 1.2.4.2 wiz # @ = (0): move listed regs from memory to the FPU #
4265 1.2.4.2 wiz # (1): move listed regs from the FPU to memory #
4266 1.2.4.2 wiz # $$$ : index of data register holding reg select mask #
4267 1.2.4.2 wiz # #
4268 1.2.4.2 wiz # NOTES: #
4269 1.2.4.2 wiz # If the data register holds a zero, then the #
4270 1.2.4.2 wiz # instruction is a nop. #
4271 1.2.4.2 wiz # #
4272 1.2.4.2 wiz #########################################################################
4273 1.2.4.2 wiz
4274 1.2.4.2 wiz global fmovm_dynamic
4275 1.2.4.2 wiz fmovm_dynamic:
4276 1.2.4.2 wiz
4277 1.2.4.2 wiz # extract the data register in which the bit string resides...
4278 1.2.4.2 wiz mov.b 1+EXC_EXTWORD(%a6),%d1 # fetch extword
4279 1.2.4.2 wiz andi.w &0x70,%d1 # extract reg bits
4280 1.2.4.2 wiz lsr.b &0x4,%d1 # shift into lo bits
4281 1.2.4.2 wiz
4282 1.2.4.2 wiz # fetch the bit string into d0...
4283 1.2.4.2 wiz bsr.l fetch_dreg # fetch reg string
4284 1.2.4.2 wiz
4285 1.2.4.2 wiz andi.l &0x000000ff,%d0 # keep only lo byte
4286 1.2.4.2 wiz
4287 1.2.4.2 wiz mov.l %d0,-(%sp) # save strg
4288 1.2.4.2 wiz mov.b (tbl_fmovm_size.w,%pc,%d0),%d0
4289 1.2.4.2 wiz mov.l %d0,-(%sp) # save size
4290 1.2.4.2 wiz bsr.l fmovm_calc_ea # calculate <ea>
4291 1.2.4.2 wiz mov.l (%sp)+,%d0 # restore size
4292 1.2.4.2 wiz mov.l (%sp)+,%d1 # restore strg
4293 1.2.4.2 wiz
4294 1.2.4.2 wiz # if the bit string is a zero, then the operation is a no-op
4295 1.2.4.2 wiz # but, make sure that we've calculated ea and advanced the opword pointer
4296 1.2.4.2 wiz beq.w fmovm_data_done
4297 1.2.4.2 wiz
4298 1.2.4.2 wiz # separate move ins from move outs...
4299 1.2.4.2 wiz btst &0x5,EXC_EXTWORD(%a6) # is it a move in or out?
4300 1.2.4.2 wiz beq.w fmovm_data_in # it's a move out
4301 1.2.4.2 wiz
4302 1.2.4.2 wiz #############
4303 1.2.4.2 wiz # MOVE OUT: #
4304 1.2.4.2 wiz #############
4305 1.2.4.2 wiz fmovm_data_out:
4306 1.2.4.2 wiz btst &0x4,EXC_EXTWORD(%a6) # control or predecrement?
4307 1.2.4.2 wiz bne.w fmovm_out_ctrl # control
4308 1.2.4.2 wiz
4309 1.2.4.2 wiz ############################
4310 1.2.4.2 wiz fmovm_out_predec:
4311 1.2.4.2 wiz # for predecrement mode, the bit string is the opposite of both control
4312 1.2.4.2 wiz # operations and postincrement mode. (bit7 = FP7 ... bit0 = FP0)
4313 1.2.4.2 wiz # here, we convert it to be just like the others...
4314 1.2.4.2 wiz mov.b (tbl_fmovm_convert.w,%pc,%d1.w*1),%d1
4315 1.2.4.2 wiz
4316 1.2.4.2 wiz btst &0x5,EXC_SR(%a6) # user or supervisor mode?
4317 1.2.4.2 wiz beq.b fmovm_out_ctrl # user
4318 1.2.4.2 wiz
4319 1.2.4.2 wiz fmovm_out_predec_s:
4320 1.2.4.2 wiz cmpi.b SPCOND_FLG(%a6),&mda7_flg # is <ea> mode -(a7)?
4321 1.2.4.2 wiz bne.b fmovm_out_ctrl
4322 1.2.4.2 wiz
4323 1.2.4.2 wiz # the operation was unfortunately an: fmovm.x dn,-(sp)
4324 1.2.4.2 wiz # called from supervisor mode.
4325 1.2.4.2 wiz # we're also passing "size" and "strg" back to the calling routine
4326 1.2.4.2 wiz rts
4327 1.2.4.2 wiz
4328 1.2.4.2 wiz ############################
4329 1.2.4.2 wiz fmovm_out_ctrl:
4330 1.2.4.2 wiz mov.l %a0,%a1 # move <ea> to a1
4331 1.2.4.2 wiz
4332 1.2.4.2 wiz sub.l %d0,%sp # subtract size of dump
4333 1.2.4.2 wiz lea (%sp),%a0
4334 1.2.4.2 wiz
4335 1.2.4.2 wiz tst.b %d1 # should FP0 be moved?
4336 1.2.4.2 wiz bpl.b fmovm_out_ctrl_fp1 # no
4337 1.2.4.2 wiz
4338 1.2.4.2 wiz mov.l 0x0+EXC_FP0(%a6),(%a0)+ # yes
4339 1.2.4.2 wiz mov.l 0x4+EXC_FP0(%a6),(%a0)+
4340 1.2.4.2 wiz mov.l 0x8+EXC_FP0(%a6),(%a0)+
4341 1.2.4.2 wiz
4342 1.2.4.2 wiz fmovm_out_ctrl_fp1:
4343 1.2.4.2 wiz lsl.b &0x1,%d1 # should FP1 be moved?
4344 1.2.4.2 wiz bpl.b fmovm_out_ctrl_fp2 # no
4345 1.2.4.2 wiz
4346 1.2.4.2 wiz mov.l 0x0+EXC_FP1(%a6),(%a0)+ # yes
4347 1.2.4.2 wiz mov.l 0x4+EXC_FP1(%a6),(%a0)+
4348 1.2.4.2 wiz mov.l 0x8+EXC_FP1(%a6),(%a0)+
4349 1.2.4.2 wiz
4350 1.2.4.2 wiz fmovm_out_ctrl_fp2:
4351 1.2.4.2 wiz lsl.b &0x1,%d1 # should FP2 be moved?
4352 1.2.4.2 wiz bpl.b fmovm_out_ctrl_fp3 # no
4353 1.2.4.2 wiz
4354 1.2.4.2 wiz fmovm.x &0x20,(%a0) # yes
4355 1.2.4.2 wiz add.l &0xc,%a0
4356 1.2.4.2 wiz
4357 1.2.4.2 wiz fmovm_out_ctrl_fp3:
4358 1.2.4.2 wiz lsl.b &0x1,%d1 # should FP3 be moved?
4359 1.2.4.2 wiz bpl.b fmovm_out_ctrl_fp4 # no
4360 1.2.4.2 wiz
4361 1.2.4.2 wiz fmovm.x &0x10,(%a0) # yes
4362 1.2.4.2 wiz add.l &0xc,%a0
4363 1.2.4.2 wiz
4364 1.2.4.2 wiz fmovm_out_ctrl_fp4:
4365 1.2.4.2 wiz lsl.b &0x1,%d1 # should FP4 be moved?
4366 1.2.4.2 wiz bpl.b fmovm_out_ctrl_fp5 # no
4367 1.2.4.2 wiz
4368 1.2.4.2 wiz fmovm.x &0x08,(%a0) # yes
4369 1.2.4.2 wiz add.l &0xc,%a0
4370 1.2.4.2 wiz
4371 1.2.4.2 wiz fmovm_out_ctrl_fp5:
4372 1.2.4.2 wiz lsl.b &0x1,%d1 # should FP5 be moved?
4373 1.2.4.2 wiz bpl.b fmovm_out_ctrl_fp6 # no
4374 1.2.4.2 wiz
4375 1.2.4.2 wiz fmovm.x &0x04,(%a0) # yes
4376 1.2.4.2 wiz add.l &0xc,%a0
4377 1.2.4.2 wiz
4378 1.2.4.2 wiz fmovm_out_ctrl_fp6:
4379 1.2.4.2 wiz lsl.b &0x1,%d1 # should FP6 be moved?
4380 1.2.4.2 wiz bpl.b fmovm_out_ctrl_fp7 # no
4381 1.2.4.2 wiz
4382 1.2.4.2 wiz fmovm.x &0x02,(%a0) # yes
4383 1.2.4.2 wiz add.l &0xc,%a0
4384 1.2.4.2 wiz
4385 1.2.4.2 wiz fmovm_out_ctrl_fp7:
4386 1.2.4.2 wiz lsl.b &0x1,%d1 # should FP7 be moved?
4387 1.2.4.2 wiz bpl.b fmovm_out_ctrl_done # no
4388 1.2.4.2 wiz
4389 1.2.4.2 wiz fmovm.x &0x01,(%a0) # yes
4390 1.2.4.2 wiz add.l &0xc,%a0
4391 1.2.4.2 wiz
4392 1.2.4.2 wiz fmovm_out_ctrl_done:
4393 1.2.4.2 wiz mov.l %a1,L_SCR1(%a6)
4394 1.2.4.2 wiz
4395 1.2.4.2 wiz lea (%sp),%a0 # pass: supervisor src
4396 1.2.4.2 wiz mov.l %d0,-(%sp) # save size
4397 1.2.4.2 wiz bsr.l _dmem_write # copy data to user mem
4398 1.2.4.2 wiz
4399 1.2.4.2 wiz mov.l (%sp)+,%d0
4400 1.2.4.2 wiz add.l %d0,%sp # clear fpreg data from stack
4401 1.2.4.2 wiz
4402 1.2.4.2 wiz tst.l %d1 # did dstore err?
4403 1.2.4.2 wiz bne.w fmovm_out_err # yes
4404 1.2.4.2 wiz
4405 1.2.4.2 wiz rts
4406 1.2.4.2 wiz
4407 1.2.4.2 wiz ############
4408 1.2.4.2 wiz # MOVE IN: #
4409 1.2.4.2 wiz ############
4410 1.2.4.2 wiz fmovm_data_in:
4411 1.2.4.2 wiz mov.l %a0,L_SCR1(%a6)
4412 1.2.4.2 wiz
4413 1.2.4.2 wiz sub.l %d0,%sp # make room for fpregs
4414 1.2.4.2 wiz lea (%sp),%a1
4415 1.2.4.2 wiz
4416 1.2.4.2 wiz mov.l %d1,-(%sp) # save bit string for later
4417 1.2.4.2 wiz mov.l %d0,-(%sp) # save # of bytes
4418 1.2.4.2 wiz
4419 1.2.4.2 wiz bsr.l _dmem_read # copy data from user mem
4420 1.2.4.2 wiz
4421 1.2.4.2 wiz mov.l (%sp)+,%d0 # retrieve # of bytes
4422 1.2.4.2 wiz
4423 1.2.4.2 wiz tst.l %d1 # did dfetch fail?
4424 1.2.4.2 wiz bne.w fmovm_in_err # yes
4425 1.2.4.2 wiz
4426 1.2.4.2 wiz mov.l (%sp)+,%d1 # load bit string
4427 1.2.4.2 wiz
4428 1.2.4.2 wiz lea (%sp),%a0 # addr of stack
4429 1.2.4.2 wiz
4430 1.2.4.2 wiz tst.b %d1 # should FP0 be moved?
4431 1.2.4.2 wiz bpl.b fmovm_data_in_fp1 # no
4432 1.2.4.2 wiz
4433 1.2.4.2 wiz mov.l (%a0)+,0x0+EXC_FP0(%a6) # yes
4434 1.2.4.2 wiz mov.l (%a0)+,0x4+EXC_FP0(%a6)
4435 1.2.4.2 wiz mov.l (%a0)+,0x8+EXC_FP0(%a6)
4436 1.2.4.2 wiz
4437 1.2.4.2 wiz fmovm_data_in_fp1:
4438 1.2.4.2 wiz lsl.b &0x1,%d1 # should FP1 be moved?
4439 1.2.4.2 wiz bpl.b fmovm_data_in_fp2 # no
4440 1.2.4.2 wiz
4441 1.2.4.2 wiz mov.l (%a0)+,0x0+EXC_FP1(%a6) # yes
4442 1.2.4.2 wiz mov.l (%a0)+,0x4+EXC_FP1(%a6)
4443 1.2.4.2 wiz mov.l (%a0)+,0x8+EXC_FP1(%a6)
4444 1.2.4.2 wiz
4445 1.2.4.2 wiz fmovm_data_in_fp2:
4446 1.2.4.2 wiz lsl.b &0x1,%d1 # should FP2 be moved?
4447 1.2.4.2 wiz bpl.b fmovm_data_in_fp3 # no
4448 1.2.4.2 wiz
4449 1.2.4.2 wiz fmovm.x (%a0)+,&0x20 # yes
4450 1.2.4.2 wiz
4451 1.2.4.2 wiz fmovm_data_in_fp3:
4452 1.2.4.2 wiz lsl.b &0x1,%d1 # should FP3 be moved?
4453 1.2.4.2 wiz bpl.b fmovm_data_in_fp4 # no
4454 1.2.4.2 wiz
4455 1.2.4.2 wiz fmovm.x (%a0)+,&0x10 # yes
4456 1.2.4.2 wiz
4457 1.2.4.2 wiz fmovm_data_in_fp4:
4458 1.2.4.2 wiz lsl.b &0x1,%d1 # should FP4 be moved?
4459 1.2.4.2 wiz bpl.b fmovm_data_in_fp5 # no
4460 1.2.4.2 wiz
4461 1.2.4.2 wiz fmovm.x (%a0)+,&0x08 # yes
4462 1.2.4.2 wiz
4463 1.2.4.2 wiz fmovm_data_in_fp5:
4464 1.2.4.2 wiz lsl.b &0x1,%d1 # should FP5 be moved?
4465 1.2.4.2 wiz bpl.b fmovm_data_in_fp6 # no
4466 1.2.4.2 wiz
4467 1.2.4.2 wiz fmovm.x (%a0)+,&0x04 # yes
4468 1.2.4.2 wiz
4469 1.2.4.2 wiz fmovm_data_in_fp6:
4470 1.2.4.2 wiz lsl.b &0x1,%d1 # should FP6 be moved?
4471 1.2.4.2 wiz bpl.b fmovm_data_in_fp7 # no
4472 1.2.4.2 wiz
4473 1.2.4.2 wiz fmovm.x (%a0)+,&0x02 # yes
4474 1.2.4.2 wiz
4475 1.2.4.2 wiz fmovm_data_in_fp7:
4476 1.2.4.2 wiz lsl.b &0x1,%d1 # should FP7 be moved?
4477 1.2.4.2 wiz bpl.b fmovm_data_in_done # no
4478 1.2.4.2 wiz
4479 1.2.4.2 wiz fmovm.x (%a0)+,&0x01 # yes
4480 1.2.4.2 wiz
4481 1.2.4.2 wiz fmovm_data_in_done:
4482 1.2.4.2 wiz add.l %d0,%sp # remove fpregs from stack
4483 1.2.4.2 wiz rts
4484 1.2.4.2 wiz
4485 1.2.4.2 wiz #####################################
4486 1.2.4.2 wiz
4487 1.2.4.2 wiz fmovm_data_done:
4488 1.2.4.2 wiz rts
4489 1.2.4.2 wiz
4490 1.2.4.2 wiz ##############################################################################
4491 1.2.4.2 wiz
4492 1.2.4.2 wiz #
4493 1.2.4.2 wiz # table indexed by the operation's bit string that gives the number
4494 1.2.4.2 wiz # of bytes that will be moved.
4495 1.2.4.2 wiz #
4496 1.2.4.2 wiz # number of bytes = (# of 1's in bit string) * 12(bytes/fpreg)
4497 1.2.4.2 wiz #
4498 1.2.4.2 wiz tbl_fmovm_size:
4499 1.2.4.2 wiz byte 0x00,0x0c,0x0c,0x18,0x0c,0x18,0x18,0x24
4500 1.2.4.2 wiz byte 0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
4501 1.2.4.2 wiz byte 0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
4502 1.2.4.2 wiz byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
4503 1.2.4.2 wiz byte 0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
4504 1.2.4.2 wiz byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
4505 1.2.4.2 wiz byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
4506 1.2.4.2 wiz byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
4507 1.2.4.2 wiz byte 0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
4508 1.2.4.2 wiz byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
4509 1.2.4.2 wiz byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
4510 1.2.4.2 wiz byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
4511 1.2.4.2 wiz byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
4512 1.2.4.2 wiz byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
4513 1.2.4.2 wiz byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
4514 1.2.4.2 wiz byte 0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
4515 1.2.4.2 wiz byte 0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
4516 1.2.4.2 wiz byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
4517 1.2.4.2 wiz byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
4518 1.2.4.2 wiz byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
4519 1.2.4.2 wiz byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
4520 1.2.4.2 wiz byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
4521 1.2.4.2 wiz byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
4522 1.2.4.2 wiz byte 0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
4523 1.2.4.2 wiz byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
4524 1.2.4.2 wiz byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
4525 1.2.4.2 wiz byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
4526 1.2.4.2 wiz byte 0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
4527 1.2.4.2 wiz byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
4528 1.2.4.2 wiz byte 0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
4529 1.2.4.2 wiz byte 0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
4530 1.2.4.2 wiz byte 0x3c,0x48,0x48,0x54,0x48,0x54,0x54,0x60
4531 1.2.4.2 wiz
4532 1.2.4.2 wiz #
4533 1.2.4.2 wiz # table to convert a pre-decrement bit string into a post-increment
4534 1.2.4.2 wiz # or control bit string.
4535 1.2.4.2 wiz # ex: 0x00 ==> 0x00
4536 1.2.4.2 wiz # 0x01 ==> 0x80
4537 1.2.4.2 wiz # 0x02 ==> 0x40
4538 1.2.4.2 wiz # .
4539 1.2.4.2 wiz # .
4540 1.2.4.2 wiz # 0xfd ==> 0xbf
4541 1.2.4.2 wiz # 0xfe ==> 0x7f
4542 1.2.4.2 wiz # 0xff ==> 0xff
4543 1.2.4.2 wiz #
4544 1.2.4.2 wiz tbl_fmovm_convert:
4545 1.2.4.2 wiz byte 0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0
4546 1.2.4.2 wiz byte 0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0
4547 1.2.4.2 wiz byte 0x08,0x88,0x48,0xc8,0x28,0xa8,0x68,0xe8
4548 1.2.4.2 wiz byte 0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8
4549 1.2.4.2 wiz byte 0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4
4550 1.2.4.2 wiz byte 0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4
4551 1.2.4.2 wiz byte 0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec
4552 1.2.4.2 wiz byte 0x1c,0x9c,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc
4553 1.2.4.2 wiz byte 0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2
4554 1.2.4.2 wiz byte 0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2
4555 1.2.4.2 wiz byte 0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea
4556 1.2.4.2 wiz byte 0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa
4557 1.2.4.2 wiz byte 0x06,0x86,0x46,0xc6,0x26,0xa6,0x66,0xe6
4558 1.2.4.2 wiz byte 0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6
4559 1.2.4.2 wiz byte 0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee
4560 1.2.4.2 wiz byte 0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe
4561 1.2.4.2 wiz byte 0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1
4562 1.2.4.2 wiz byte 0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1
4563 1.2.4.2 wiz byte 0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9
4564 1.2.4.2 wiz byte 0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9
4565 1.2.4.2 wiz byte 0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5
4566 1.2.4.2 wiz byte 0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5
4567 1.2.4.2 wiz byte 0x0d,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed
4568 1.2.4.2 wiz byte 0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd
4569 1.2.4.2 wiz byte 0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3
4570 1.2.4.2 wiz byte 0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3
4571 1.2.4.2 wiz byte 0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb
4572 1.2.4.2 wiz byte 0x1b,0x9b,0x5b,0xdb,0x3b,0xbb,0x7b,0xfb
4573 1.2.4.2 wiz byte 0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7
4574 1.2.4.2 wiz byte 0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7
4575 1.2.4.2 wiz byte 0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef
4576 1.2.4.2 wiz byte 0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff
4577 1.2.4.2 wiz
4578 1.2.4.2 wiz global fmovm_calc_ea
4579 1.2.4.2 wiz ###############################################
4580 1.2.4.2 wiz # _fmovm_calc_ea: calculate effective address #
4581 1.2.4.2 wiz ###############################################
4582 1.2.4.2 wiz fmovm_calc_ea:
4583 1.2.4.2 wiz mov.l %d0,%a0 # move # bytes to a0
4584 1.2.4.2 wiz
4585 1.2.4.2 wiz # currently, MODE and REG are taken from the EXC_OPWORD. this could be
4586 1.2.4.2 wiz # easily changed if they were inputs passed in registers.
4587 1.2.4.2 wiz mov.w EXC_OPWORD(%a6),%d0 # fetch opcode word
4588 1.2.4.2 wiz mov.w %d0,%d1 # make a copy
4589 1.2.4.2 wiz
4590 1.2.4.2 wiz andi.w &0x3f,%d0 # extract mode field
4591 1.2.4.2 wiz andi.l &0x7,%d1 # extract reg field
4592 1.2.4.2 wiz
4593 1.2.4.2 wiz # jump to the corresponding function for each {MODE,REG} pair.
4594 1.2.4.2 wiz mov.w (tbl_fea_mode.b,%pc,%d0.w*2),%d0 # fetch jmp distance
4595 1.2.4.2 wiz jmp (tbl_fea_mode.b,%pc,%d0.w*1) # jmp to correct ea mode
4596 1.2.4.2 wiz
4597 1.2.4.2 wiz swbeg &64
4598 1.2.4.2 wiz tbl_fea_mode:
4599 1.2.4.2 wiz short tbl_fea_mode - tbl_fea_mode
4600 1.2.4.2 wiz short tbl_fea_mode - tbl_fea_mode
4601 1.2.4.2 wiz short tbl_fea_mode - tbl_fea_mode
4602 1.2.4.2 wiz short tbl_fea_mode - tbl_fea_mode
4603 1.2.4.2 wiz short tbl_fea_mode - tbl_fea_mode
4604 1.2.4.2 wiz short tbl_fea_mode - tbl_fea_mode
4605 1.2.4.2 wiz short tbl_fea_mode - tbl_fea_mode
4606 1.2.4.2 wiz short tbl_fea_mode - tbl_fea_mode
4607 1.2.4.2 wiz
4608 1.2.4.2 wiz short tbl_fea_mode - tbl_fea_mode
4609 1.2.4.2 wiz short tbl_fea_mode - tbl_fea_mode
4610 1.2.4.2 wiz short tbl_fea_mode - tbl_fea_mode
4611 1.2.4.2 wiz short tbl_fea_mode - tbl_fea_mode
4612 1.2.4.2 wiz short tbl_fea_mode - tbl_fea_mode
4613 1.2.4.2 wiz short tbl_fea_mode - tbl_fea_mode
4614 1.2.4.2 wiz short tbl_fea_mode - tbl_fea_mode
4615 1.2.4.2 wiz short tbl_fea_mode - tbl_fea_mode
4616 1.2.4.2 wiz
4617 1.2.4.2 wiz short faddr_ind_a0 - tbl_fea_mode
4618 1.2.4.2 wiz short faddr_ind_a1 - tbl_fea_mode
4619 1.2.4.2 wiz short faddr_ind_a2 - tbl_fea_mode
4620 1.2.4.2 wiz short faddr_ind_a3 - tbl_fea_mode
4621 1.2.4.2 wiz short faddr_ind_a4 - tbl_fea_mode
4622 1.2.4.2 wiz short faddr_ind_a5 - tbl_fea_mode
4623 1.2.4.2 wiz short faddr_ind_a6 - tbl_fea_mode
4624 1.2.4.2 wiz short faddr_ind_a7 - tbl_fea_mode
4625 1.2.4.2 wiz
4626 1.2.4.2 wiz short faddr_ind_p_a0 - tbl_fea_mode
4627 1.2.4.2 wiz short faddr_ind_p_a1 - tbl_fea_mode
4628 1.2.4.2 wiz short faddr_ind_p_a2 - tbl_fea_mode
4629 1.2.4.2 wiz short faddr_ind_p_a3 - tbl_fea_mode
4630 1.2.4.2 wiz short faddr_ind_p_a4 - tbl_fea_mode
4631 1.2.4.2 wiz short faddr_ind_p_a5 - tbl_fea_mode
4632 1.2.4.2 wiz short faddr_ind_p_a6 - tbl_fea_mode
4633 1.2.4.2 wiz short faddr_ind_p_a7 - tbl_fea_mode
4634 1.2.4.2 wiz
4635 1.2.4.2 wiz short faddr_ind_m_a0 - tbl_fea_mode
4636 1.2.4.2 wiz short faddr_ind_m_a1 - tbl_fea_mode
4637 1.2.4.2 wiz short faddr_ind_m_a2 - tbl_fea_mode
4638 1.2.4.2 wiz short faddr_ind_m_a3 - tbl_fea_mode
4639 1.2.4.2 wiz short faddr_ind_m_a4 - tbl_fea_mode
4640 1.2.4.2 wiz short faddr_ind_m_a5 - tbl_fea_mode
4641 1.2.4.2 wiz short faddr_ind_m_a6 - tbl_fea_mode
4642 1.2.4.2 wiz short faddr_ind_m_a7 - tbl_fea_mode
4643 1.2.4.2 wiz
4644 1.2.4.2 wiz short faddr_ind_disp_a0 - tbl_fea_mode
4645 1.2.4.2 wiz short faddr_ind_disp_a1 - tbl_fea_mode
4646 1.2.4.2 wiz short faddr_ind_disp_a2 - tbl_fea_mode
4647 1.2.4.2 wiz short faddr_ind_disp_a3 - tbl_fea_mode
4648 1.2.4.2 wiz short faddr_ind_disp_a4 - tbl_fea_mode
4649 1.2.4.2 wiz short faddr_ind_disp_a5 - tbl_fea_mode
4650 1.2.4.2 wiz short faddr_ind_disp_a6 - tbl_fea_mode
4651 1.2.4.2 wiz short faddr_ind_disp_a7 - tbl_fea_mode
4652 1.2.4.2 wiz
4653 1.2.4.2 wiz short faddr_ind_ext - tbl_fea_mode
4654 1.2.4.2 wiz short faddr_ind_ext - tbl_fea_mode
4655 1.2.4.2 wiz short faddr_ind_ext - tbl_fea_mode
4656 1.2.4.2 wiz short faddr_ind_ext - tbl_fea_mode
4657 1.2.4.2 wiz short faddr_ind_ext - tbl_fea_mode
4658 1.2.4.2 wiz short faddr_ind_ext - tbl_fea_mode
4659 1.2.4.2 wiz short faddr_ind_ext - tbl_fea_mode
4660 1.2.4.2 wiz short faddr_ind_ext - tbl_fea_mode
4661 1.2.4.2 wiz
4662 1.2.4.2 wiz short fabs_short - tbl_fea_mode
4663 1.2.4.2 wiz short fabs_long - tbl_fea_mode
4664 1.2.4.2 wiz short fpc_ind - tbl_fea_mode
4665 1.2.4.2 wiz short fpc_ind_ext - tbl_fea_mode
4666 1.2.4.2 wiz short tbl_fea_mode - tbl_fea_mode
4667 1.2.4.2 wiz short tbl_fea_mode - tbl_fea_mode
4668 1.2.4.2 wiz short tbl_fea_mode - tbl_fea_mode
4669 1.2.4.2 wiz short tbl_fea_mode - tbl_fea_mode
4670 1.2.4.2 wiz
4671 1.2.4.2 wiz ###################################
4672 1.2.4.2 wiz # Address register indirect: (An) #
4673 1.2.4.2 wiz ###################################
4674 1.2.4.2 wiz faddr_ind_a0:
4675 1.2.4.2 wiz mov.l EXC_DREGS+0x8(%a6),%a0 # Get current a0
4676 1.2.4.2 wiz rts
4677 1.2.4.2 wiz
4678 1.2.4.2 wiz faddr_ind_a1:
4679 1.2.4.2 wiz mov.l EXC_DREGS+0xc(%a6),%a0 # Get current a1
4680 1.2.4.2 wiz rts
4681 1.2.4.2 wiz
4682 1.2.4.2 wiz faddr_ind_a2:
4683 1.2.4.2 wiz mov.l %a2,%a0 # Get current a2
4684 1.2.4.2 wiz rts
4685 1.2.4.2 wiz
4686 1.2.4.2 wiz faddr_ind_a3:
4687 1.2.4.2 wiz mov.l %a3,%a0 # Get current a3
4688 1.2.4.2 wiz rts
4689 1.2.4.2 wiz
4690 1.2.4.2 wiz faddr_ind_a4:
4691 1.2.4.2 wiz mov.l %a4,%a0 # Get current a4
4692 1.2.4.2 wiz rts
4693 1.2.4.2 wiz
4694 1.2.4.2 wiz faddr_ind_a5:
4695 1.2.4.2 wiz mov.l %a5,%a0 # Get current a5
4696 1.2.4.2 wiz rts
4697 1.2.4.2 wiz
4698 1.2.4.2 wiz faddr_ind_a6:
4699 1.2.4.2 wiz mov.l (%a6),%a0 # Get current a6
4700 1.2.4.2 wiz rts
4701 1.2.4.2 wiz
4702 1.2.4.2 wiz faddr_ind_a7:
4703 1.2.4.2 wiz mov.l EXC_A7(%a6),%a0 # Get current a7
4704 1.2.4.2 wiz rts
4705 1.2.4.2 wiz
4706 1.2.4.2 wiz #####################################################
4707 1.2.4.2 wiz # Address register indirect w/ postincrement: (An)+ #
4708 1.2.4.2 wiz #####################################################
4709 1.2.4.2 wiz faddr_ind_p_a0:
4710 1.2.4.2 wiz mov.l EXC_DREGS+0x8(%a6),%d0 # Get current a0
4711 1.2.4.2 wiz mov.l %d0,%d1
4712 1.2.4.2 wiz add.l %a0,%d1 # Increment
4713 1.2.4.2 wiz mov.l %d1,EXC_DREGS+0x8(%a6) # Save incr value
4714 1.2.4.2 wiz mov.l %d0,%a0
4715 1.2.4.2 wiz rts
4716 1.2.4.2 wiz
4717 1.2.4.2 wiz faddr_ind_p_a1:
4718 1.2.4.2 wiz mov.l EXC_DREGS+0xc(%a6),%d0 # Get current a1
4719 1.2.4.2 wiz mov.l %d0,%d1
4720 1.2.4.2 wiz add.l %a0,%d1 # Increment
4721 1.2.4.2 wiz mov.l %d1,EXC_DREGS+0xc(%a6) # Save incr value
4722 1.2.4.2 wiz mov.l %d0,%a0
4723 1.2.4.2 wiz rts
4724 1.2.4.2 wiz
4725 1.2.4.2 wiz faddr_ind_p_a2:
4726 1.2.4.2 wiz mov.l %a2,%d0 # Get current a2
4727 1.2.4.2 wiz mov.l %d0,%d1
4728 1.2.4.2 wiz add.l %a0,%d1 # Increment
4729 1.2.4.2 wiz mov.l %d1,%a2 # Save incr value
4730 1.2.4.2 wiz mov.l %d0,%a0
4731 1.2.4.2 wiz rts
4732 1.2.4.2 wiz
4733 1.2.4.2 wiz faddr_ind_p_a3:
4734 1.2.4.2 wiz mov.l %a3,%d0 # Get current a3
4735 1.2.4.2 wiz mov.l %d0,%d1
4736 1.2.4.2 wiz add.l %a0,%d1 # Increment
4737 1.2.4.2 wiz mov.l %d1,%a3 # Save incr value
4738 1.2.4.2 wiz mov.l %d0,%a0
4739 1.2.4.2 wiz rts
4740 1.2.4.2 wiz
4741 1.2.4.2 wiz faddr_ind_p_a4:
4742 1.2.4.2 wiz mov.l %a4,%d0 # Get current a4
4743 1.2.4.2 wiz mov.l %d0,%d1
4744 1.2.4.2 wiz add.l %a0,%d1 # Increment
4745 1.2.4.2 wiz mov.l %d1,%a4 # Save incr value
4746 1.2.4.2 wiz mov.l %d0,%a0
4747 1.2.4.2 wiz rts
4748 1.2.4.2 wiz
4749 1.2.4.2 wiz faddr_ind_p_a5:
4750 1.2.4.2 wiz mov.l %a5,%d0 # Get current a5
4751 1.2.4.2 wiz mov.l %d0,%d1
4752 1.2.4.2 wiz add.l %a0,%d1 # Increment
4753 1.2.4.2 wiz mov.l %d1,%a5 # Save incr value
4754 1.2.4.2 wiz mov.l %d0,%a0
4755 1.2.4.2 wiz rts
4756 1.2.4.2 wiz
4757 1.2.4.2 wiz faddr_ind_p_a6:
4758 1.2.4.2 wiz mov.l (%a6),%d0 # Get current a6
4759 1.2.4.2 wiz mov.l %d0,%d1
4760 1.2.4.2 wiz add.l %a0,%d1 # Increment
4761 1.2.4.2 wiz mov.l %d1,(%a6) # Save incr value
4762 1.2.4.2 wiz mov.l %d0,%a0
4763 1.2.4.2 wiz rts
4764 1.2.4.2 wiz
4765 1.2.4.2 wiz faddr_ind_p_a7:
4766 1.2.4.2 wiz mov.b &mia7_flg,SPCOND_FLG(%a6) # set "special case" flag
4767 1.2.4.2 wiz
4768 1.2.4.2 wiz mov.l EXC_A7(%a6),%d0 # Get current a7
4769 1.2.4.2 wiz mov.l %d0,%d1
4770 1.2.4.2 wiz add.l %a0,%d1 # Increment
4771 1.2.4.2 wiz mov.l %d1,EXC_A7(%a6) # Save incr value
4772 1.2.4.2 wiz mov.l %d0,%a0
4773 1.2.4.2 wiz rts
4774 1.2.4.2 wiz
4775 1.2.4.2 wiz ####################################################
4776 1.2.4.2 wiz # Address register indirect w/ predecrement: -(An) #
4777 1.2.4.2 wiz ####################################################
4778 1.2.4.2 wiz faddr_ind_m_a0:
4779 1.2.4.2 wiz mov.l EXC_DREGS+0x8(%a6),%d0 # Get current a0
4780 1.2.4.2 wiz sub.l %a0,%d0 # Decrement
4781 1.2.4.2 wiz mov.l %d0,EXC_DREGS+0x8(%a6) # Save decr value
4782 1.2.4.2 wiz mov.l %d0,%a0
4783 1.2.4.2 wiz rts
4784 1.2.4.2 wiz
4785 1.2.4.2 wiz faddr_ind_m_a1:
4786 1.2.4.2 wiz mov.l EXC_DREGS+0xc(%a6),%d0 # Get current a1
4787 1.2.4.2 wiz sub.l %a0,%d0 # Decrement
4788 1.2.4.2 wiz mov.l %d0,EXC_DREGS+0xc(%a6) # Save decr value
4789 1.2.4.2 wiz mov.l %d0,%a0
4790 1.2.4.2 wiz rts
4791 1.2.4.2 wiz
4792 1.2.4.2 wiz faddr_ind_m_a2:
4793 1.2.4.2 wiz mov.l %a2,%d0 # Get current a2
4794 1.2.4.2 wiz sub.l %a0,%d0 # Decrement
4795 1.2.4.2 wiz mov.l %d0,%a2 # Save decr value
4796 1.2.4.2 wiz mov.l %d0,%a0
4797 1.2.4.2 wiz rts
4798 1.2.4.2 wiz
4799 1.2.4.2 wiz faddr_ind_m_a3:
4800 1.2.4.2 wiz mov.l %a3,%d0 # Get current a3
4801 1.2.4.2 wiz sub.l %a0,%d0 # Decrement
4802 1.2.4.2 wiz mov.l %d0,%a3 # Save decr value
4803 1.2.4.2 wiz mov.l %d0,%a0
4804 1.2.4.2 wiz rts
4805 1.2.4.2 wiz
4806 1.2.4.2 wiz faddr_ind_m_a4:
4807 1.2.4.2 wiz mov.l %a4,%d0 # Get current a4
4808 1.2.4.2 wiz sub.l %a0,%d0 # Decrement
4809 1.2.4.2 wiz mov.l %d0,%a4 # Save decr value
4810 1.2.4.2 wiz mov.l %d0,%a0
4811 1.2.4.2 wiz rts
4812 1.2.4.2 wiz
4813 1.2.4.2 wiz faddr_ind_m_a5:
4814 1.2.4.2 wiz mov.l %a5,%d0 # Get current a5
4815 1.2.4.2 wiz sub.l %a0,%d0 # Decrement
4816 1.2.4.2 wiz mov.l %d0,%a5 # Save decr value
4817 1.2.4.2 wiz mov.l %d0,%a0
4818 1.2.4.2 wiz rts
4819 1.2.4.2 wiz
4820 1.2.4.2 wiz faddr_ind_m_a6:
4821 1.2.4.2 wiz mov.l (%a6),%d0 # Get current a6
4822 1.2.4.2 wiz sub.l %a0,%d0 # Decrement
4823 1.2.4.2 wiz mov.l %d0,(%a6) # Save decr value
4824 1.2.4.2 wiz mov.l %d0,%a0
4825 1.2.4.2 wiz rts
4826 1.2.4.2 wiz
4827 1.2.4.2 wiz faddr_ind_m_a7:
4828 1.2.4.2 wiz mov.b &mda7_flg,SPCOND_FLG(%a6) # set "special case" flag
4829 1.2.4.2 wiz
4830 1.2.4.2 wiz mov.l EXC_A7(%a6),%d0 # Get current a7
4831 1.2.4.2 wiz sub.l %a0,%d0 # Decrement
4832 1.2.4.2 wiz mov.l %d0,EXC_A7(%a6) # Save decr value
4833 1.2.4.2 wiz mov.l %d0,%a0
4834 1.2.4.2 wiz rts
4835 1.2.4.2 wiz
4836 1.2.4.2 wiz ########################################################
4837 1.2.4.2 wiz # Address register indirect w/ displacement: (d16, An) #
4838 1.2.4.2 wiz ########################################################
4839 1.2.4.2 wiz faddr_ind_disp_a0:
4840 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
4841 1.2.4.2 wiz addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
4842 1.2.4.2 wiz bsr.l _imem_read_word
4843 1.2.4.2 wiz
4844 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
4845 1.2.4.2 wiz bne.l iea_iacc # yes
4846 1.2.4.2 wiz
4847 1.2.4.2 wiz mov.w %d0,%a0 # sign extend displacement
4848 1.2.4.2 wiz
4849 1.2.4.2 wiz add.l EXC_DREGS+0x8(%a6),%a0 # a0 + d16
4850 1.2.4.2 wiz rts
4851 1.2.4.2 wiz
4852 1.2.4.2 wiz faddr_ind_disp_a1:
4853 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
4854 1.2.4.2 wiz addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
4855 1.2.4.2 wiz bsr.l _imem_read_word
4856 1.2.4.2 wiz
4857 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
4858 1.2.4.2 wiz bne.l iea_iacc # yes
4859 1.2.4.2 wiz
4860 1.2.4.2 wiz mov.w %d0,%a0 # sign extend displacement
4861 1.2.4.2 wiz
4862 1.2.4.2 wiz add.l EXC_DREGS+0xc(%a6),%a0 # a1 + d16
4863 1.2.4.2 wiz rts
4864 1.2.4.2 wiz
4865 1.2.4.2 wiz faddr_ind_disp_a2:
4866 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
4867 1.2.4.2 wiz addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
4868 1.2.4.2 wiz bsr.l _imem_read_word
4869 1.2.4.2 wiz
4870 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
4871 1.2.4.2 wiz bne.l iea_iacc # yes
4872 1.2.4.2 wiz
4873 1.2.4.2 wiz mov.w %d0,%a0 # sign extend displacement
4874 1.2.4.2 wiz
4875 1.2.4.2 wiz add.l %a2,%a0 # a2 + d16
4876 1.2.4.2 wiz rts
4877 1.2.4.2 wiz
4878 1.2.4.2 wiz faddr_ind_disp_a3:
4879 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
4880 1.2.4.2 wiz addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
4881 1.2.4.2 wiz bsr.l _imem_read_word
4882 1.2.4.2 wiz
4883 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
4884 1.2.4.2 wiz bne.l iea_iacc # yes
4885 1.2.4.2 wiz
4886 1.2.4.2 wiz mov.w %d0,%a0 # sign extend displacement
4887 1.2.4.2 wiz
4888 1.2.4.2 wiz add.l %a3,%a0 # a3 + d16
4889 1.2.4.2 wiz rts
4890 1.2.4.2 wiz
4891 1.2.4.2 wiz faddr_ind_disp_a4:
4892 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
4893 1.2.4.2 wiz addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
4894 1.2.4.2 wiz bsr.l _imem_read_word
4895 1.2.4.2 wiz
4896 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
4897 1.2.4.2 wiz bne.l iea_iacc # yes
4898 1.2.4.2 wiz
4899 1.2.4.2 wiz mov.w %d0,%a0 # sign extend displacement
4900 1.2.4.2 wiz
4901 1.2.4.2 wiz add.l %a4,%a0 # a4 + d16
4902 1.2.4.2 wiz rts
4903 1.2.4.2 wiz
4904 1.2.4.2 wiz faddr_ind_disp_a5:
4905 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
4906 1.2.4.2 wiz addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
4907 1.2.4.2 wiz bsr.l _imem_read_word
4908 1.2.4.2 wiz
4909 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
4910 1.2.4.2 wiz bne.l iea_iacc # yes
4911 1.2.4.2 wiz
4912 1.2.4.2 wiz mov.w %d0,%a0 # sign extend displacement
4913 1.2.4.2 wiz
4914 1.2.4.2 wiz add.l %a5,%a0 # a5 + d16
4915 1.2.4.2 wiz rts
4916 1.2.4.2 wiz
4917 1.2.4.2 wiz faddr_ind_disp_a6:
4918 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
4919 1.2.4.2 wiz addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
4920 1.2.4.2 wiz bsr.l _imem_read_word
4921 1.2.4.2 wiz
4922 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
4923 1.2.4.2 wiz bne.l iea_iacc # yes
4924 1.2.4.2 wiz
4925 1.2.4.2 wiz mov.w %d0,%a0 # sign extend displacement
4926 1.2.4.2 wiz
4927 1.2.4.2 wiz add.l (%a6),%a0 # a6 + d16
4928 1.2.4.2 wiz rts
4929 1.2.4.2 wiz
4930 1.2.4.2 wiz faddr_ind_disp_a7:
4931 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
4932 1.2.4.2 wiz addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
4933 1.2.4.2 wiz bsr.l _imem_read_word
4934 1.2.4.2 wiz
4935 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
4936 1.2.4.2 wiz bne.l iea_iacc # yes
4937 1.2.4.2 wiz
4938 1.2.4.2 wiz mov.w %d0,%a0 # sign extend displacement
4939 1.2.4.2 wiz
4940 1.2.4.2 wiz add.l EXC_A7(%a6),%a0 # a7 + d16
4941 1.2.4.2 wiz rts
4942 1.2.4.2 wiz
4943 1.2.4.2 wiz ########################################################################
4944 1.2.4.2 wiz # Address register indirect w/ index(8-bit displacement): (d8, An, Xn) #
4945 1.2.4.2 wiz # " " " w/ " (base displacement): (bd, An, Xn) #
4946 1.2.4.2 wiz # Memory indirect postindexed: ([bd, An], Xn, od) #
4947 1.2.4.2 wiz # Memory indirect preindexed: ([bd, An, Xn], od) #
4948 1.2.4.2 wiz ########################################################################
4949 1.2.4.2 wiz faddr_ind_ext:
4950 1.2.4.2 wiz addq.l &0x8,%d1
4951 1.2.4.2 wiz bsr.l fetch_dreg # fetch base areg
4952 1.2.4.2 wiz mov.l %d0,-(%sp)
4953 1.2.4.2 wiz
4954 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
4955 1.2.4.2 wiz addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
4956 1.2.4.2 wiz bsr.l _imem_read_word # fetch extword in d0
4957 1.2.4.2 wiz
4958 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
4959 1.2.4.2 wiz bne.l iea_iacc # yes
4960 1.2.4.2 wiz
4961 1.2.4.2 wiz mov.l (%sp)+,%a0
4962 1.2.4.2 wiz
4963 1.2.4.2 wiz btst &0x8,%d0
4964 1.2.4.2 wiz bne.w fcalc_mem_ind
4965 1.2.4.2 wiz
4966 1.2.4.2 wiz mov.l %d0,L_SCR1(%a6) # hold opword
4967 1.2.4.2 wiz
4968 1.2.4.2 wiz mov.l %d0,%d1
4969 1.2.4.2 wiz rol.w &0x4,%d1
4970 1.2.4.2 wiz andi.w &0xf,%d1 # extract index regno
4971 1.2.4.2 wiz
4972 1.2.4.2 wiz # count on fetch_dreg() not to alter a0...
4973 1.2.4.2 wiz bsr.l fetch_dreg # fetch index
4974 1.2.4.2 wiz
4975 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
4976 1.2.4.2 wiz mov.l L_SCR1(%a6),%d2 # fetch opword
4977 1.2.4.2 wiz
4978 1.2.4.2 wiz btst &0xb,%d2 # is it word or long?
4979 1.2.4.2 wiz bne.b faii8_long
4980 1.2.4.2 wiz ext.l %d0 # sign extend word index
4981 1.2.4.2 wiz faii8_long:
4982 1.2.4.2 wiz mov.l %d2,%d1
4983 1.2.4.2 wiz rol.w &0x7,%d1
4984 1.2.4.2 wiz andi.l &0x3,%d1 # extract scale value
4985 1.2.4.2 wiz
4986 1.2.4.2 wiz lsl.l %d1,%d0 # shift index by scale
4987 1.2.4.2 wiz
4988 1.2.4.2 wiz extb.l %d2 # sign extend displacement
4989 1.2.4.2 wiz add.l %d2,%d0 # index + disp
4990 1.2.4.2 wiz add.l %d0,%a0 # An + (index + disp)
4991 1.2.4.2 wiz
4992 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore old d2
4993 1.2.4.2 wiz rts
4994 1.2.4.2 wiz
4995 1.2.4.2 wiz ###########################
4996 1.2.4.2 wiz # Absolute short: (XXX).W #
4997 1.2.4.2 wiz ###########################
4998 1.2.4.2 wiz fabs_short:
4999 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5000 1.2.4.2 wiz addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
5001 1.2.4.2 wiz bsr.l _imem_read_word # fetch short address
5002 1.2.4.2 wiz
5003 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
5004 1.2.4.2 wiz bne.l iea_iacc # yes
5005 1.2.4.2 wiz
5006 1.2.4.2 wiz mov.w %d0,%a0 # return <ea> in a0
5007 1.2.4.2 wiz rts
5008 1.2.4.2 wiz
5009 1.2.4.2 wiz ##########################
5010 1.2.4.2 wiz # Absolute long: (XXX).L #
5011 1.2.4.2 wiz ##########################
5012 1.2.4.2 wiz fabs_long:
5013 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5014 1.2.4.2 wiz addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
5015 1.2.4.2 wiz bsr.l _imem_read_long # fetch long address
5016 1.2.4.2 wiz
5017 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
5018 1.2.4.2 wiz bne.l iea_iacc # yes
5019 1.2.4.2 wiz
5020 1.2.4.2 wiz mov.l %d0,%a0 # return <ea> in a0
5021 1.2.4.2 wiz rts
5022 1.2.4.2 wiz
5023 1.2.4.2 wiz #######################################################
5024 1.2.4.2 wiz # Program counter indirect w/ displacement: (d16, PC) #
5025 1.2.4.2 wiz #######################################################
5026 1.2.4.2 wiz fpc_ind:
5027 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5028 1.2.4.2 wiz addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
5029 1.2.4.2 wiz bsr.l _imem_read_word # fetch word displacement
5030 1.2.4.2 wiz
5031 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
5032 1.2.4.2 wiz bne.l iea_iacc # yes
5033 1.2.4.2 wiz
5034 1.2.4.2 wiz mov.w %d0,%a0 # sign extend displacement
5035 1.2.4.2 wiz
5036 1.2.4.2 wiz add.l EXC_EXTWPTR(%a6),%a0 # pc + d16
5037 1.2.4.2 wiz
5038 1.2.4.2 wiz # _imem_read_word() increased the extwptr by 2. need to adjust here.
5039 1.2.4.2 wiz subq.l &0x2,%a0 # adjust <ea>
5040 1.2.4.2 wiz rts
5041 1.2.4.2 wiz
5042 1.2.4.2 wiz ##########################################################
5043 1.2.4.2 wiz # PC indirect w/ index(8-bit displacement): (d8, PC, An) #
5044 1.2.4.2 wiz # " " w/ " (base displacement): (bd, PC, An) #
5045 1.2.4.2 wiz # PC memory indirect postindexed: ([bd, PC], Xn, od) #
5046 1.2.4.2 wiz # PC memory indirect preindexed: ([bd, PC, Xn], od) #
5047 1.2.4.2 wiz ##########################################################
5048 1.2.4.2 wiz fpc_ind_ext:
5049 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5050 1.2.4.2 wiz addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
5051 1.2.4.2 wiz bsr.l _imem_read_word # fetch ext word
5052 1.2.4.2 wiz
5053 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
5054 1.2.4.2 wiz bne.l iea_iacc # yes
5055 1.2.4.2 wiz
5056 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # put base in a0
5057 1.2.4.2 wiz subq.l &0x2,%a0 # adjust base
5058 1.2.4.2 wiz
5059 1.2.4.2 wiz btst &0x8,%d0 # is disp only 8 bits?
5060 1.2.4.2 wiz bne.w fcalc_mem_ind # calc memory indirect
5061 1.2.4.2 wiz
5062 1.2.4.2 wiz mov.l %d0,L_SCR1(%a6) # store opword
5063 1.2.4.2 wiz
5064 1.2.4.2 wiz mov.l %d0,%d1 # make extword copy
5065 1.2.4.2 wiz rol.w &0x4,%d1 # rotate reg num into place
5066 1.2.4.2 wiz andi.w &0xf,%d1 # extract register number
5067 1.2.4.2 wiz
5068 1.2.4.2 wiz # count on fetch_dreg() not to alter a0...
5069 1.2.4.2 wiz bsr.l fetch_dreg # fetch index
5070 1.2.4.2 wiz
5071 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
5072 1.2.4.2 wiz mov.l L_SCR1(%a6),%d2 # fetch opword
5073 1.2.4.2 wiz
5074 1.2.4.2 wiz btst &0xb,%d2 # is index word or long?
5075 1.2.4.2 wiz bne.b fpii8_long # long
5076 1.2.4.2 wiz ext.l %d0 # sign extend word index
5077 1.2.4.2 wiz fpii8_long:
5078 1.2.4.2 wiz mov.l %d2,%d1
5079 1.2.4.2 wiz rol.w &0x7,%d1 # rotate scale value into place
5080 1.2.4.2 wiz andi.l &0x3,%d1 # extract scale value
5081 1.2.4.2 wiz
5082 1.2.4.2 wiz lsl.l %d1,%d0 # shift index by scale
5083 1.2.4.2 wiz
5084 1.2.4.2 wiz extb.l %d2 # sign extend displacement
5085 1.2.4.2 wiz add.l %d2,%d0 # disp + index
5086 1.2.4.2 wiz add.l %d0,%a0 # An + (index + disp)
5087 1.2.4.2 wiz
5088 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore temp register
5089 1.2.4.2 wiz rts
5090 1.2.4.2 wiz
5091 1.2.4.2 wiz # d2 = index
5092 1.2.4.2 wiz # d3 = base
5093 1.2.4.2 wiz # d4 = od
5094 1.2.4.2 wiz # d5 = extword
5095 1.2.4.2 wiz fcalc_mem_ind:
5096 1.2.4.2 wiz btst &0x6,%d0 # is the index suppressed?
5097 1.2.4.2 wiz beq.b fcalc_index
5098 1.2.4.2 wiz
5099 1.2.4.2 wiz movm.l &0x3c00,-(%sp) # save d2-d5
5100 1.2.4.2 wiz
5101 1.2.4.2 wiz mov.l %d0,%d5 # put extword in d5
5102 1.2.4.2 wiz mov.l %a0,%d3 # put base in d3
5103 1.2.4.2 wiz
5104 1.2.4.2 wiz clr.l %d2 # yes, so index = 0
5105 1.2.4.2 wiz bra.b fbase_supp_ck
5106 1.2.4.2 wiz
5107 1.2.4.2 wiz # index:
5108 1.2.4.2 wiz fcalc_index:
5109 1.2.4.2 wiz mov.l %d0,L_SCR1(%a6) # save d0 (opword)
5110 1.2.4.2 wiz bfextu %d0{&16:&4},%d1 # fetch dreg index
5111 1.2.4.2 wiz bsr.l fetch_dreg
5112 1.2.4.2 wiz
5113 1.2.4.2 wiz movm.l &0x3c00,-(%sp) # save d2-d5
5114 1.2.4.2 wiz mov.l %d0,%d2 # put index in d2
5115 1.2.4.2 wiz mov.l L_SCR1(%a6),%d5
5116 1.2.4.2 wiz mov.l %a0,%d3
5117 1.2.4.2 wiz
5118 1.2.4.2 wiz btst &0xb,%d5 # is index word or long?
5119 1.2.4.2 wiz bne.b fno_ext
5120 1.2.4.2 wiz ext.l %d2
5121 1.2.4.2 wiz
5122 1.2.4.2 wiz fno_ext:
5123 1.2.4.2 wiz bfextu %d5{&21:&2},%d0
5124 1.2.4.2 wiz lsl.l %d0,%d2
5125 1.2.4.2 wiz
5126 1.2.4.2 wiz # base address (passed as parameter in d3):
5127 1.2.4.2 wiz # we clear the value here if it should actually be suppressed.
5128 1.2.4.2 wiz fbase_supp_ck:
5129 1.2.4.2 wiz btst &0x7,%d5 # is the bd suppressed?
5130 1.2.4.2 wiz beq.b fno_base_sup
5131 1.2.4.2 wiz clr.l %d3
5132 1.2.4.2 wiz
5133 1.2.4.2 wiz # base displacement:
5134 1.2.4.2 wiz fno_base_sup:
5135 1.2.4.2 wiz bfextu %d5{&26:&2},%d0 # get bd size
5136 1.2.4.2 wiz # beq.l fmovm_error # if (size == 0) it's reserved
5137 1.2.4.2 wiz
5138 1.2.4.2 wiz cmpi.b %d0,&0x2
5139 1.2.4.2 wiz blt.b fno_bd
5140 1.2.4.2 wiz beq.b fget_word_bd
5141 1.2.4.2 wiz
5142 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5143 1.2.4.2 wiz addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
5144 1.2.4.2 wiz bsr.l _imem_read_long
5145 1.2.4.2 wiz
5146 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
5147 1.2.4.2 wiz bne.l fcea_iacc # yes
5148 1.2.4.2 wiz
5149 1.2.4.2 wiz bra.b fchk_ind
5150 1.2.4.2 wiz
5151 1.2.4.2 wiz fget_word_bd:
5152 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5153 1.2.4.2 wiz addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
5154 1.2.4.2 wiz bsr.l _imem_read_word
5155 1.2.4.2 wiz
5156 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
5157 1.2.4.2 wiz bne.l fcea_iacc # yes
5158 1.2.4.2 wiz
5159 1.2.4.2 wiz ext.l %d0 # sign extend bd
5160 1.2.4.2 wiz
5161 1.2.4.2 wiz fchk_ind:
5162 1.2.4.2 wiz add.l %d0,%d3 # base += bd
5163 1.2.4.2 wiz
5164 1.2.4.2 wiz # outer displacement:
5165 1.2.4.2 wiz fno_bd:
5166 1.2.4.2 wiz bfextu %d5{&30:&2},%d0 # is od suppressed?
5167 1.2.4.2 wiz beq.w faii_bd
5168 1.2.4.2 wiz
5169 1.2.4.2 wiz cmpi.b %d0,&0x2
5170 1.2.4.2 wiz blt.b fnull_od
5171 1.2.4.2 wiz beq.b fword_od
5172 1.2.4.2 wiz
5173 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5174 1.2.4.2 wiz addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
5175 1.2.4.2 wiz bsr.l _imem_read_long
5176 1.2.4.2 wiz
5177 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
5178 1.2.4.2 wiz bne.l fcea_iacc # yes
5179 1.2.4.2 wiz
5180 1.2.4.2 wiz bra.b fadd_them
5181 1.2.4.2 wiz
5182 1.2.4.2 wiz fword_od:
5183 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5184 1.2.4.2 wiz addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
5185 1.2.4.2 wiz bsr.l _imem_read_word
5186 1.2.4.2 wiz
5187 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
5188 1.2.4.2 wiz bne.l fcea_iacc # yes
5189 1.2.4.2 wiz
5190 1.2.4.2 wiz ext.l %d0 # sign extend od
5191 1.2.4.2 wiz bra.b fadd_them
5192 1.2.4.2 wiz
5193 1.2.4.2 wiz fnull_od:
5194 1.2.4.2 wiz clr.l %d0
5195 1.2.4.2 wiz
5196 1.2.4.2 wiz fadd_them:
5197 1.2.4.2 wiz mov.l %d0,%d4
5198 1.2.4.2 wiz
5199 1.2.4.2 wiz btst &0x2,%d5 # pre or post indexing?
5200 1.2.4.2 wiz beq.b fpre_indexed
5201 1.2.4.2 wiz
5202 1.2.4.2 wiz mov.l %d3,%a0
5203 1.2.4.2 wiz bsr.l _dmem_read_long
5204 1.2.4.2 wiz
5205 1.2.4.2 wiz tst.l %d1 # did dfetch fail?
5206 1.2.4.2 wiz bne.w fcea_err # yes
5207 1.2.4.2 wiz
5208 1.2.4.2 wiz add.l %d2,%d0 # <ea> += index
5209 1.2.4.2 wiz add.l %d4,%d0 # <ea> += od
5210 1.2.4.2 wiz bra.b fdone_ea
5211 1.2.4.2 wiz
5212 1.2.4.2 wiz fpre_indexed:
5213 1.2.4.2 wiz add.l %d2,%d3 # preindexing
5214 1.2.4.2 wiz mov.l %d3,%a0
5215 1.2.4.2 wiz bsr.l _dmem_read_long
5216 1.2.4.2 wiz
5217 1.2.4.2 wiz tst.l %d1 # did dfetch fail?
5218 1.2.4.2 wiz bne.w fcea_err # yes
5219 1.2.4.2 wiz
5220 1.2.4.2 wiz add.l %d4,%d0 # ea += od
5221 1.2.4.2 wiz bra.b fdone_ea
5222 1.2.4.2 wiz
5223 1.2.4.2 wiz faii_bd:
5224 1.2.4.2 wiz add.l %d2,%d3 # ea = (base + bd) + index
5225 1.2.4.2 wiz mov.l %d3,%d0
5226 1.2.4.2 wiz fdone_ea:
5227 1.2.4.2 wiz mov.l %d0,%a0
5228 1.2.4.2 wiz
5229 1.2.4.2 wiz movm.l (%sp)+,&0x003c # restore d2-d5
5230 1.2.4.2 wiz rts
5231 1.2.4.2 wiz
5232 1.2.4.2 wiz #########################################################
5233 1.2.4.2 wiz fcea_err:
5234 1.2.4.2 wiz mov.l %d3,%a0
5235 1.2.4.2 wiz
5236 1.2.4.2 wiz movm.l (%sp)+,&0x003c # restore d2-d5
5237 1.2.4.2 wiz mov.w &0x0101,%d0
5238 1.2.4.2 wiz bra.l iea_dacc
5239 1.2.4.2 wiz
5240 1.2.4.2 wiz fcea_iacc:
5241 1.2.4.2 wiz movm.l (%sp)+,&0x003c # restore d2-d5
5242 1.2.4.2 wiz bra.l iea_iacc
5243 1.2.4.2 wiz
5244 1.2.4.2 wiz fmovm_out_err:
5245 1.2.4.2 wiz bsr.l restore
5246 1.2.4.2 wiz mov.w &0x00e1,%d0
5247 1.2.4.2 wiz bra.b fmovm_err
5248 1.2.4.2 wiz
5249 1.2.4.2 wiz fmovm_in_err:
5250 1.2.4.2 wiz bsr.l restore
5251 1.2.4.2 wiz mov.w &0x0161,%d0
5252 1.2.4.2 wiz
5253 1.2.4.2 wiz fmovm_err:
5254 1.2.4.2 wiz mov.l L_SCR1(%a6),%a0
5255 1.2.4.2 wiz bra.l iea_dacc
5256 1.2.4.2 wiz
5257 1.2.4.2 wiz #########################################################################
5258 1.2.4.2 wiz # XDEF **************************************************************** #
5259 1.2.4.2 wiz # fmovm_ctrl(): emulate fmovm.l of control registers instr #
5260 1.2.4.2 wiz # #
5261 1.2.4.2 wiz # XREF **************************************************************** #
5262 1.2.4.2 wiz # _imem_read_long() - read longword from memory #
5263 1.2.4.2 wiz # iea_iacc() - _imem_read_long() failed; error recovery #
5264 1.2.4.2 wiz # #
5265 1.2.4.2 wiz # INPUT *************************************************************** #
5266 1.2.4.2 wiz # None #
5267 1.2.4.2 wiz # #
5268 1.2.4.2 wiz # OUTPUT ************************************************************** #
5269 1.2.4.2 wiz # If _imem_read_long() doesn't fail: #
5270 1.2.4.2 wiz # USER_FPCR(a6) = new FPCR value #
5271 1.2.4.2 wiz # USER_FPSR(a6) = new FPSR value #
5272 1.2.4.2 wiz # USER_FPIAR(a6) = new FPIAR value #
5273 1.2.4.2 wiz # #
5274 1.2.4.2 wiz # ALGORITHM *********************************************************** #
5275 1.2.4.2 wiz # Decode the instruction type by looking at the extension word #
5276 1.2.4.2 wiz # in order to see how many control registers to fetch from memory. #
5277 1.2.4.2 wiz # Fetch them using _imem_read_long(). If this fetch fails, exit through #
5278 1.2.4.2 wiz # the special access error exit handler iea_iacc(). #
5279 1.2.4.2 wiz # #
5280 1.2.4.2 wiz # Instruction word decoding: #
5281 1.2.4.2 wiz # #
5282 1.2.4.2 wiz # fmovem.l #<data>, {FPIAR&|FPCR&|FPSR} #
5283 1.2.4.2 wiz # #
5284 1.2.4.2 wiz # WORD1 WORD2 #
5285 1.2.4.2 wiz # 1111 0010 00 111100 100$ $$00 0000 0000 #
5286 1.2.4.2 wiz # #
5287 1.2.4.2 wiz # $$$ (100): FPCR #
5288 1.2.4.2 wiz # (010): FPSR #
5289 1.2.4.2 wiz # (001): FPIAR #
5290 1.2.4.2 wiz # (000): FPIAR #
5291 1.2.4.2 wiz # #
5292 1.2.4.2 wiz #########################################################################
5293 1.2.4.2 wiz
5294 1.2.4.2 wiz global fmovm_ctrl
5295 1.2.4.2 wiz fmovm_ctrl:
5296 1.2.4.2 wiz mov.b EXC_EXTWORD(%a6),%d0 # fetch reg select bits
5297 1.2.4.2 wiz cmpi.b %d0,&0x9c # fpcr & fpsr & fpiar ?
5298 1.2.4.2 wiz beq.w fctrl_in_7 # yes
5299 1.2.4.2 wiz cmpi.b %d0,&0x98 # fpcr & fpsr ?
5300 1.2.4.2 wiz beq.w fctrl_in_6 # yes
5301 1.2.4.2 wiz cmpi.b %d0,&0x94 # fpcr & fpiar ?
5302 1.2.4.2 wiz beq.b fctrl_in_5 # yes
5303 1.2.4.2 wiz
5304 1.2.4.2 wiz # fmovem.l #<data>, fpsr/fpiar
5305 1.2.4.2 wiz fctrl_in_3:
5306 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5307 1.2.4.2 wiz addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
5308 1.2.4.2 wiz bsr.l _imem_read_long # fetch FPSR from mem
5309 1.2.4.2 wiz
5310 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
5311 1.2.4.2 wiz bne.l iea_iacc # yes
5312 1.2.4.2 wiz
5313 1.2.4.2 wiz mov.l %d0,USER_FPSR(%a6) # store new FPSR to stack
5314 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5315 1.2.4.2 wiz addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
5316 1.2.4.2 wiz bsr.l _imem_read_long # fetch FPIAR from mem
5317 1.2.4.2 wiz
5318 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
5319 1.2.4.2 wiz bne.l iea_iacc # yes
5320 1.2.4.2 wiz
5321 1.2.4.2 wiz mov.l %d0,USER_FPIAR(%a6) # store new FPIAR to stack
5322 1.2.4.2 wiz rts
5323 1.2.4.2 wiz
5324 1.2.4.2 wiz # fmovem.l #<data>, fpcr/fpiar
5325 1.2.4.2 wiz fctrl_in_5:
5326 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5327 1.2.4.2 wiz addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
5328 1.2.4.2 wiz bsr.l _imem_read_long # fetch FPCR from mem
5329 1.2.4.2 wiz
5330 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
5331 1.2.4.2 wiz bne.l iea_iacc # yes
5332 1.2.4.2 wiz
5333 1.2.4.2 wiz mov.l %d0,USER_FPCR(%a6) # store new FPCR to stack
5334 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5335 1.2.4.2 wiz addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
5336 1.2.4.2 wiz bsr.l _imem_read_long # fetch FPIAR from mem
5337 1.2.4.2 wiz
5338 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
5339 1.2.4.2 wiz bne.l iea_iacc # yes
5340 1.2.4.2 wiz
5341 1.2.4.2 wiz mov.l %d0,USER_FPIAR(%a6) # store new FPIAR to stack
5342 1.2.4.2 wiz rts
5343 1.2.4.2 wiz
5344 1.2.4.2 wiz # fmovem.l #<data>, fpcr/fpsr
5345 1.2.4.2 wiz fctrl_in_6:
5346 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5347 1.2.4.2 wiz addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
5348 1.2.4.2 wiz bsr.l _imem_read_long # fetch FPCR from mem
5349 1.2.4.2 wiz
5350 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
5351 1.2.4.2 wiz bne.l iea_iacc # yes
5352 1.2.4.2 wiz
5353 1.2.4.2 wiz mov.l %d0,USER_FPCR(%a6) # store new FPCR to mem
5354 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5355 1.2.4.2 wiz addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
5356 1.2.4.2 wiz bsr.l _imem_read_long # fetch FPSR from mem
5357 1.2.4.2 wiz
5358 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
5359 1.2.4.2 wiz bne.l iea_iacc # yes
5360 1.2.4.2 wiz
5361 1.2.4.2 wiz mov.l %d0,USER_FPSR(%a6) # store new FPSR to mem
5362 1.2.4.2 wiz rts
5363 1.2.4.2 wiz
5364 1.2.4.2 wiz # fmovem.l #<data>, fpcr/fpsr/fpiar
5365 1.2.4.2 wiz fctrl_in_7:
5366 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5367 1.2.4.2 wiz addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
5368 1.2.4.2 wiz bsr.l _imem_read_long # fetch FPCR from mem
5369 1.2.4.2 wiz
5370 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
5371 1.2.4.2 wiz bne.l iea_iacc # yes
5372 1.2.4.2 wiz
5373 1.2.4.2 wiz mov.l %d0,USER_FPCR(%a6) # store new FPCR to mem
5374 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5375 1.2.4.2 wiz addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
5376 1.2.4.2 wiz bsr.l _imem_read_long # fetch FPSR from mem
5377 1.2.4.2 wiz
5378 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
5379 1.2.4.2 wiz bne.l iea_iacc # yes
5380 1.2.4.2 wiz
5381 1.2.4.2 wiz mov.l %d0,USER_FPSR(%a6) # store new FPSR to mem
5382 1.2.4.2 wiz mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
5383 1.2.4.2 wiz addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
5384 1.2.4.2 wiz bsr.l _imem_read_long # fetch FPIAR from mem
5385 1.2.4.2 wiz
5386 1.2.4.2 wiz tst.l %d1 # did ifetch fail?
5387 1.2.4.2 wiz bne.l iea_iacc # yes
5388 1.2.4.2 wiz
5389 1.2.4.2 wiz mov.l %d0,USER_FPIAR(%a6) # store new FPIAR to mem
5390 1.2.4.2 wiz rts
5391 1.2.4.2 wiz
5392 1.2.4.2 wiz ##########################################################################
5393 1.2.4.2 wiz
5394 1.2.4.2 wiz #########################################################################
5395 1.2.4.2 wiz # XDEF **************************************************************** #
5396 1.2.4.2 wiz # addsub_scaler2(): scale inputs to fadd/fsub such that no #
5397 1.2.4.2 wiz # OVFL/UNFL exceptions will result #
5398 1.2.4.2 wiz # #
5399 1.2.4.2 wiz # XREF **************************************************************** #
5400 1.2.4.2 wiz # norm() - normalize mantissa after adjusting exponent #
5401 1.2.4.2 wiz # #
5402 1.2.4.2 wiz # INPUT *************************************************************** #
5403 1.2.4.2 wiz # FP_SRC(a6) = fp op1(src) #
5404 1.2.4.2 wiz # FP_DST(a6) = fp op2(dst) #
5405 1.2.4.2 wiz # #
5406 1.2.4.2 wiz # OUTPUT ************************************************************** #
5407 1.2.4.2 wiz # FP_SRC(a6) = fp op1 scaled(src) #
5408 1.2.4.2 wiz # FP_DST(a6) = fp op2 scaled(dst) #
5409 1.2.4.2 wiz # d0 = scale amount #
5410 1.2.4.2 wiz # #
5411 1.2.4.2 wiz # ALGORITHM *********************************************************** #
5412 1.2.4.2 wiz # If the DST exponent is > the SRC exponent, set the DST exponent #
5413 1.2.4.2 wiz # equal to 0x3fff and scale the SRC exponent by the value that the #
5414 1.2.4.2 wiz # DST exponent was scaled by. If the SRC exponent is greater or equal, #
5415 1.2.4.2 wiz # do the opposite. Return this scale factor in d0. #
5416 1.2.4.2 wiz # If the two exponents differ by > the number of mantissa bits #
5417 1.2.4.2 wiz # plus two, then set the smallest exponent to a very small value as a #
5418 1.2.4.2 wiz # quick shortcut. #
5419 1.2.4.2 wiz # #
5420 1.2.4.2 wiz #########################################################################
5421 1.2.4.2 wiz
5422 1.2.4.2 wiz global addsub_scaler2
5423 1.2.4.2 wiz addsub_scaler2:
5424 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
5425 1.2.4.2 wiz mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
5426 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
5427 1.2.4.2 wiz mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
5428 1.2.4.2 wiz mov.w SRC_EX(%a0),%d0
5429 1.2.4.2 wiz mov.w DST_EX(%a1),%d1
5430 1.2.4.2 wiz mov.w %d0,FP_SCR0_EX(%a6)
5431 1.2.4.2 wiz mov.w %d1,FP_SCR1_EX(%a6)
5432 1.2.4.2 wiz
5433 1.2.4.2 wiz andi.w &0x7fff,%d0
5434 1.2.4.2 wiz andi.w &0x7fff,%d1
5435 1.2.4.2 wiz mov.w %d0,L_SCR1(%a6) # store src exponent
5436 1.2.4.2 wiz mov.w %d1,2+L_SCR1(%a6) # store dst exponent
5437 1.2.4.2 wiz
5438 1.2.4.2 wiz cmp.w %d0, %d1 # is src exp >= dst exp?
5439 1.2.4.2 wiz bge.l src_exp_ge2
5440 1.2.4.2 wiz
5441 1.2.4.2 wiz # dst exp is > src exp; scale dst to exp = 0x3fff
5442 1.2.4.2 wiz dst_exp_gt2:
5443 1.2.4.2 wiz bsr.l scale_to_zero_dst
5444 1.2.4.2 wiz mov.l %d0,-(%sp) # save scale factor
5445 1.2.4.2 wiz
5446 1.2.4.2 wiz cmpi.b STAG(%a6),&DENORM # is dst denormalized?
5447 1.2.4.2 wiz bne.b cmpexp12
5448 1.2.4.2 wiz
5449 1.2.4.2 wiz lea FP_SCR0(%a6),%a0
5450 1.2.4.2 wiz bsr.l norm # normalize the denorm; result is new exp
5451 1.2.4.2 wiz neg.w %d0 # new exp = -(shft val)
5452 1.2.4.2 wiz mov.w %d0,L_SCR1(%a6) # inset new exp
5453 1.2.4.2 wiz
5454 1.2.4.2 wiz cmpexp12:
5455 1.2.4.2 wiz mov.w 2+L_SCR1(%a6),%d0
5456 1.2.4.2 wiz subi.w &mantissalen+2,%d0 # subtract mantissalen+2 from larger exp
5457 1.2.4.2 wiz
5458 1.2.4.2 wiz cmp.w %d0,L_SCR1(%a6) # is difference >= len(mantissa)+2?
5459 1.2.4.2 wiz bge.b quick_scale12
5460 1.2.4.2 wiz
5461 1.2.4.2 wiz mov.w L_SCR1(%a6),%d0
5462 1.2.4.2 wiz add.w 0x2(%sp),%d0 # scale src exponent by scale factor
5463 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1
5464 1.2.4.2 wiz and.w &0x8000,%d1
5465 1.2.4.2 wiz or.w %d1,%d0 # concat {sgn,new exp}
5466 1.2.4.2 wiz mov.w %d0,FP_SCR0_EX(%a6) # insert new dst exponent
5467 1.2.4.2 wiz
5468 1.2.4.2 wiz mov.l (%sp)+,%d0 # return SCALE factor
5469 1.2.4.2 wiz rts
5470 1.2.4.2 wiz
5471 1.2.4.2 wiz quick_scale12:
5472 1.2.4.2 wiz andi.w &0x8000,FP_SCR0_EX(%a6) # zero src exponent
5473 1.2.4.2 wiz bset &0x0,1+FP_SCR0_EX(%a6) # set exp = 1
5474 1.2.4.2 wiz
5475 1.2.4.2 wiz mov.l (%sp)+,%d0 # return SCALE factor
5476 1.2.4.2 wiz rts
5477 1.2.4.2 wiz
5478 1.2.4.2 wiz # src exp is >= dst exp; scale src to exp = 0x3fff
5479 1.2.4.2 wiz src_exp_ge2:
5480 1.2.4.2 wiz bsr.l scale_to_zero_src
5481 1.2.4.2 wiz mov.l %d0,-(%sp) # save scale factor
5482 1.2.4.2 wiz
5483 1.2.4.2 wiz cmpi.b DTAG(%a6),&DENORM # is dst denormalized?
5484 1.2.4.2 wiz bne.b cmpexp22
5485 1.2.4.2 wiz lea FP_SCR1(%a6),%a0
5486 1.2.4.2 wiz bsr.l norm # normalize the denorm; result is new exp
5487 1.2.4.2 wiz neg.w %d0 # new exp = -(shft val)
5488 1.2.4.2 wiz mov.w %d0,2+L_SCR1(%a6) # inset new exp
5489 1.2.4.2 wiz
5490 1.2.4.2 wiz cmpexp22:
5491 1.2.4.2 wiz mov.w L_SCR1(%a6),%d0
5492 1.2.4.2 wiz subi.w &mantissalen+2,%d0 # subtract mantissalen+2 from larger exp
5493 1.2.4.2 wiz
5494 1.2.4.2 wiz cmp.w %d0,2+L_SCR1(%a6) # is difference >= len(mantissa)+2?
5495 1.2.4.2 wiz bge.b quick_scale22
5496 1.2.4.2 wiz
5497 1.2.4.2 wiz mov.w 2+L_SCR1(%a6),%d0
5498 1.2.4.2 wiz add.w 0x2(%sp),%d0 # scale dst exponent by scale factor
5499 1.2.4.2 wiz mov.w FP_SCR1_EX(%a6),%d1
5500 1.2.4.2 wiz andi.w &0x8000,%d1
5501 1.2.4.2 wiz or.w %d1,%d0 # concat {sgn,new exp}
5502 1.2.4.2 wiz mov.w %d0,FP_SCR1_EX(%a6) # insert new dst exponent
5503 1.2.4.2 wiz
5504 1.2.4.2 wiz mov.l (%sp)+,%d0 # return SCALE factor
5505 1.2.4.2 wiz rts
5506 1.2.4.2 wiz
5507 1.2.4.2 wiz quick_scale22:
5508 1.2.4.2 wiz andi.w &0x8000,FP_SCR1_EX(%a6) # zero dst exponent
5509 1.2.4.2 wiz bset &0x0,1+FP_SCR1_EX(%a6) # set exp = 1
5510 1.2.4.2 wiz
5511 1.2.4.2 wiz mov.l (%sp)+,%d0 # return SCALE factor
5512 1.2.4.2 wiz rts
5513 1.2.4.2 wiz
5514 1.2.4.2 wiz ##########################################################################
5515 1.2.4.2 wiz
5516 1.2.4.2 wiz #########################################################################
5517 1.2.4.2 wiz # XDEF **************************************************************** #
5518 1.2.4.2 wiz # scale_to_zero_src(): scale the exponent of extended precision #
5519 1.2.4.2 wiz # value at FP_SCR0(a6). #
5520 1.2.4.2 wiz # #
5521 1.2.4.2 wiz # XREF **************************************************************** #
5522 1.2.4.2 wiz # norm() - normalize the mantissa if the operand was a DENORM #
5523 1.2.4.2 wiz # #
5524 1.2.4.2 wiz # INPUT *************************************************************** #
5525 1.2.4.2 wiz # FP_SCR0(a6) = extended precision operand to be scaled #
5526 1.2.4.2 wiz # #
5527 1.2.4.2 wiz # OUTPUT ************************************************************** #
5528 1.2.4.2 wiz # FP_SCR0(a6) = scaled extended precision operand #
5529 1.2.4.2 wiz # d0 = scale value #
5530 1.2.4.2 wiz # #
5531 1.2.4.2 wiz # ALGORITHM *********************************************************** #
5532 1.2.4.2 wiz # Set the exponent of the input operand to 0x3fff. Save the value #
5533 1.2.4.2 wiz # of the difference between the original and new exponent. Then, #
5534 1.2.4.2 wiz # normalize the operand if it was a DENORM. Add this normalization #
5535 1.2.4.2 wiz # value to the previous value. Return the result. #
5536 1.2.4.2 wiz # #
5537 1.2.4.2 wiz #########################################################################
5538 1.2.4.2 wiz
5539 1.2.4.2 wiz global scale_to_zero_src
5540 1.2.4.2 wiz scale_to_zero_src:
5541 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # extract operand's {sgn,exp}
5542 1.2.4.2 wiz mov.w %d1,%d0 # make a copy
5543 1.2.4.2 wiz
5544 1.2.4.2 wiz andi.l &0x7fff,%d1 # extract operand's exponent
5545 1.2.4.2 wiz
5546 1.2.4.2 wiz andi.w &0x8000,%d0 # extract operand's sgn
5547 1.2.4.2 wiz or.w &0x3fff,%d0 # insert new operand's exponent(=0)
5548 1.2.4.2 wiz
5549 1.2.4.2 wiz mov.w %d0,FP_SCR0_EX(%a6) # insert biased exponent
5550 1.2.4.2 wiz
5551 1.2.4.2 wiz cmpi.b STAG(%a6),&DENORM # is operand normalized?
5552 1.2.4.2 wiz beq.b stzs_denorm # normalize the DENORM
5553 1.2.4.2 wiz
5554 1.2.4.2 wiz stzs_norm:
5555 1.2.4.2 wiz mov.l &0x3fff,%d0
5556 1.2.4.2 wiz sub.l %d1,%d0 # scale = BIAS + (-exp)
5557 1.2.4.2 wiz
5558 1.2.4.2 wiz rts
5559 1.2.4.2 wiz
5560 1.2.4.2 wiz stzs_denorm:
5561 1.2.4.2 wiz lea FP_SCR0(%a6),%a0 # pass ptr to src op
5562 1.2.4.2 wiz bsr.l norm # normalize denorm
5563 1.2.4.2 wiz neg.l %d0 # new exponent = -(shft val)
5564 1.2.4.2 wiz mov.l %d0,%d1 # prepare for op_norm call
5565 1.2.4.2 wiz bra.b stzs_norm # finish scaling
5566 1.2.4.2 wiz
5567 1.2.4.2 wiz ###
5568 1.2.4.2 wiz
5569 1.2.4.2 wiz #########################################################################
5570 1.2.4.2 wiz # XDEF **************************************************************** #
5571 1.2.4.2 wiz # scale_sqrt(): scale the input operand exponent so a subsequent #
5572 1.2.4.2 wiz # fsqrt operation won't take an exception. #
5573 1.2.4.2 wiz # #
5574 1.2.4.2 wiz # XREF **************************************************************** #
5575 1.2.4.2 wiz # norm() - normalize the mantissa if the operand was a DENORM #
5576 1.2.4.2 wiz # #
5577 1.2.4.2 wiz # INPUT *************************************************************** #
5578 1.2.4.2 wiz # FP_SCR0(a6) = extended precision operand to be scaled #
5579 1.2.4.2 wiz # #
5580 1.2.4.2 wiz # OUTPUT ************************************************************** #
5581 1.2.4.2 wiz # FP_SCR0(a6) = scaled extended precision operand #
5582 1.2.4.2 wiz # d0 = scale value #
5583 1.2.4.2 wiz # #
5584 1.2.4.2 wiz # ALGORITHM *********************************************************** #
5585 1.2.4.2 wiz # If the input operand is a DENORM, normalize it. #
5586 1.2.4.2 wiz # If the exponent of the input operand is even, set the exponent #
5587 1.2.4.2 wiz # to 0x3ffe and return a scale factor of "(exp-0x3ffe)/2". If the #
5588 1.2.4.2 wiz # exponent of the input operand is off, set the exponent to ox3fff and #
5589 1.2.4.2 wiz # return a scale factor of "(exp-0x3fff)/2". #
5590 1.2.4.2 wiz # #
5591 1.2.4.2 wiz #########################################################################
5592 1.2.4.2 wiz
5593 1.2.4.2 wiz global scale_sqrt
5594 1.2.4.2 wiz scale_sqrt:
5595 1.2.4.2 wiz cmpi.b STAG(%a6),&DENORM # is operand normalized?
5596 1.2.4.2 wiz beq.b ss_denorm # normalize the DENORM
5597 1.2.4.2 wiz
5598 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # extract operand's {sgn,exp}
5599 1.2.4.2 wiz andi.l &0x7fff,%d1 # extract operand's exponent
5600 1.2.4.2 wiz
5601 1.2.4.2 wiz andi.w &0x8000,FP_SCR0_EX(%a6) # extract operand's sgn
5602 1.2.4.2 wiz
5603 1.2.4.2 wiz btst &0x0,%d1 # is exp even or odd?
5604 1.2.4.2 wiz beq.b ss_norm_even
5605 1.2.4.2 wiz
5606 1.2.4.2 wiz ori.w &0x3fff,FP_SCR0_EX(%a6) # insert new operand's exponent(=0)
5607 1.2.4.2 wiz
5608 1.2.4.2 wiz mov.l &0x3fff,%d0
5609 1.2.4.2 wiz sub.l %d1,%d0 # scale = BIAS + (-exp)
5610 1.2.4.2 wiz asr.l &0x1,%d0 # divide scale factor by 2
5611 1.2.4.2 wiz rts
5612 1.2.4.2 wiz
5613 1.2.4.2 wiz ss_norm_even:
5614 1.2.4.2 wiz ori.w &0x3ffe,FP_SCR0_EX(%a6) # insert new operand's exponent(=0)
5615 1.2.4.2 wiz
5616 1.2.4.2 wiz mov.l &0x3ffe,%d0
5617 1.2.4.2 wiz sub.l %d1,%d0 # scale = BIAS + (-exp)
5618 1.2.4.2 wiz asr.l &0x1,%d0 # divide scale factor by 2
5619 1.2.4.2 wiz rts
5620 1.2.4.2 wiz
5621 1.2.4.2 wiz ss_denorm:
5622 1.2.4.2 wiz lea FP_SCR0(%a6),%a0 # pass ptr to src op
5623 1.2.4.2 wiz bsr.l norm # normalize denorm
5624 1.2.4.2 wiz
5625 1.2.4.2 wiz btst &0x0,%d0 # is exp even or odd?
5626 1.2.4.2 wiz beq.b ss_denorm_even
5627 1.2.4.2 wiz
5628 1.2.4.2 wiz ori.w &0x3fff,FP_SCR0_EX(%a6) # insert new operand's exponent(=0)
5629 1.2.4.2 wiz
5630 1.2.4.2 wiz add.l &0x3fff,%d0
5631 1.2.4.2 wiz asr.l &0x1,%d0 # divide scale factor by 2
5632 1.2.4.2 wiz rts
5633 1.2.4.2 wiz
5634 1.2.4.2 wiz ss_denorm_even:
5635 1.2.4.2 wiz ori.w &0x3ffe,FP_SCR0_EX(%a6) # insert new operand's exponent(=0)
5636 1.2.4.2 wiz
5637 1.2.4.2 wiz add.l &0x3ffe,%d0
5638 1.2.4.2 wiz asr.l &0x1,%d0 # divide scale factor by 2
5639 1.2.4.2 wiz rts
5640 1.2.4.2 wiz
5641 1.2.4.2 wiz ###
5642 1.2.4.2 wiz
5643 1.2.4.2 wiz #########################################################################
5644 1.2.4.2 wiz # XDEF **************************************************************** #
5645 1.2.4.2 wiz # scale_to_zero_dst(): scale the exponent of extended precision #
5646 1.2.4.2 wiz # value at FP_SCR1(a6). #
5647 1.2.4.2 wiz # #
5648 1.2.4.2 wiz # XREF **************************************************************** #
5649 1.2.4.2 wiz # norm() - normalize the mantissa if the operand was a DENORM #
5650 1.2.4.2 wiz # #
5651 1.2.4.2 wiz # INPUT *************************************************************** #
5652 1.2.4.2 wiz # FP_SCR1(a6) = extended precision operand to be scaled #
5653 1.2.4.2 wiz # #
5654 1.2.4.2 wiz # OUTPUT ************************************************************** #
5655 1.2.4.2 wiz # FP_SCR1(a6) = scaled extended precision operand #
5656 1.2.4.2 wiz # d0 = scale value #
5657 1.2.4.2 wiz # #
5658 1.2.4.2 wiz # ALGORITHM *********************************************************** #
5659 1.2.4.2 wiz # Set the exponent of the input operand to 0x3fff. Save the value #
5660 1.2.4.2 wiz # of the difference between the original and new exponent. Then, #
5661 1.2.4.2 wiz # normalize the operand if it was a DENORM. Add this normalization #
5662 1.2.4.2 wiz # value to the previous value. Return the result. #
5663 1.2.4.2 wiz # #
5664 1.2.4.2 wiz #########################################################################
5665 1.2.4.2 wiz
5666 1.2.4.2 wiz global scale_to_zero_dst
5667 1.2.4.2 wiz scale_to_zero_dst:
5668 1.2.4.2 wiz mov.w FP_SCR1_EX(%a6),%d1 # extract operand's {sgn,exp}
5669 1.2.4.2 wiz mov.w %d1,%d0 # make a copy
5670 1.2.4.2 wiz
5671 1.2.4.2 wiz andi.l &0x7fff,%d1 # extract operand's exponent
5672 1.2.4.2 wiz
5673 1.2.4.2 wiz andi.w &0x8000,%d0 # extract operand's sgn
5674 1.2.4.2 wiz or.w &0x3fff,%d0 # insert new operand's exponent(=0)
5675 1.2.4.2 wiz
5676 1.2.4.2 wiz mov.w %d0,FP_SCR1_EX(%a6) # insert biased exponent
5677 1.2.4.2 wiz
5678 1.2.4.2 wiz cmpi.b DTAG(%a6),&DENORM # is operand normalized?
5679 1.2.4.2 wiz beq.b stzd_denorm # normalize the DENORM
5680 1.2.4.2 wiz
5681 1.2.4.2 wiz stzd_norm:
5682 1.2.4.2 wiz mov.l &0x3fff,%d0
5683 1.2.4.2 wiz sub.l %d1,%d0 # scale = BIAS + (-exp)
5684 1.2.4.2 wiz rts
5685 1.2.4.2 wiz
5686 1.2.4.2 wiz stzd_denorm:
5687 1.2.4.2 wiz lea FP_SCR1(%a6),%a0 # pass ptr to dst op
5688 1.2.4.2 wiz bsr.l norm # normalize denorm
5689 1.2.4.2 wiz neg.l %d0 # new exponent = -(shft val)
5690 1.2.4.2 wiz mov.l %d0,%d1 # prepare for op_norm call
5691 1.2.4.2 wiz bra.b stzd_norm # finish scaling
5692 1.2.4.2 wiz
5693 1.2.4.2 wiz ##########################################################################
5694 1.2.4.2 wiz
5695 1.2.4.2 wiz #########################################################################
5696 1.2.4.2 wiz # XDEF **************************************************************** #
5697 1.2.4.2 wiz # res_qnan(): return default result w/ QNAN operand for dyadic #
5698 1.2.4.2 wiz # res_snan(): return default result w/ SNAN operand for dyadic #
5699 1.2.4.2 wiz # res_qnan_1op(): return dflt result w/ QNAN operand for monadic #
5700 1.2.4.2 wiz # res_snan_1op(): return dflt result w/ SNAN operand for monadic #
5701 1.2.4.2 wiz # #
5702 1.2.4.2 wiz # XREF **************************************************************** #
5703 1.2.4.2 wiz # None #
5704 1.2.4.2 wiz # #
5705 1.2.4.2 wiz # INPUT *************************************************************** #
5706 1.2.4.2 wiz # FP_SRC(a6) = pointer to extended precision src operand #
5707 1.2.4.2 wiz # FP_DST(a6) = pointer to extended precision dst operand #
5708 1.2.4.2 wiz # #
5709 1.2.4.2 wiz # OUTPUT ************************************************************** #
5710 1.2.4.2 wiz # fp0 = default result #
5711 1.2.4.2 wiz # #
5712 1.2.4.2 wiz # ALGORITHM *********************************************************** #
5713 1.2.4.2 wiz # If either operand (but not both operands) of an operation is a #
5714 1.2.4.2 wiz # nonsignalling NAN, then that NAN is returned as the result. If both #
5715 1.2.4.2 wiz # operands are nonsignalling NANs, then the destination operand #
5716 1.2.4.2 wiz # nonsignalling NAN is returned as the result. #
5717 1.2.4.2 wiz # If either operand to an operation is a signalling NAN (SNAN), #
5718 1.2.4.2 wiz # then, the SNAN bit is set in the FPSR EXC byte. If the SNAN trap #
5719 1.2.4.2 wiz # enable bit is set in the FPCR, then the trap is taken and the #
5720 1.2.4.2 wiz # destination is not modified. If the SNAN trap enable bit is not set, #
5721 1.2.4.2 wiz # then the SNAN is converted to a nonsignalling NAN (by setting the #
5722 1.2.4.2 wiz # SNAN bit in the operand to one), and the operation continues as #
5723 1.2.4.2 wiz # described in the preceding paragraph, for nonsignalling NANs. #
5724 1.2.4.2 wiz # Make sure the appropriate FPSR bits are set before exiting. #
5725 1.2.4.2 wiz # #
5726 1.2.4.2 wiz #########################################################################
5727 1.2.4.2 wiz
5728 1.2.4.2 wiz global res_qnan
5729 1.2.4.2 wiz global res_snan
5730 1.2.4.2 wiz res_qnan:
5731 1.2.4.2 wiz res_snan:
5732 1.2.4.2 wiz cmp.b DTAG(%a6), &SNAN # is the dst an SNAN?
5733 1.2.4.2 wiz beq.b dst_snan2
5734 1.2.4.2 wiz cmp.b DTAG(%a6), &QNAN # is the dst a QNAN?
5735 1.2.4.2 wiz beq.b dst_qnan2
5736 1.2.4.2 wiz src_nan:
5737 1.2.4.2 wiz cmp.b STAG(%a6), &QNAN
5738 1.2.4.2 wiz beq.b src_qnan2
5739 1.2.4.2 wiz global res_snan_1op
5740 1.2.4.2 wiz res_snan_1op:
5741 1.2.4.2 wiz src_snan2:
5742 1.2.4.2 wiz bset &0x6, FP_SRC_HI(%a6) # set SNAN bit
5743 1.2.4.2 wiz or.l &nan_mask+aiop_mask+snan_mask, USER_FPSR(%a6)
5744 1.2.4.2 wiz lea FP_SRC(%a6), %a0
5745 1.2.4.2 wiz bra.b nan_comp
5746 1.2.4.2 wiz global res_qnan_1op
5747 1.2.4.2 wiz res_qnan_1op:
5748 1.2.4.2 wiz src_qnan2:
5749 1.2.4.2 wiz or.l &nan_mask, USER_FPSR(%a6)
5750 1.2.4.2 wiz lea FP_SRC(%a6), %a0
5751 1.2.4.2 wiz bra.b nan_comp
5752 1.2.4.2 wiz dst_snan2:
5753 1.2.4.2 wiz or.l &nan_mask+aiop_mask+snan_mask, USER_FPSR(%a6)
5754 1.2.4.2 wiz bset &0x6, FP_DST_HI(%a6) # set SNAN bit
5755 1.2.4.2 wiz lea FP_DST(%a6), %a0
5756 1.2.4.2 wiz bra.b nan_comp
5757 1.2.4.2 wiz dst_qnan2:
5758 1.2.4.2 wiz lea FP_DST(%a6), %a0
5759 1.2.4.2 wiz cmp.b STAG(%a6), &SNAN
5760 1.2.4.2 wiz bne nan_done
5761 1.2.4.2 wiz or.l &aiop_mask+snan_mask, USER_FPSR(%a6)
5762 1.2.4.2 wiz nan_done:
5763 1.2.4.2 wiz or.l &nan_mask, USER_FPSR(%a6)
5764 1.2.4.2 wiz nan_comp:
5765 1.2.4.2 wiz btst &0x7, FTEMP_EX(%a0) # is NAN neg?
5766 1.2.4.2 wiz beq.b nan_not_neg
5767 1.2.4.2 wiz or.l &neg_mask, USER_FPSR(%a6)
5768 1.2.4.2 wiz nan_not_neg:
5769 1.2.4.2 wiz fmovm.x (%a0), &0x80
5770 1.2.4.2 wiz rts
5771 1.2.4.2 wiz
5772 1.2.4.2 wiz #########################################################################
5773 1.2.4.2 wiz # XDEF **************************************************************** #
5774 1.2.4.2 wiz # res_operr(): return default result during operand error #
5775 1.2.4.2 wiz # #
5776 1.2.4.2 wiz # XREF **************************************************************** #
5777 1.2.4.2 wiz # None #
5778 1.2.4.2 wiz # #
5779 1.2.4.2 wiz # INPUT *************************************************************** #
5780 1.2.4.2 wiz # None #
5781 1.2.4.2 wiz # #
5782 1.2.4.2 wiz # OUTPUT ************************************************************** #
5783 1.2.4.2 wiz # fp0 = default operand error result #
5784 1.2.4.2 wiz # #
5785 1.2.4.2 wiz # ALGORITHM *********************************************************** #
5786 1.2.4.2 wiz # An nonsignalling NAN is returned as the default result when #
5787 1.2.4.2 wiz # an operand error occurs for the following cases: #
5788 1.2.4.2 wiz # #
5789 1.2.4.2 wiz # Multiply: (Infinity x Zero) #
5790 1.2.4.2 wiz # Divide : (Zero / Zero) || (Infinity / Infinity) #
5791 1.2.4.2 wiz # #
5792 1.2.4.2 wiz #########################################################################
5793 1.2.4.2 wiz
5794 1.2.4.2 wiz global res_operr
5795 1.2.4.2 wiz res_operr:
5796 1.2.4.2 wiz or.l &nan_mask+operr_mask+aiop_mask, USER_FPSR(%a6)
5797 1.2.4.2 wiz fmovm.x nan_return(%pc), &0x80
5798 1.2.4.2 wiz rts
5799 1.2.4.2 wiz
5800 1.2.4.2 wiz nan_return:
5801 1.2.4.2 wiz long 0x7fff0000, 0xffffffff, 0xffffffff
5802 1.2.4.2 wiz
5803 1.2.4.2 wiz #########################################################################
5804 1.2.4.2 wiz # XDEF **************************************************************** #
5805 1.2.4.2 wiz # _denorm(): denormalize an intermediate result #
5806 1.2.4.2 wiz # #
5807 1.2.4.2 wiz # XREF **************************************************************** #
5808 1.2.4.2 wiz # None #
5809 1.2.4.2 wiz # #
5810 1.2.4.2 wiz # INPUT *************************************************************** #
5811 1.2.4.2 wiz # a0 = points to the operand to be denormalized #
5812 1.2.4.2 wiz # (in the internal extended format) #
5813 1.2.4.2 wiz # #
5814 1.2.4.2 wiz # d0 = rounding precision #
5815 1.2.4.2 wiz # #
5816 1.2.4.2 wiz # OUTPUT ************************************************************** #
5817 1.2.4.2 wiz # a0 = pointer to the denormalized result #
5818 1.2.4.2 wiz # (in the internal extended format) #
5819 1.2.4.2 wiz # #
5820 1.2.4.2 wiz # d0 = guard,round,sticky #
5821 1.2.4.2 wiz # #
5822 1.2.4.2 wiz # ALGORITHM *********************************************************** #
5823 1.2.4.2 wiz # According to the exponent underflow threshold for the given #
5824 1.2.4.2 wiz # precision, shift the mantissa bits to the right in order raise the #
5825 1.2.4.2 wiz # exponent of the operand to the threshold value. While shifting the #
5826 1.2.4.2 wiz # mantissa bits right, maintain the value of the guard, round, and #
5827 1.2.4.2 wiz # sticky bits. #
5828 1.2.4.2 wiz # other notes: #
5829 1.2.4.2 wiz # (1) _denorm() is called by the underflow routines #
5830 1.2.4.2 wiz # (2) _denorm() does NOT affect the status register #
5831 1.2.4.2 wiz # #
5832 1.2.4.2 wiz #########################################################################
5833 1.2.4.2 wiz
5834 1.2.4.2 wiz #
5835 1.2.4.2 wiz # table of exponent threshold values for each precision
5836 1.2.4.2 wiz #
5837 1.2.4.2 wiz tbl_thresh:
5838 1.2.4.2 wiz short 0x0
5839 1.2.4.2 wiz short sgl_thresh
5840 1.2.4.2 wiz short dbl_thresh
5841 1.2.4.2 wiz
5842 1.2.4.2 wiz global _denorm
5843 1.2.4.2 wiz _denorm:
5844 1.2.4.2 wiz #
5845 1.2.4.2 wiz # Load the exponent threshold for the precision selected and check
5846 1.2.4.2 wiz # to see if (threshold - exponent) is > 65 in which case we can
5847 1.2.4.2 wiz # simply calculate the sticky bit and zero the mantissa. otherwise
5848 1.2.4.2 wiz # we have to call the denormalization routine.
5849 1.2.4.2 wiz #
5850 1.2.4.2 wiz lsr.b &0x2, %d0 # shift prec to lo bits
5851 1.2.4.2 wiz mov.w (tbl_thresh.b,%pc,%d0.w*2), %d1 # load prec threshold
5852 1.2.4.2 wiz mov.w %d1, %d0 # copy d1 into d0
5853 1.2.4.2 wiz sub.w FTEMP_EX(%a0), %d0 # diff = threshold - exp
5854 1.2.4.2 wiz cmpi.w %d0, &66 # is diff > 65? (mant + g,r bits)
5855 1.2.4.2 wiz bpl.b denorm_set_stky # yes; just calc sticky
5856 1.2.4.2 wiz
5857 1.2.4.2 wiz clr.l %d0 # clear g,r,s
5858 1.2.4.2 wiz btst &inex2_bit, FPSR_EXCEPT(%a6) # yes; was INEX2 set?
5859 1.2.4.2 wiz beq.b denorm_call # no; don't change anything
5860 1.2.4.2 wiz bset &29, %d0 # yes; set sticky bit
5861 1.2.4.2 wiz
5862 1.2.4.2 wiz denorm_call:
5863 1.2.4.2 wiz bsr.l dnrm_lp # denormalize the number
5864 1.2.4.2 wiz rts
5865 1.2.4.2 wiz
5866 1.2.4.2 wiz #
5867 1.2.4.2 wiz # all bit would have been shifted off during the denorm so simply
5868 1.2.4.2 wiz # calculate if the sticky should be set and clear the entire mantissa.
5869 1.2.4.2 wiz #
5870 1.2.4.2 wiz denorm_set_stky:
5871 1.2.4.2 wiz mov.l &0x20000000, %d0 # set sticky bit in return value
5872 1.2.4.2 wiz mov.w %d1, FTEMP_EX(%a0) # load exp with threshold
5873 1.2.4.2 wiz clr.l FTEMP_HI(%a0) # set d1 = 0 (ms mantissa)
5874 1.2.4.2 wiz clr.l FTEMP_LO(%a0) # set d2 = 0 (ms mantissa)
5875 1.2.4.2 wiz rts
5876 1.2.4.2 wiz
5877 1.2.4.2 wiz # #
5878 1.2.4.2 wiz # dnrm_lp(): normalize exponent/mantissa to specified threshhold #
5879 1.2.4.2 wiz # #
5880 1.2.4.2 wiz # INPUT: #
5881 1.2.4.2 wiz # %a0 : points to the operand to be denormalized #
5882 1.2.4.2 wiz # %d0{31:29} : initial guard,round,sticky #
5883 1.2.4.2 wiz # %d1{15:0} : denormalization threshold #
5884 1.2.4.2 wiz # OUTPUT: #
5885 1.2.4.2 wiz # %a0 : points to the denormalized operand #
5886 1.2.4.2 wiz # %d0{31:29} : final guard,round,sticky #
5887 1.2.4.2 wiz # #
5888 1.2.4.2 wiz
5889 1.2.4.2 wiz # *** Local Equates *** #
5890 1.2.4.2 wiz set GRS, L_SCR2 # g,r,s temp storage
5891 1.2.4.2 wiz set FTEMP_LO2, L_SCR1 # FTEMP_LO copy
5892 1.2.4.2 wiz
5893 1.2.4.2 wiz global dnrm_lp
5894 1.2.4.2 wiz dnrm_lp:
5895 1.2.4.2 wiz
5896 1.2.4.2 wiz #
5897 1.2.4.2 wiz # make a copy of FTEMP_LO and place the g,r,s bits directly after it
5898 1.2.4.2 wiz # in memory so as to make the bitfield extraction for denormalization easier.
5899 1.2.4.2 wiz #
5900 1.2.4.2 wiz mov.l FTEMP_LO(%a0), FTEMP_LO2(%a6) # make FTEMP_LO copy
5901 1.2.4.2 wiz mov.l %d0, GRS(%a6) # place g,r,s after it
5902 1.2.4.2 wiz
5903 1.2.4.2 wiz #
5904 1.2.4.2 wiz # check to see how much less than the underflow threshold the operand
5905 1.2.4.2 wiz # exponent is.
5906 1.2.4.2 wiz #
5907 1.2.4.2 wiz mov.l %d1, %d0 # copy the denorm threshold
5908 1.2.4.2 wiz sub.w FTEMP_EX(%a0), %d1 # d1 = threshold - uns exponent
5909 1.2.4.2 wiz ble.b dnrm_no_lp # d1 <= 0
5910 1.2.4.2 wiz cmpi.w %d1, &0x20 # is ( 0 <= d1 < 32) ?
5911 1.2.4.2 wiz blt.b case_1 # yes
5912 1.2.4.2 wiz cmpi.w %d1, &0x40 # is (32 <= d1 < 64) ?
5913 1.2.4.2 wiz blt.b case_2 # yes
5914 1.2.4.2 wiz bra.w case_3 # (d1 >= 64)
5915 1.2.4.2 wiz
5916 1.2.4.2 wiz #
5917 1.2.4.2 wiz # No normalization necessary
5918 1.2.4.2 wiz #
5919 1.2.4.2 wiz dnrm_no_lp:
5920 1.2.4.2 wiz mov.l GRS(%a6), %d0 # restore original g,r,s
5921 1.2.4.2 wiz rts
5922 1.2.4.2 wiz
5923 1.2.4.2 wiz #
5924 1.2.4.2 wiz # case (0<d1<32)
5925 1.2.4.2 wiz #
5926 1.2.4.2 wiz # %d0 = denorm threshold
5927 1.2.4.2 wiz # %d1 = "n" = amt to shift
5928 1.2.4.2 wiz #
5929 1.2.4.2 wiz # ---------------------------------------------------------
5930 1.2.4.2 wiz # | FTEMP_HI | FTEMP_LO |grs000.........000|
5931 1.2.4.2 wiz # ---------------------------------------------------------
5932 1.2.4.2 wiz # <-(32 - n)-><-(n)-><-(32 - n)-><-(n)-><-(32 - n)-><-(n)->
5933 1.2.4.2 wiz # \ \ \ \
5934 1.2.4.2 wiz # \ \ \ \
5935 1.2.4.2 wiz # \ \ \ \
5936 1.2.4.2 wiz # \ \ \ \
5937 1.2.4.2 wiz # \ \ \ \
5938 1.2.4.2 wiz # \ \ \ \
5939 1.2.4.2 wiz # \ \ \ \
5940 1.2.4.2 wiz # \ \ \ \
5941 1.2.4.2 wiz # <-(n)-><-(32 - n)-><------(32)-------><------(32)------->
5942 1.2.4.2 wiz # ---------------------------------------------------------
5943 1.2.4.2 wiz # |0.....0| NEW_HI | NEW_FTEMP_LO |grs |
5944 1.2.4.2 wiz # ---------------------------------------------------------
5945 1.2.4.2 wiz #
5946 1.2.4.2 wiz case_1:
5947 1.2.4.2 wiz mov.l %d2, -(%sp) # create temp storage
5948 1.2.4.2 wiz
5949 1.2.4.2 wiz mov.w %d0, FTEMP_EX(%a0) # exponent = denorm threshold
5950 1.2.4.2 wiz mov.l &32, %d0
5951 1.2.4.2 wiz sub.w %d1, %d0 # %d0 = 32 - %d1
5952 1.2.4.2 wiz
5953 1.2.4.2 wiz cmpi.w %d1, &29 # is shft amt >= 29
5954 1.2.4.2 wiz blt.b case1_extract # no; no fix needed
5955 1.2.4.2 wiz mov.b GRS(%a6), %d2
5956 1.2.4.2 wiz or.b %d2, 3+FTEMP_LO2(%a6)
5957 1.2.4.2 wiz
5958 1.2.4.2 wiz case1_extract:
5959 1.2.4.2 wiz bfextu FTEMP_HI(%a0){&0:%d0}, %d2 # %d2 = new FTEMP_HI
5960 1.2.4.2 wiz bfextu FTEMP_HI(%a0){%d0:&32}, %d1 # %d1 = new FTEMP_LO
5961 1.2.4.2 wiz bfextu FTEMP_LO2(%a6){%d0:&32}, %d0 # %d0 = new G,R,S
5962 1.2.4.2 wiz
5963 1.2.4.2 wiz mov.l %d2, FTEMP_HI(%a0) # store new FTEMP_HI
5964 1.2.4.2 wiz mov.l %d1, FTEMP_LO(%a0) # store new FTEMP_LO
5965 1.2.4.2 wiz
5966 1.2.4.2 wiz bftst %d0{&2:&30} # were bits shifted off?
5967 1.2.4.2 wiz beq.b case1_sticky_clear # no; go finish
5968 1.2.4.2 wiz bset &rnd_stky_bit, %d0 # yes; set sticky bit
5969 1.2.4.2 wiz
5970 1.2.4.2 wiz case1_sticky_clear:
5971 1.2.4.2 wiz and.l &0xe0000000, %d0 # clear all but G,R,S
5972 1.2.4.2 wiz mov.l (%sp)+, %d2 # restore temp register
5973 1.2.4.2 wiz rts
5974 1.2.4.2 wiz
5975 1.2.4.2 wiz #
5976 1.2.4.2 wiz # case (32<=d1<64)
5977 1.2.4.2 wiz #
5978 1.2.4.2 wiz # %d0 = denorm threshold
5979 1.2.4.2 wiz # %d1 = "n" = amt to shift
5980 1.2.4.2 wiz #
5981 1.2.4.2 wiz # ---------------------------------------------------------
5982 1.2.4.2 wiz # | FTEMP_HI | FTEMP_LO |grs000.........000|
5983 1.2.4.2 wiz # ---------------------------------------------------------
5984 1.2.4.2 wiz # <-(32 - n)-><-(n)-><-(32 - n)-><-(n)-><-(32 - n)-><-(n)->
5985 1.2.4.2 wiz # \ \ \
5986 1.2.4.2 wiz # \ \ \
5987 1.2.4.2 wiz # \ \ -------------------
5988 1.2.4.2 wiz # \ -------------------- \
5989 1.2.4.2 wiz # ------------------- \ \
5990 1.2.4.2 wiz # \ \ \
5991 1.2.4.2 wiz # \ \ \
5992 1.2.4.2 wiz # \ \ \
5993 1.2.4.2 wiz # <-------(32)------><-(n)-><-(32 - n)-><------(32)------->
5994 1.2.4.2 wiz # ---------------------------------------------------------
5995 1.2.4.2 wiz # |0...............0|0....0| NEW_LO |grs |
5996 1.2.4.2 wiz # ---------------------------------------------------------
5997 1.2.4.2 wiz #
5998 1.2.4.2 wiz case_2:
5999 1.2.4.2 wiz mov.l %d2, -(%sp) # create temp storage
6000 1.2.4.2 wiz
6001 1.2.4.2 wiz mov.w %d0, FTEMP_EX(%a0) # exponent = denorm threshold
6002 1.2.4.2 wiz subi.w &0x20, %d1 # %d1 now between 0 and 32
6003 1.2.4.2 wiz mov.l &0x20, %d0
6004 1.2.4.2 wiz sub.w %d1, %d0 # %d0 = 32 - %d1
6005 1.2.4.2 wiz
6006 1.2.4.2 wiz # subtle step here; or in the g,r,s at the bottom of FTEMP_LO to minimize
6007 1.2.4.2 wiz # the number of bits to check for the sticky detect.
6008 1.2.4.2 wiz # it only plays a role in shift amounts of 61-63.
6009 1.2.4.2 wiz mov.b GRS(%a6), %d2
6010 1.2.4.2 wiz or.b %d2, 3+FTEMP_LO2(%a6)
6011 1.2.4.2 wiz
6012 1.2.4.2 wiz bfextu FTEMP_HI(%a0){&0:%d0}, %d2 # %d2 = new FTEMP_LO
6013 1.2.4.2 wiz bfextu FTEMP_HI(%a0){%d0:&32}, %d1 # %d1 = new G,R,S
6014 1.2.4.2 wiz
6015 1.2.4.2 wiz bftst %d1{&2:&30} # were any bits shifted off?
6016 1.2.4.2 wiz bne.b case2_set_sticky # yes; set sticky bit
6017 1.2.4.2 wiz bftst FTEMP_LO2(%a6){%d0:&31} # were any bits shifted off?
6018 1.2.4.2 wiz bne.b case2_set_sticky # yes; set sticky bit
6019 1.2.4.2 wiz
6020 1.2.4.2 wiz mov.l %d1, %d0 # move new G,R,S to %d0
6021 1.2.4.2 wiz bra.b case2_end
6022 1.2.4.2 wiz
6023 1.2.4.2 wiz case2_set_sticky:
6024 1.2.4.2 wiz mov.l %d1, %d0 # move new G,R,S to %d0
6025 1.2.4.2 wiz bset &rnd_stky_bit, %d0 # set sticky bit
6026 1.2.4.2 wiz
6027 1.2.4.2 wiz case2_end:
6028 1.2.4.2 wiz clr.l FTEMP_HI(%a0) # store FTEMP_HI = 0
6029 1.2.4.2 wiz mov.l %d2, FTEMP_LO(%a0) # store FTEMP_LO
6030 1.2.4.2 wiz and.l &0xe0000000, %d0 # clear all but G,R,S
6031 1.2.4.2 wiz
6032 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore temp register
6033 1.2.4.2 wiz rts
6034 1.2.4.2 wiz
6035 1.2.4.2 wiz #
6036 1.2.4.2 wiz # case (d1>=64)
6037 1.2.4.2 wiz #
6038 1.2.4.2 wiz # %d0 = denorm threshold
6039 1.2.4.2 wiz # %d1 = amt to shift
6040 1.2.4.2 wiz #
6041 1.2.4.2 wiz case_3:
6042 1.2.4.2 wiz mov.w %d0, FTEMP_EX(%a0) # insert denorm threshold
6043 1.2.4.2 wiz
6044 1.2.4.2 wiz cmpi.w %d1, &65 # is shift amt > 65?
6045 1.2.4.2 wiz blt.b case3_64 # no; it's == 64
6046 1.2.4.2 wiz beq.b case3_65 # no; it's == 65
6047 1.2.4.2 wiz
6048 1.2.4.2 wiz #
6049 1.2.4.2 wiz # case (d1>65)
6050 1.2.4.2 wiz #
6051 1.2.4.2 wiz # Shift value is > 65 and out of range. All bits are shifted off.
6052 1.2.4.2 wiz # Return a zero mantissa with the sticky bit set
6053 1.2.4.2 wiz #
6054 1.2.4.2 wiz clr.l FTEMP_HI(%a0) # clear hi(mantissa)
6055 1.2.4.2 wiz clr.l FTEMP_LO(%a0) # clear lo(mantissa)
6056 1.2.4.2 wiz mov.l &0x20000000, %d0 # set sticky bit
6057 1.2.4.2 wiz rts
6058 1.2.4.2 wiz
6059 1.2.4.2 wiz #
6060 1.2.4.2 wiz # case (d1 == 64)
6061 1.2.4.2 wiz #
6062 1.2.4.2 wiz # ---------------------------------------------------------
6063 1.2.4.2 wiz # | FTEMP_HI | FTEMP_LO |grs000.........000|
6064 1.2.4.2 wiz # ---------------------------------------------------------
6065 1.2.4.2 wiz # <-------(32)------>
6066 1.2.4.2 wiz # \ \
6067 1.2.4.2 wiz # \ \
6068 1.2.4.2 wiz # \ \
6069 1.2.4.2 wiz # \ ------------------------------
6070 1.2.4.2 wiz # ------------------------------- \
6071 1.2.4.2 wiz # \ \
6072 1.2.4.2 wiz # \ \
6073 1.2.4.2 wiz # \ \
6074 1.2.4.2 wiz # <-------(32)------>
6075 1.2.4.2 wiz # ---------------------------------------------------------
6076 1.2.4.2 wiz # |0...............0|0................0|grs |
6077 1.2.4.2 wiz # ---------------------------------------------------------
6078 1.2.4.2 wiz #
6079 1.2.4.2 wiz case3_64:
6080 1.2.4.2 wiz mov.l FTEMP_HI(%a0), %d0 # fetch hi(mantissa)
6081 1.2.4.2 wiz mov.l %d0, %d1 # make a copy
6082 1.2.4.2 wiz and.l &0xc0000000, %d0 # extract G,R
6083 1.2.4.2 wiz and.l &0x3fffffff, %d1 # extract other bits
6084 1.2.4.2 wiz
6085 1.2.4.2 wiz bra.b case3_complete
6086 1.2.4.2 wiz
6087 1.2.4.2 wiz #
6088 1.2.4.2 wiz # case (d1 == 65)
6089 1.2.4.2 wiz #
6090 1.2.4.2 wiz # ---------------------------------------------------------
6091 1.2.4.2 wiz # | FTEMP_HI | FTEMP_LO |grs000.........000|
6092 1.2.4.2 wiz # ---------------------------------------------------------
6093 1.2.4.2 wiz # <-------(32)------>
6094 1.2.4.2 wiz # \ \
6095 1.2.4.2 wiz # \ \
6096 1.2.4.2 wiz # \ \
6097 1.2.4.2 wiz # \ ------------------------------
6098 1.2.4.2 wiz # -------------------------------- \
6099 1.2.4.2 wiz # \ \
6100 1.2.4.2 wiz # \ \
6101 1.2.4.2 wiz # \ \
6102 1.2.4.2 wiz # <-------(31)----->
6103 1.2.4.2 wiz # ---------------------------------------------------------
6104 1.2.4.2 wiz # |0...............0|0................0|0rs |
6105 1.2.4.2 wiz # ---------------------------------------------------------
6106 1.2.4.2 wiz #
6107 1.2.4.2 wiz case3_65:
6108 1.2.4.2 wiz mov.l FTEMP_HI(%a0), %d0 # fetch hi(mantissa)
6109 1.2.4.2 wiz and.l &0x80000000, %d0 # extract R bit
6110 1.2.4.2 wiz lsr.l &0x1, %d0 # shift high bit into R bit
6111 1.2.4.2 wiz and.l &0x7fffffff, %d1 # extract other bits
6112 1.2.4.2 wiz
6113 1.2.4.2 wiz case3_complete:
6114 1.2.4.2 wiz # last operation done was an "and" of the bits shifted off so the condition
6115 1.2.4.2 wiz # codes are already set so branch accordingly.
6116 1.2.4.2 wiz bne.b case3_set_sticky # yes; go set new sticky
6117 1.2.4.2 wiz tst.l FTEMP_LO(%a0) # were any bits shifted off?
6118 1.2.4.2 wiz bne.b case3_set_sticky # yes; go set new sticky
6119 1.2.4.2 wiz tst.b GRS(%a6) # were any bits shifted off?
6120 1.2.4.2 wiz bne.b case3_set_sticky # yes; go set new sticky
6121 1.2.4.2 wiz
6122 1.2.4.2 wiz #
6123 1.2.4.2 wiz # no bits were shifted off so don't set the sticky bit.
6124 1.2.4.2 wiz # the guard and
6125 1.2.4.2 wiz # the entire mantissa is zero.
6126 1.2.4.2 wiz #
6127 1.2.4.2 wiz clr.l FTEMP_HI(%a0) # clear hi(mantissa)
6128 1.2.4.2 wiz clr.l FTEMP_LO(%a0) # clear lo(mantissa)
6129 1.2.4.2 wiz rts
6130 1.2.4.2 wiz
6131 1.2.4.2 wiz #
6132 1.2.4.2 wiz # some bits were shifted off so set the sticky bit.
6133 1.2.4.2 wiz # the entire mantissa is zero.
6134 1.2.4.2 wiz #
6135 1.2.4.2 wiz case3_set_sticky:
6136 1.2.4.2 wiz bset &rnd_stky_bit,%d0 # set new sticky bit
6137 1.2.4.2 wiz clr.l FTEMP_HI(%a0) # clear hi(mantissa)
6138 1.2.4.2 wiz clr.l FTEMP_LO(%a0) # clear lo(mantissa)
6139 1.2.4.2 wiz rts
6140 1.2.4.2 wiz
6141 1.2.4.2 wiz #########################################################################
6142 1.2.4.2 wiz # XDEF **************************************************************** #
6143 1.2.4.2 wiz # _round(): round result according to precision/mode #
6144 1.2.4.2 wiz # #
6145 1.2.4.2 wiz # XREF **************************************************************** #
6146 1.2.4.2 wiz # None #
6147 1.2.4.2 wiz # #
6148 1.2.4.2 wiz # INPUT *************************************************************** #
6149 1.2.4.2 wiz # a0 = ptr to input operand in internal extended format #
6150 1.2.4.2 wiz # d1(hi) = contains rounding precision: #
6151 1.2.4.2 wiz # ext = $0000xxxx #
6152 1.2.4.2 wiz # sgl = $0004xxxx #
6153 1.2.4.2 wiz # dbl = $0008xxxx #
6154 1.2.4.2 wiz # d1(lo) = contains rounding mode: #
6155 1.2.4.2 wiz # RN = $xxxx0000 #
6156 1.2.4.2 wiz # RZ = $xxxx0001 #
6157 1.2.4.2 wiz # RM = $xxxx0002 #
6158 1.2.4.2 wiz # RP = $xxxx0003 #
6159 1.2.4.2 wiz # d0{31:29} = contains the g,r,s bits (extended) #
6160 1.2.4.2 wiz # #
6161 1.2.4.2 wiz # OUTPUT ************************************************************** #
6162 1.2.4.2 wiz # a0 = pointer to rounded result #
6163 1.2.4.2 wiz # #
6164 1.2.4.2 wiz # ALGORITHM *********************************************************** #
6165 1.2.4.2 wiz # On return the value pointed to by a0 is correctly rounded, #
6166 1.2.4.2 wiz # a0 is preserved and the g-r-s bits in d0 are cleared. #
6167 1.2.4.2 wiz # The result is not typed - the tag field is invalid. The #
6168 1.2.4.2 wiz # result is still in the internal extended format. #
6169 1.2.4.2 wiz # #
6170 1.2.4.2 wiz # The INEX bit of USER_FPSR will be set if the rounded result was #
6171 1.2.4.2 wiz # inexact (i.e. if any of the g-r-s bits were set). #
6172 1.2.4.2 wiz # #
6173 1.2.4.2 wiz #########################################################################
6174 1.2.4.2 wiz
6175 1.2.4.2 wiz global _round
6176 1.2.4.2 wiz _round:
6177 1.2.4.2 wiz #
6178 1.2.4.2 wiz # ext_grs() looks at the rounding precision and sets the appropriate
6179 1.2.4.2 wiz # G,R,S bits.
6180 1.2.4.2 wiz # If (G,R,S == 0) then result is exact and round is done, else set
6181 1.2.4.2 wiz # the inex flag in status reg and continue.
6182 1.2.4.2 wiz #
6183 1.2.4.2 wiz bsr.l ext_grs # extract G,R,S
6184 1.2.4.2 wiz
6185 1.2.4.2 wiz tst.l %d0 # are G,R,S zero?
6186 1.2.4.2 wiz beq.w truncate # yes; round is complete
6187 1.2.4.2 wiz
6188 1.2.4.2 wiz or.w &inx2a_mask, 2+USER_FPSR(%a6) # set inex2/ainex
6189 1.2.4.2 wiz
6190 1.2.4.2 wiz #
6191 1.2.4.2 wiz # Use rounding mode as an index into a jump table for these modes.
6192 1.2.4.2 wiz # All of the following assumes grs != 0.
6193 1.2.4.2 wiz #
6194 1.2.4.2 wiz mov.w (tbl_mode.b,%pc,%d1.w*2), %a1 # load jump offset
6195 1.2.4.2 wiz jmp (tbl_mode.b,%pc,%a1) # jmp to rnd mode handler
6196 1.2.4.2 wiz
6197 1.2.4.2 wiz tbl_mode:
6198 1.2.4.2 wiz short rnd_near - tbl_mode
6199 1.2.4.2 wiz short truncate - tbl_mode # RZ always truncates
6200 1.2.4.2 wiz short rnd_mnus - tbl_mode
6201 1.2.4.2 wiz short rnd_plus - tbl_mode
6202 1.2.4.2 wiz
6203 1.2.4.2 wiz #################################################################
6204 1.2.4.2 wiz # ROUND PLUS INFINITY #
6205 1.2.4.2 wiz # #
6206 1.2.4.2 wiz # If sign of fp number = 0 (positive), then add 1 to l. #
6207 1.2.4.2 wiz #################################################################
6208 1.2.4.2 wiz rnd_plus:
6209 1.2.4.2 wiz tst.b FTEMP_SGN(%a0) # check for sign
6210 1.2.4.2 wiz bmi.w truncate # if positive then truncate
6211 1.2.4.2 wiz
6212 1.2.4.2 wiz mov.l &0xffffffff, %d0 # force g,r,s to be all f's
6213 1.2.4.2 wiz swap %d1 # set up d1 for round prec.
6214 1.2.4.2 wiz
6215 1.2.4.2 wiz cmpi.b %d1, &s_mode # is prec = sgl?
6216 1.2.4.2 wiz beq.w add_sgl # yes
6217 1.2.4.2 wiz bgt.w add_dbl # no; it's dbl
6218 1.2.4.2 wiz bra.w add_ext # no; it's ext
6219 1.2.4.2 wiz
6220 1.2.4.2 wiz #################################################################
6221 1.2.4.2 wiz # ROUND MINUS INFINITY #
6222 1.2.4.2 wiz # #
6223 1.2.4.2 wiz # If sign of fp number = 1 (negative), then add 1 to l. #
6224 1.2.4.2 wiz #################################################################
6225 1.2.4.2 wiz rnd_mnus:
6226 1.2.4.2 wiz tst.b FTEMP_SGN(%a0) # check for sign
6227 1.2.4.2 wiz bpl.w truncate # if negative then truncate
6228 1.2.4.2 wiz
6229 1.2.4.2 wiz mov.l &0xffffffff, %d0 # force g,r,s to be all f's
6230 1.2.4.2 wiz swap %d1 # set up d1 for round prec.
6231 1.2.4.2 wiz
6232 1.2.4.2 wiz cmpi.b %d1, &s_mode # is prec = sgl?
6233 1.2.4.2 wiz beq.w add_sgl # yes
6234 1.2.4.2 wiz bgt.w add_dbl # no; it's dbl
6235 1.2.4.2 wiz bra.w add_ext # no; it's ext
6236 1.2.4.2 wiz
6237 1.2.4.2 wiz #################################################################
6238 1.2.4.2 wiz # ROUND NEAREST #
6239 1.2.4.2 wiz # #
6240 1.2.4.2 wiz # If (g=1), then add 1 to l and if (r=s=0), then clear l #
6241 1.2.4.2 wiz # Note that this will round to even in case of a tie. #
6242 1.2.4.2 wiz #################################################################
6243 1.2.4.2 wiz rnd_near:
6244 1.2.4.2 wiz asl.l &0x1, %d0 # shift g-bit to c-bit
6245 1.2.4.2 wiz bcc.w truncate # if (g=1) then
6246 1.2.4.2 wiz
6247 1.2.4.2 wiz swap %d1 # set up d1 for round prec.
6248 1.2.4.2 wiz
6249 1.2.4.2 wiz cmpi.b %d1, &s_mode # is prec = sgl?
6250 1.2.4.2 wiz beq.w add_sgl # yes
6251 1.2.4.2 wiz bgt.w add_dbl # no; it's dbl
6252 1.2.4.2 wiz bra.w add_ext # no; it's ext
6253 1.2.4.2 wiz
6254 1.2.4.2 wiz # *** LOCAL EQUATES ***
6255 1.2.4.2 wiz set ad_1_sgl, 0x00000100 # constant to add 1 to l-bit in sgl prec
6256 1.2.4.2 wiz set ad_1_dbl, 0x00000800 # constant to add 1 to l-bit in dbl prec
6257 1.2.4.2 wiz
6258 1.2.4.2 wiz #########################
6259 1.2.4.2 wiz # ADD SINGLE #
6260 1.2.4.2 wiz #########################
6261 1.2.4.2 wiz add_sgl:
6262 1.2.4.2 wiz add.l &ad_1_sgl, FTEMP_HI(%a0)
6263 1.2.4.2 wiz bcc.b scc_clr # no mantissa overflow
6264 1.2.4.2 wiz roxr.w FTEMP_HI(%a0) # shift v-bit back in
6265 1.2.4.2 wiz roxr.w FTEMP_HI+2(%a0) # shift v-bit back in
6266 1.2.4.2 wiz add.w &0x1, FTEMP_EX(%a0) # and incr exponent
6267 1.2.4.2 wiz scc_clr:
6268 1.2.4.2 wiz tst.l %d0 # test for rs = 0
6269 1.2.4.2 wiz bne.b sgl_done
6270 1.2.4.2 wiz and.w &0xfe00, FTEMP_HI+2(%a0) # clear the l-bit
6271 1.2.4.2 wiz sgl_done:
6272 1.2.4.2 wiz and.l &0xffffff00, FTEMP_HI(%a0) # truncate bits beyond sgl limit
6273 1.2.4.2 wiz clr.l FTEMP_LO(%a0) # clear d2
6274 1.2.4.2 wiz rts
6275 1.2.4.2 wiz
6276 1.2.4.2 wiz #########################
6277 1.2.4.2 wiz # ADD EXTENDED #
6278 1.2.4.2 wiz #########################
6279 1.2.4.2 wiz add_ext:
6280 1.2.4.2 wiz addq.l &1,FTEMP_LO(%a0) # add 1 to l-bit
6281 1.2.4.2 wiz bcc.b xcc_clr # test for carry out
6282 1.2.4.2 wiz addq.l &1,FTEMP_HI(%a0) # propogate carry
6283 1.2.4.2 wiz bcc.b xcc_clr
6284 1.2.4.2 wiz roxr.w FTEMP_HI(%a0) # mant is 0 so restore v-bit
6285 1.2.4.2 wiz roxr.w FTEMP_HI+2(%a0) # mant is 0 so restore v-bit
6286 1.2.4.2 wiz roxr.w FTEMP_LO(%a0)
6287 1.2.4.2 wiz roxr.w FTEMP_LO+2(%a0)
6288 1.2.4.2 wiz add.w &0x1,FTEMP_EX(%a0) # and inc exp
6289 1.2.4.2 wiz xcc_clr:
6290 1.2.4.2 wiz tst.l %d0 # test rs = 0
6291 1.2.4.2 wiz bne.b add_ext_done
6292 1.2.4.2 wiz and.b &0xfe,FTEMP_LO+3(%a0) # clear the l bit
6293 1.2.4.2 wiz add_ext_done:
6294 1.2.4.2 wiz rts
6295 1.2.4.2 wiz
6296 1.2.4.2 wiz #########################
6297 1.2.4.2 wiz # ADD DOUBLE #
6298 1.2.4.2 wiz #########################
6299 1.2.4.2 wiz add_dbl:
6300 1.2.4.2 wiz add.l &ad_1_dbl, FTEMP_LO(%a0) # add 1 to lsb
6301 1.2.4.2 wiz bcc.b dcc_clr # no carry
6302 1.2.4.2 wiz addq.l &0x1, FTEMP_HI(%a0) # propogate carry
6303 1.2.4.2 wiz bcc.b dcc_clr # no carry
6304 1.2.4.2 wiz
6305 1.2.4.2 wiz roxr.w FTEMP_HI(%a0) # mant is 0 so restore v-bit
6306 1.2.4.2 wiz roxr.w FTEMP_HI+2(%a0) # mant is 0 so restore v-bit
6307 1.2.4.2 wiz roxr.w FTEMP_LO(%a0)
6308 1.2.4.2 wiz roxr.w FTEMP_LO+2(%a0)
6309 1.2.4.2 wiz addq.w &0x1, FTEMP_EX(%a0) # incr exponent
6310 1.2.4.2 wiz dcc_clr:
6311 1.2.4.2 wiz tst.l %d0 # test for rs = 0
6312 1.2.4.2 wiz bne.b dbl_done
6313 1.2.4.2 wiz and.w &0xf000, FTEMP_LO+2(%a0) # clear the l-bit
6314 1.2.4.2 wiz
6315 1.2.4.2 wiz dbl_done:
6316 1.2.4.2 wiz and.l &0xfffff800,FTEMP_LO(%a0) # truncate bits beyond dbl limit
6317 1.2.4.2 wiz rts
6318 1.2.4.2 wiz
6319 1.2.4.2 wiz ###########################
6320 1.2.4.2 wiz # Truncate all other bits #
6321 1.2.4.2 wiz ###########################
6322 1.2.4.2 wiz truncate:
6323 1.2.4.2 wiz swap %d1 # select rnd prec
6324 1.2.4.2 wiz
6325 1.2.4.2 wiz cmpi.b %d1, &s_mode # is prec sgl?
6326 1.2.4.2 wiz beq.w sgl_done # yes
6327 1.2.4.2 wiz bgt.b dbl_done # no; it's dbl
6328 1.2.4.2 wiz rts # no; it's ext
6329 1.2.4.2 wiz
6330 1.2.4.2 wiz
6331 1.2.4.2 wiz #
6332 1.2.4.2 wiz # ext_grs(): extract guard, round and sticky bits according to
6333 1.2.4.2 wiz # rounding precision.
6334 1.2.4.2 wiz #
6335 1.2.4.2 wiz # INPUT
6336 1.2.4.2 wiz # d0 = extended precision g,r,s (in d0{31:29})
6337 1.2.4.2 wiz # d1 = {PREC,ROUND}
6338 1.2.4.2 wiz # OUTPUT
6339 1.2.4.2 wiz # d0{31:29} = guard, round, sticky
6340 1.2.4.2 wiz #
6341 1.2.4.2 wiz # The ext_grs extract the guard/round/sticky bits according to the
6342 1.2.4.2 wiz # selected rounding precision. It is called by the round subroutine
6343 1.2.4.2 wiz # only. All registers except d0 are kept intact. d0 becomes an
6344 1.2.4.2 wiz # updated guard,round,sticky in d0{31:29}
6345 1.2.4.2 wiz #
6346 1.2.4.2 wiz # Notes: the ext_grs uses the round PREC, and therefore has to swap d1
6347 1.2.4.2 wiz # prior to usage, and needs to restore d1 to original. this
6348 1.2.4.2 wiz # routine is tightly tied to the round routine and not meant to
6349 1.2.4.2 wiz # uphold standard subroutine calling practices.
6350 1.2.4.2 wiz #
6351 1.2.4.2 wiz
6352 1.2.4.2 wiz ext_grs:
6353 1.2.4.2 wiz swap %d1 # have d1.w point to round precision
6354 1.2.4.2 wiz tst.b %d1 # is rnd prec = extended?
6355 1.2.4.2 wiz bne.b ext_grs_not_ext # no; go handle sgl or dbl
6356 1.2.4.2 wiz
6357 1.2.4.2 wiz #
6358 1.2.4.2 wiz # %d0 actually already hold g,r,s since _round() had it before calling
6359 1.2.4.2 wiz # this function. so, as long as we don't disturb it, we are "returning" it.
6360 1.2.4.2 wiz #
6361 1.2.4.2 wiz ext_grs_ext:
6362 1.2.4.2 wiz swap %d1 # yes; return to correct positions
6363 1.2.4.2 wiz rts
6364 1.2.4.2 wiz
6365 1.2.4.2 wiz ext_grs_not_ext:
6366 1.2.4.2 wiz movm.l &0x3000, -(%sp) # make some temp registers {d2/d3}
6367 1.2.4.2 wiz
6368 1.2.4.2 wiz cmpi.b %d1, &s_mode # is rnd prec = sgl?
6369 1.2.4.2 wiz bne.b ext_grs_dbl # no; go handle dbl
6370 1.2.4.2 wiz
6371 1.2.4.2 wiz #
6372 1.2.4.2 wiz # sgl:
6373 1.2.4.2 wiz # 96 64 40 32 0
6374 1.2.4.2 wiz # -----------------------------------------------------
6375 1.2.4.2 wiz # | EXP |XXXXXXX| |xx | |grs|
6376 1.2.4.2 wiz # -----------------------------------------------------
6377 1.2.4.2 wiz # <--(24)--->nn\ /
6378 1.2.4.2 wiz # ee ---------------------
6379 1.2.4.2 wiz # ww |
6380 1.2.4.2 wiz # v
6381 1.2.4.2 wiz # gr new sticky
6382 1.2.4.2 wiz #
6383 1.2.4.2 wiz ext_grs_sgl:
6384 1.2.4.2 wiz bfextu FTEMP_HI(%a0){&24:&2}, %d3 # sgl prec. g-r are 2 bits right
6385 1.2.4.2 wiz mov.l &30, %d2 # of the sgl prec. limits
6386 1.2.4.2 wiz lsl.l %d2, %d3 # shift g-r bits to MSB of d3
6387 1.2.4.2 wiz mov.l FTEMP_HI(%a0), %d2 # get word 2 for s-bit test
6388 1.2.4.2 wiz and.l &0x0000003f, %d2 # s bit is the or of all other
6389 1.2.4.2 wiz bne.b ext_grs_st_stky # bits to the right of g-r
6390 1.2.4.2 wiz tst.l FTEMP_LO(%a0) # test lower mantissa
6391 1.2.4.2 wiz bne.b ext_grs_st_stky # if any are set, set sticky
6392 1.2.4.2 wiz tst.l %d0 # test original g,r,s
6393 1.2.4.2 wiz bne.b ext_grs_st_stky # if any are set, set sticky
6394 1.2.4.2 wiz bra.b ext_grs_end_sd # if words 3 and 4 are clr, exit
6395 1.2.4.2 wiz
6396 1.2.4.2 wiz #
6397 1.2.4.2 wiz # dbl:
6398 1.2.4.2 wiz # 96 64 32 11 0
6399 1.2.4.2 wiz # -----------------------------------------------------
6400 1.2.4.2 wiz # | EXP |XXXXXXX| | |xx |grs|
6401 1.2.4.2 wiz # -----------------------------------------------------
6402 1.2.4.2 wiz # nn\ /
6403 1.2.4.2 wiz # ee -------
6404 1.2.4.2 wiz # ww |
6405 1.2.4.2 wiz # v
6406 1.2.4.2 wiz # gr new sticky
6407 1.2.4.2 wiz #
6408 1.2.4.2 wiz ext_grs_dbl:
6409 1.2.4.2 wiz bfextu FTEMP_LO(%a0){&21:&2}, %d3 # dbl-prec. g-r are 2 bits right
6410 1.2.4.2 wiz mov.l &30, %d2 # of the dbl prec. limits
6411 1.2.4.2 wiz lsl.l %d2, %d3 # shift g-r bits to the MSB of d3
6412 1.2.4.2 wiz mov.l FTEMP_LO(%a0), %d2 # get lower mantissa for s-bit test
6413 1.2.4.2 wiz and.l &0x000001ff, %d2 # s bit is the or-ing of all
6414 1.2.4.2 wiz bne.b ext_grs_st_stky # other bits to the right of g-r
6415 1.2.4.2 wiz tst.l %d0 # test word original g,r,s
6416 1.2.4.2 wiz bne.b ext_grs_st_stky # if any are set, set sticky
6417 1.2.4.2 wiz bra.b ext_grs_end_sd # if clear, exit
6418 1.2.4.2 wiz
6419 1.2.4.2 wiz ext_grs_st_stky:
6420 1.2.4.2 wiz bset &rnd_stky_bit, %d3 # set sticky bit
6421 1.2.4.2 wiz ext_grs_end_sd:
6422 1.2.4.2 wiz mov.l %d3, %d0 # return grs to d0
6423 1.2.4.2 wiz
6424 1.2.4.2 wiz movm.l (%sp)+, &0xc # restore scratch registers {d2/d3}
6425 1.2.4.2 wiz
6426 1.2.4.2 wiz swap %d1 # restore d1 to original
6427 1.2.4.2 wiz rts
6428 1.2.4.2 wiz
6429 1.2.4.2 wiz #########################################################################
6430 1.2.4.2 wiz # norm(): normalize the mantissa of an extended precision input. the #
6431 1.2.4.2 wiz # input operand should not be normalized already. #
6432 1.2.4.2 wiz # #
6433 1.2.4.2 wiz # XDEF **************************************************************** #
6434 1.2.4.2 wiz # norm() #
6435 1.2.4.2 wiz # #
6436 1.2.4.2 wiz # XREF **************************************************************** #
6437 1.2.4.2 wiz # none #
6438 1.2.4.2 wiz # #
6439 1.2.4.2 wiz # INPUT *************************************************************** #
6440 1.2.4.2 wiz # a0 = pointer fp extended precision operand to normalize #
6441 1.2.4.2 wiz # #
6442 1.2.4.2 wiz # OUTPUT ************************************************************** #
6443 1.2.4.2 wiz # d0 = number of bit positions the mantissa was shifted #
6444 1.2.4.2 wiz # a0 = the input operand's mantissa is normalized; the exponent #
6445 1.2.4.2 wiz # is unchanged. #
6446 1.2.4.2 wiz # #
6447 1.2.4.2 wiz #########################################################################
6448 1.2.4.2 wiz global norm
6449 1.2.4.2 wiz norm:
6450 1.2.4.2 wiz mov.l %d2, -(%sp) # create some temp regs
6451 1.2.4.2 wiz mov.l %d3, -(%sp)
6452 1.2.4.2 wiz
6453 1.2.4.2 wiz mov.l FTEMP_HI(%a0), %d0 # load hi(mantissa)
6454 1.2.4.2 wiz mov.l FTEMP_LO(%a0), %d1 # load lo(mantissa)
6455 1.2.4.2 wiz
6456 1.2.4.2 wiz bfffo %d0{&0:&32}, %d2 # how many places to shift?
6457 1.2.4.2 wiz beq.b norm_lo # hi(man) is all zeroes!
6458 1.2.4.2 wiz
6459 1.2.4.2 wiz norm_hi:
6460 1.2.4.2 wiz lsl.l %d2, %d0 # left shift hi(man)
6461 1.2.4.2 wiz bfextu %d1{&0:%d2}, %d3 # extract lo bits
6462 1.2.4.2 wiz
6463 1.2.4.2 wiz or.l %d3, %d0 # create hi(man)
6464 1.2.4.2 wiz lsl.l %d2, %d1 # create lo(man)
6465 1.2.4.2 wiz
6466 1.2.4.2 wiz mov.l %d0, FTEMP_HI(%a0) # store new hi(man)
6467 1.2.4.2 wiz mov.l %d1, FTEMP_LO(%a0) # store new lo(man)
6468 1.2.4.2 wiz
6469 1.2.4.2 wiz mov.l %d2, %d0 # return shift amount
6470 1.2.4.2 wiz
6471 1.2.4.2 wiz mov.l (%sp)+, %d3 # restore temp regs
6472 1.2.4.2 wiz mov.l (%sp)+, %d2
6473 1.2.4.2 wiz
6474 1.2.4.2 wiz rts
6475 1.2.4.2 wiz
6476 1.2.4.2 wiz norm_lo:
6477 1.2.4.2 wiz bfffo %d1{&0:&32}, %d2 # how many places to shift?
6478 1.2.4.2 wiz lsl.l %d2, %d1 # shift lo(man)
6479 1.2.4.2 wiz add.l &32, %d2 # add 32 to shft amount
6480 1.2.4.2 wiz
6481 1.2.4.2 wiz mov.l %d1, FTEMP_HI(%a0) # store hi(man)
6482 1.2.4.2 wiz clr.l FTEMP_LO(%a0) # lo(man) is now zero
6483 1.2.4.2 wiz
6484 1.2.4.2 wiz mov.l %d2, %d0 # return shift amount
6485 1.2.4.2 wiz
6486 1.2.4.2 wiz mov.l (%sp)+, %d3 # restore temp regs
6487 1.2.4.2 wiz mov.l (%sp)+, %d2
6488 1.2.4.2 wiz
6489 1.2.4.2 wiz rts
6490 1.2.4.2 wiz
6491 1.2.4.2 wiz #########################################################################
6492 1.2.4.2 wiz # unnorm_fix(): - changes an UNNORM to one of NORM, DENORM, or ZERO #
6493 1.2.4.2 wiz # - returns corresponding optype tag #
6494 1.2.4.2 wiz # #
6495 1.2.4.2 wiz # XDEF **************************************************************** #
6496 1.2.4.2 wiz # unnorm_fix() #
6497 1.2.4.2 wiz # #
6498 1.2.4.2 wiz # XREF **************************************************************** #
6499 1.2.4.2 wiz # norm() - normalize the mantissa #
6500 1.2.4.2 wiz # #
6501 1.2.4.2 wiz # INPUT *************************************************************** #
6502 1.2.4.2 wiz # a0 = pointer to unnormalized extended precision number #
6503 1.2.4.2 wiz # #
6504 1.2.4.2 wiz # OUTPUT ************************************************************** #
6505 1.2.4.2 wiz # d0 = optype tag - is corrected to one of NORM, DENORM, or ZERO #
6506 1.2.4.2 wiz # a0 = input operand has been converted to a norm, denorm, or #
6507 1.2.4.2 wiz # zero; both the exponent and mantissa are changed. #
6508 1.2.4.2 wiz # #
6509 1.2.4.2 wiz #########################################################################
6510 1.2.4.2 wiz
6511 1.2.4.2 wiz global unnorm_fix
6512 1.2.4.2 wiz unnorm_fix:
6513 1.2.4.2 wiz bfffo FTEMP_HI(%a0){&0:&32}, %d0 # how many shifts are needed?
6514 1.2.4.2 wiz bne.b unnorm_shift # hi(man) is not all zeroes
6515 1.2.4.2 wiz
6516 1.2.4.2 wiz #
6517 1.2.4.2 wiz # hi(man) is all zeroes so see if any bits in lo(man) are set
6518 1.2.4.2 wiz #
6519 1.2.4.2 wiz unnorm_chk_lo:
6520 1.2.4.2 wiz bfffo FTEMP_LO(%a0){&0:&32}, %d0 # is operand really a zero?
6521 1.2.4.2 wiz beq.w unnorm_zero # yes
6522 1.2.4.2 wiz
6523 1.2.4.2 wiz add.w &32, %d0 # no; fix shift distance
6524 1.2.4.2 wiz
6525 1.2.4.2 wiz #
6526 1.2.4.2 wiz # d0 = # shifts needed for complete normalization
6527 1.2.4.2 wiz #
6528 1.2.4.2 wiz unnorm_shift:
6529 1.2.4.2 wiz clr.l %d1 # clear top word
6530 1.2.4.2 wiz mov.w FTEMP_EX(%a0), %d1 # extract exponent
6531 1.2.4.2 wiz and.w &0x7fff, %d1 # strip off sgn
6532 1.2.4.2 wiz
6533 1.2.4.2 wiz cmp.w %d0, %d1 # will denorm push exp < 0?
6534 1.2.4.2 wiz bgt.b unnorm_nrm_zero # yes; denorm only until exp = 0
6535 1.2.4.2 wiz
6536 1.2.4.2 wiz #
6537 1.2.4.2 wiz # exponent would not go < 0. therefore, number stays normalized
6538 1.2.4.2 wiz #
6539 1.2.4.2 wiz sub.w %d0, %d1 # shift exponent value
6540 1.2.4.2 wiz mov.w FTEMP_EX(%a0), %d0 # load old exponent
6541 1.2.4.2 wiz and.w &0x8000, %d0 # save old sign
6542 1.2.4.2 wiz or.w %d0, %d1 # {sgn,new exp}
6543 1.2.4.2 wiz mov.w %d1, FTEMP_EX(%a0) # insert new exponent
6544 1.2.4.2 wiz
6545 1.2.4.2 wiz bsr.l norm # normalize UNNORM
6546 1.2.4.2 wiz
6547 1.2.4.2 wiz mov.b &NORM, %d0 # return new optype tag
6548 1.2.4.2 wiz rts
6549 1.2.4.2 wiz
6550 1.2.4.2 wiz #
6551 1.2.4.2 wiz # exponent would go < 0, so only denormalize until exp = 0
6552 1.2.4.2 wiz #
6553 1.2.4.2 wiz unnorm_nrm_zero:
6554 1.2.4.2 wiz cmp.b %d1, &32 # is exp <= 32?
6555 1.2.4.2 wiz bgt.b unnorm_nrm_zero_lrg # no; go handle large exponent
6556 1.2.4.2 wiz
6557 1.2.4.2 wiz bfextu FTEMP_HI(%a0){%d1:&32}, %d0 # extract new hi(man)
6558 1.2.4.2 wiz mov.l %d0, FTEMP_HI(%a0) # save new hi(man)
6559 1.2.4.2 wiz
6560 1.2.4.2 wiz mov.l FTEMP_LO(%a0), %d0 # fetch old lo(man)
6561 1.2.4.2 wiz lsl.l %d1, %d0 # extract new lo(man)
6562 1.2.4.2 wiz mov.l %d0, FTEMP_LO(%a0) # save new lo(man)
6563 1.2.4.2 wiz
6564 1.2.4.2 wiz and.w &0x8000, FTEMP_EX(%a0) # set exp = 0
6565 1.2.4.2 wiz
6566 1.2.4.2 wiz mov.b &DENORM, %d0 # return new optype tag
6567 1.2.4.2 wiz rts
6568 1.2.4.2 wiz
6569 1.2.4.2 wiz #
6570 1.2.4.2 wiz # only mantissa bits set are in lo(man)
6571 1.2.4.2 wiz #
6572 1.2.4.2 wiz unnorm_nrm_zero_lrg:
6573 1.2.4.2 wiz sub.w &32, %d1 # adjust shft amt by 32
6574 1.2.4.2 wiz
6575 1.2.4.2 wiz mov.l FTEMP_LO(%a0), %d0 # fetch old lo(man)
6576 1.2.4.2 wiz lsl.l %d1, %d0 # left shift lo(man)
6577 1.2.4.2 wiz
6578 1.2.4.2 wiz mov.l %d0, FTEMP_HI(%a0) # store new hi(man)
6579 1.2.4.2 wiz clr.l FTEMP_LO(%a0) # lo(man) = 0
6580 1.2.4.2 wiz
6581 1.2.4.2 wiz and.w &0x8000, FTEMP_EX(%a0) # set exp = 0
6582 1.2.4.2 wiz
6583 1.2.4.2 wiz mov.b &DENORM, %d0 # return new optype tag
6584 1.2.4.2 wiz rts
6585 1.2.4.2 wiz
6586 1.2.4.2 wiz #
6587 1.2.4.2 wiz # whole mantissa is zero so this UNNORM is actually a zero
6588 1.2.4.2 wiz #
6589 1.2.4.2 wiz unnorm_zero:
6590 1.2.4.2 wiz and.w &0x8000, FTEMP_EX(%a0) # force exponent to zero
6591 1.2.4.2 wiz
6592 1.2.4.2 wiz mov.b &ZERO, %d0 # fix optype tag
6593 1.2.4.2 wiz rts
6594 1.2.4.2 wiz
6595 1.2.4.2 wiz #########################################################################
6596 1.2.4.2 wiz # XDEF **************************************************************** #
6597 1.2.4.2 wiz # set_tag_x(): return the optype of the input ext fp number #
6598 1.2.4.2 wiz # #
6599 1.2.4.2 wiz # XREF **************************************************************** #
6600 1.2.4.2 wiz # None #
6601 1.2.4.2 wiz # #
6602 1.2.4.2 wiz # INPUT *************************************************************** #
6603 1.2.4.2 wiz # a0 = pointer to extended precision operand #
6604 1.2.4.2 wiz # #
6605 1.2.4.2 wiz # OUTPUT ************************************************************** #
6606 1.2.4.2 wiz # d0 = value of type tag #
6607 1.2.4.2 wiz # one of: NORM, INF, QNAN, SNAN, DENORM, UNNORM, ZERO #
6608 1.2.4.2 wiz # #
6609 1.2.4.2 wiz # ALGORITHM *********************************************************** #
6610 1.2.4.2 wiz # Simply test the exponent, j-bit, and mantissa values to #
6611 1.2.4.2 wiz # determine the type of operand. #
6612 1.2.4.2 wiz # If it's an unnormalized zero, alter the operand and force it #
6613 1.2.4.2 wiz # to be a normal zero. #
6614 1.2.4.2 wiz # #
6615 1.2.4.2 wiz #########################################################################
6616 1.2.4.2 wiz
6617 1.2.4.2 wiz global set_tag_x
6618 1.2.4.2 wiz set_tag_x:
6619 1.2.4.2 wiz mov.w FTEMP_EX(%a0), %d0 # extract exponent
6620 1.2.4.2 wiz andi.w &0x7fff, %d0 # strip off sign
6621 1.2.4.2 wiz cmpi.w %d0, &0x7fff # is (EXP == MAX)?
6622 1.2.4.2 wiz beq.b inf_or_nan_x
6623 1.2.4.2 wiz not_inf_or_nan_x:
6624 1.2.4.2 wiz btst &0x7,FTEMP_HI(%a0)
6625 1.2.4.2 wiz beq.b not_norm_x
6626 1.2.4.2 wiz is_norm_x:
6627 1.2.4.2 wiz mov.b &NORM, %d0
6628 1.2.4.2 wiz rts
6629 1.2.4.2 wiz not_norm_x:
6630 1.2.4.2 wiz tst.w %d0 # is exponent = 0?
6631 1.2.4.2 wiz bne.b is_unnorm_x
6632 1.2.4.2 wiz not_unnorm_x:
6633 1.2.4.2 wiz tst.l FTEMP_HI(%a0)
6634 1.2.4.2 wiz bne.b is_denorm_x
6635 1.2.4.2 wiz tst.l FTEMP_LO(%a0)
6636 1.2.4.2 wiz bne.b is_denorm_x
6637 1.2.4.2 wiz is_zero_x:
6638 1.2.4.2 wiz mov.b &ZERO, %d0
6639 1.2.4.2 wiz rts
6640 1.2.4.2 wiz is_denorm_x:
6641 1.2.4.2 wiz mov.b &DENORM, %d0
6642 1.2.4.2 wiz rts
6643 1.2.4.2 wiz # must distinguish now "Unnormalized zeroes" which we
6644 1.2.4.2 wiz # must convert to zero.
6645 1.2.4.2 wiz is_unnorm_x:
6646 1.2.4.2 wiz tst.l FTEMP_HI(%a0)
6647 1.2.4.2 wiz bne.b is_unnorm_reg_x
6648 1.2.4.2 wiz tst.l FTEMP_LO(%a0)
6649 1.2.4.2 wiz bne.b is_unnorm_reg_x
6650 1.2.4.2 wiz # it's an "unnormalized zero". let's convert it to an actual zero...
6651 1.2.4.2 wiz andi.w &0x8000,FTEMP_EX(%a0) # clear exponent
6652 1.2.4.2 wiz mov.b &ZERO, %d0
6653 1.2.4.2 wiz rts
6654 1.2.4.2 wiz is_unnorm_reg_x:
6655 1.2.4.2 wiz mov.b &UNNORM, %d0
6656 1.2.4.2 wiz rts
6657 1.2.4.2 wiz inf_or_nan_x:
6658 1.2.4.2 wiz tst.l FTEMP_LO(%a0)
6659 1.2.4.2 wiz bne.b is_nan_x
6660 1.2.4.2 wiz mov.l FTEMP_HI(%a0), %d0
6661 1.2.4.2 wiz and.l &0x7fffffff, %d0 # msb is a don't care!
6662 1.2.4.2 wiz bne.b is_nan_x
6663 1.2.4.2 wiz is_inf_x:
6664 1.2.4.2 wiz mov.b &INF, %d0
6665 1.2.4.2 wiz rts
6666 1.2.4.2 wiz is_nan_x:
6667 1.2.4.2 wiz btst &0x6, FTEMP_HI(%a0)
6668 1.2.4.2 wiz beq.b is_snan_x
6669 1.2.4.2 wiz mov.b &QNAN, %d0
6670 1.2.4.2 wiz rts
6671 1.2.4.2 wiz is_snan_x:
6672 1.2.4.2 wiz mov.b &SNAN, %d0
6673 1.2.4.2 wiz rts
6674 1.2.4.2 wiz
6675 1.2.4.2 wiz #########################################################################
6676 1.2.4.2 wiz # XDEF **************************************************************** #
6677 1.2.4.2 wiz # set_tag_d(): return the optype of the input dbl fp number #
6678 1.2.4.2 wiz # #
6679 1.2.4.2 wiz # XREF **************************************************************** #
6680 1.2.4.2 wiz # None #
6681 1.2.4.2 wiz # #
6682 1.2.4.2 wiz # INPUT *************************************************************** #
6683 1.2.4.2 wiz # a0 = points to double precision operand #
6684 1.2.4.2 wiz # #
6685 1.2.4.2 wiz # OUTPUT ************************************************************** #
6686 1.2.4.2 wiz # d0 = value of type tag #
6687 1.2.4.2 wiz # one of: NORM, INF, QNAN, SNAN, DENORM, ZERO #
6688 1.2.4.2 wiz # #
6689 1.2.4.2 wiz # ALGORITHM *********************************************************** #
6690 1.2.4.2 wiz # Simply test the exponent, j-bit, and mantissa values to #
6691 1.2.4.2 wiz # determine the type of operand. #
6692 1.2.4.2 wiz # #
6693 1.2.4.2 wiz #########################################################################
6694 1.2.4.2 wiz
6695 1.2.4.2 wiz global set_tag_d
6696 1.2.4.2 wiz set_tag_d:
6697 1.2.4.2 wiz mov.l FTEMP(%a0), %d0
6698 1.2.4.2 wiz mov.l %d0, %d1
6699 1.2.4.2 wiz
6700 1.2.4.2 wiz andi.l &0x7ff00000, %d0
6701 1.2.4.2 wiz beq.b zero_or_denorm_d
6702 1.2.4.2 wiz
6703 1.2.4.2 wiz cmpi.l %d0, &0x7ff00000
6704 1.2.4.2 wiz beq.b inf_or_nan_d
6705 1.2.4.2 wiz
6706 1.2.4.2 wiz is_norm_d:
6707 1.2.4.2 wiz mov.b &NORM, %d0
6708 1.2.4.2 wiz rts
6709 1.2.4.2 wiz zero_or_denorm_d:
6710 1.2.4.2 wiz and.l &0x000fffff, %d1
6711 1.2.4.2 wiz bne is_denorm_d
6712 1.2.4.2 wiz tst.l 4+FTEMP(%a0)
6713 1.2.4.2 wiz bne is_denorm_d
6714 1.2.4.2 wiz is_zero_d:
6715 1.2.4.2 wiz mov.b &ZERO, %d0
6716 1.2.4.2 wiz rts
6717 1.2.4.2 wiz is_denorm_d:
6718 1.2.4.2 wiz mov.b &DENORM, %d0
6719 1.2.4.2 wiz rts
6720 1.2.4.2 wiz inf_or_nan_d:
6721 1.2.4.2 wiz and.l &0x000fffff, %d1
6722 1.2.4.2 wiz bne is_nan_d
6723 1.2.4.2 wiz tst.l 4+FTEMP(%a0)
6724 1.2.4.2 wiz bne is_nan_d
6725 1.2.4.2 wiz is_inf_d:
6726 1.2.4.2 wiz mov.b &INF, %d0
6727 1.2.4.2 wiz rts
6728 1.2.4.2 wiz is_nan_d:
6729 1.2.4.2 wiz btst &19, %d1
6730 1.2.4.2 wiz bne is_qnan_d
6731 1.2.4.2 wiz is_snan_d:
6732 1.2.4.2 wiz mov.b &SNAN, %d0
6733 1.2.4.2 wiz rts
6734 1.2.4.2 wiz is_qnan_d:
6735 1.2.4.2 wiz mov.b &QNAN, %d0
6736 1.2.4.2 wiz rts
6737 1.2.4.2 wiz
6738 1.2.4.2 wiz #########################################################################
6739 1.2.4.2 wiz # XDEF **************************************************************** #
6740 1.2.4.2 wiz # set_tag_s(): return the optype of the input sgl fp number #
6741 1.2.4.2 wiz # #
6742 1.2.4.2 wiz # XREF **************************************************************** #
6743 1.2.4.2 wiz # None #
6744 1.2.4.2 wiz # #
6745 1.2.4.2 wiz # INPUT *************************************************************** #
6746 1.2.4.2 wiz # a0 = pointer to single precision operand #
6747 1.2.4.2 wiz # #
6748 1.2.4.2 wiz # OUTPUT ************************************************************** #
6749 1.2.4.2 wiz # d0 = value of type tag #
6750 1.2.4.2 wiz # one of: NORM, INF, QNAN, SNAN, DENORM, ZERO #
6751 1.2.4.2 wiz # #
6752 1.2.4.2 wiz # ALGORITHM *********************************************************** #
6753 1.2.4.2 wiz # Simply test the exponent, j-bit, and mantissa values to #
6754 1.2.4.2 wiz # determine the type of operand. #
6755 1.2.4.2 wiz # #
6756 1.2.4.2 wiz #########################################################################
6757 1.2.4.2 wiz
6758 1.2.4.2 wiz global set_tag_s
6759 1.2.4.2 wiz set_tag_s:
6760 1.2.4.2 wiz mov.l FTEMP(%a0), %d0
6761 1.2.4.2 wiz mov.l %d0, %d1
6762 1.2.4.2 wiz
6763 1.2.4.2 wiz andi.l &0x7f800000, %d0
6764 1.2.4.2 wiz beq.b zero_or_denorm_s
6765 1.2.4.2 wiz
6766 1.2.4.2 wiz cmpi.l %d0, &0x7f800000
6767 1.2.4.2 wiz beq.b inf_or_nan_s
6768 1.2.4.2 wiz
6769 1.2.4.2 wiz is_norm_s:
6770 1.2.4.2 wiz mov.b &NORM, %d0
6771 1.2.4.2 wiz rts
6772 1.2.4.2 wiz zero_or_denorm_s:
6773 1.2.4.2 wiz and.l &0x007fffff, %d1
6774 1.2.4.2 wiz bne is_denorm_s
6775 1.2.4.2 wiz is_zero_s:
6776 1.2.4.2 wiz mov.b &ZERO, %d0
6777 1.2.4.2 wiz rts
6778 1.2.4.2 wiz is_denorm_s:
6779 1.2.4.2 wiz mov.b &DENORM, %d0
6780 1.2.4.2 wiz rts
6781 1.2.4.2 wiz inf_or_nan_s:
6782 1.2.4.2 wiz and.l &0x007fffff, %d1
6783 1.2.4.2 wiz bne is_nan_s
6784 1.2.4.2 wiz is_inf_s:
6785 1.2.4.2 wiz mov.b &INF, %d0
6786 1.2.4.2 wiz rts
6787 1.2.4.2 wiz is_nan_s:
6788 1.2.4.2 wiz btst &22, %d1
6789 1.2.4.2 wiz bne is_qnan_s
6790 1.2.4.2 wiz is_snan_s:
6791 1.2.4.2 wiz mov.b &SNAN, %d0
6792 1.2.4.2 wiz rts
6793 1.2.4.2 wiz is_qnan_s:
6794 1.2.4.2 wiz mov.b &QNAN, %d0
6795 1.2.4.2 wiz rts
6796 1.2.4.2 wiz
6797 1.2.4.2 wiz #########################################################################
6798 1.2.4.2 wiz # XDEF **************************************************************** #
6799 1.2.4.2 wiz # unf_res(): routine to produce default underflow result of a #
6800 1.2.4.2 wiz # scaled extended precision number; this is used by #
6801 1.2.4.2 wiz # fadd/fdiv/fmul/etc. emulation routines. #
6802 1.2.4.2 wiz # unf_res4(): same as above but for fsglmul/fsgldiv which use #
6803 1.2.4.2 wiz # single round prec and extended prec mode. #
6804 1.2.4.2 wiz # #
6805 1.2.4.2 wiz # XREF **************************************************************** #
6806 1.2.4.2 wiz # _denorm() - denormalize according to scale factor #
6807 1.2.4.2 wiz # _round() - round denormalized number according to rnd prec #
6808 1.2.4.2 wiz # #
6809 1.2.4.2 wiz # INPUT *************************************************************** #
6810 1.2.4.2 wiz # a0 = pointer to extended precison operand #
6811 1.2.4.2 wiz # d0 = scale factor #
6812 1.2.4.2 wiz # d1 = rounding precision/mode #
6813 1.2.4.2 wiz # #
6814 1.2.4.2 wiz # OUTPUT ************************************************************** #
6815 1.2.4.2 wiz # a0 = pointer to default underflow result in extended precision #
6816 1.2.4.2 wiz # d0.b = result FPSR_cc which caller may or may not want to save #
6817 1.2.4.2 wiz # #
6818 1.2.4.2 wiz # ALGORITHM *********************************************************** #
6819 1.2.4.2 wiz # Convert the input operand to "internal format" which means the #
6820 1.2.4.2 wiz # exponent is extended to 16 bits and the sign is stored in the unused #
6821 1.2.4.2 wiz # portion of the extended precison operand. Denormalize the number #
6822 1.2.4.2 wiz # according to the scale factor passed in d0. Then, round the #
6823 1.2.4.2 wiz # denormalized result. #
6824 1.2.4.2 wiz # Set the FPSR_exc bits as appropriate but return the cc bits in #
6825 1.2.4.2 wiz # d0 in case the caller doesn't want to save them (as is the case for #
6826 1.2.4.2 wiz # fmove out). #
6827 1.2.4.2 wiz # unf_res4() for fsglmul/fsgldiv forces the denorm to extended #
6828 1.2.4.2 wiz # precision and the rounding mode to single. #
6829 1.2.4.2 wiz # #
6830 1.2.4.2 wiz #########################################################################
6831 1.2.4.2 wiz global unf_res
6832 1.2.4.2 wiz unf_res:
6833 1.2.4.2 wiz mov.l %d1, -(%sp) # save rnd prec,mode on stack
6834 1.2.4.2 wiz
6835 1.2.4.2 wiz btst &0x7, FTEMP_EX(%a0) # make "internal" format
6836 1.2.4.2 wiz sne FTEMP_SGN(%a0)
6837 1.2.4.2 wiz
6838 1.2.4.2 wiz mov.w FTEMP_EX(%a0), %d1 # extract exponent
6839 1.2.4.2 wiz and.w &0x7fff, %d1
6840 1.2.4.2 wiz sub.w %d0, %d1
6841 1.2.4.2 wiz mov.w %d1, FTEMP_EX(%a0) # insert 16 bit exponent
6842 1.2.4.2 wiz
6843 1.2.4.2 wiz mov.l %a0, -(%sp) # save operand ptr during calls
6844 1.2.4.2 wiz
6845 1.2.4.2 wiz mov.l 0x4(%sp),%d0 # pass rnd prec.
6846 1.2.4.2 wiz andi.w &0x00c0,%d0
6847 1.2.4.2 wiz lsr.w &0x4,%d0
6848 1.2.4.2 wiz bsr.l _denorm # denorm result
6849 1.2.4.2 wiz
6850 1.2.4.2 wiz mov.l (%sp),%a0
6851 1.2.4.2 wiz mov.w 0x6(%sp),%d1 # load prec:mode into %d1
6852 1.2.4.2 wiz andi.w &0xc0,%d1 # extract rnd prec
6853 1.2.4.2 wiz lsr.w &0x4,%d1
6854 1.2.4.2 wiz swap %d1
6855 1.2.4.2 wiz mov.w 0x6(%sp),%d1
6856 1.2.4.2 wiz andi.w &0x30,%d1
6857 1.2.4.2 wiz lsr.w &0x4,%d1
6858 1.2.4.2 wiz bsr.l _round # round the denorm
6859 1.2.4.2 wiz
6860 1.2.4.2 wiz mov.l (%sp)+, %a0
6861 1.2.4.2 wiz
6862 1.2.4.2 wiz # result is now rounded properly. convert back to normal format
6863 1.2.4.2 wiz bclr &0x7, FTEMP_EX(%a0) # clear sgn first; may have residue
6864 1.2.4.2 wiz tst.b FTEMP_SGN(%a0) # is "internal result" sign set?
6865 1.2.4.2 wiz beq.b unf_res_chkifzero # no; result is positive
6866 1.2.4.2 wiz bset &0x7, FTEMP_EX(%a0) # set result sgn
6867 1.2.4.2 wiz clr.b FTEMP_SGN(%a0) # clear temp sign
6868 1.2.4.2 wiz
6869 1.2.4.2 wiz # the number may have become zero after rounding. set ccodes accordingly.
6870 1.2.4.2 wiz unf_res_chkifzero:
6871 1.2.4.2 wiz clr.l %d0
6872 1.2.4.2 wiz tst.l FTEMP_HI(%a0) # is value now a zero?
6873 1.2.4.2 wiz bne.b unf_res_cont # no
6874 1.2.4.2 wiz tst.l FTEMP_LO(%a0)
6875 1.2.4.2 wiz bne.b unf_res_cont # no
6876 1.2.4.2 wiz # bset &z_bit, FPSR_CC(%a6) # yes; set zero ccode bit
6877 1.2.4.2 wiz bset &z_bit, %d0 # yes; set zero ccode bit
6878 1.2.4.2 wiz
6879 1.2.4.2 wiz unf_res_cont:
6880 1.2.4.2 wiz
6881 1.2.4.2 wiz #
6882 1.2.4.2 wiz # can inex1 also be set along with unfl and inex2???
6883 1.2.4.2 wiz #
6884 1.2.4.2 wiz # we know that underflow has occurred. aunfl should be set if INEX2 is also set.
6885 1.2.4.2 wiz #
6886 1.2.4.2 wiz btst &inex2_bit, FPSR_EXCEPT(%a6) # is INEX2 set?
6887 1.2.4.2 wiz beq.b unf_res_end # no
6888 1.2.4.2 wiz bset &aunfl_bit, FPSR_AEXCEPT(%a6) # yes; set aunfl
6889 1.2.4.2 wiz
6890 1.2.4.2 wiz unf_res_end:
6891 1.2.4.2 wiz add.l &0x4, %sp # clear stack
6892 1.2.4.2 wiz rts
6893 1.2.4.2 wiz
6894 1.2.4.2 wiz # unf_res() for fsglmul() and fsgldiv().
6895 1.2.4.2 wiz global unf_res4
6896 1.2.4.2 wiz unf_res4:
6897 1.2.4.2 wiz mov.l %d1,-(%sp) # save rnd prec,mode on stack
6898 1.2.4.2 wiz
6899 1.2.4.2 wiz btst &0x7,FTEMP_EX(%a0) # make "internal" format
6900 1.2.4.2 wiz sne FTEMP_SGN(%a0)
6901 1.2.4.2 wiz
6902 1.2.4.2 wiz mov.w FTEMP_EX(%a0),%d1 # extract exponent
6903 1.2.4.2 wiz and.w &0x7fff,%d1
6904 1.2.4.2 wiz sub.w %d0,%d1
6905 1.2.4.2 wiz mov.w %d1,FTEMP_EX(%a0) # insert 16 bit exponent
6906 1.2.4.2 wiz
6907 1.2.4.2 wiz mov.l %a0,-(%sp) # save operand ptr during calls
6908 1.2.4.2 wiz
6909 1.2.4.2 wiz clr.l %d0 # force rnd prec = ext
6910 1.2.4.2 wiz bsr.l _denorm # denorm result
6911 1.2.4.2 wiz
6912 1.2.4.2 wiz mov.l (%sp),%a0
6913 1.2.4.2 wiz mov.w &s_mode,%d1 # force rnd prec = sgl
6914 1.2.4.2 wiz swap %d1
6915 1.2.4.2 wiz mov.w 0x6(%sp),%d1 # load rnd mode
6916 1.2.4.2 wiz andi.w &0x30,%d1 # extract rnd prec
6917 1.2.4.2 wiz lsr.w &0x4,%d1
6918 1.2.4.2 wiz bsr.l _round # round the denorm
6919 1.2.4.2 wiz
6920 1.2.4.2 wiz mov.l (%sp)+,%a0
6921 1.2.4.2 wiz
6922 1.2.4.2 wiz # result is now rounded properly. convert back to normal format
6923 1.2.4.2 wiz bclr &0x7,FTEMP_EX(%a0) # clear sgn first; may have residue
6924 1.2.4.2 wiz tst.b FTEMP_SGN(%a0) # is "internal result" sign set?
6925 1.2.4.2 wiz beq.b unf_res4_chkifzero # no; result is positive
6926 1.2.4.2 wiz bset &0x7,FTEMP_EX(%a0) # set result sgn
6927 1.2.4.2 wiz clr.b FTEMP_SGN(%a0) # clear temp sign
6928 1.2.4.2 wiz
6929 1.2.4.2 wiz # the number may have become zero after rounding. set ccodes accordingly.
6930 1.2.4.2 wiz unf_res4_chkifzero:
6931 1.2.4.2 wiz clr.l %d0
6932 1.2.4.2 wiz tst.l FTEMP_HI(%a0) # is value now a zero?
6933 1.2.4.2 wiz bne.b unf_res4_cont # no
6934 1.2.4.2 wiz tst.l FTEMP_LO(%a0)
6935 1.2.4.2 wiz bne.b unf_res4_cont # no
6936 1.2.4.2 wiz # bset &z_bit,FPSR_CC(%a6) # yes; set zero ccode bit
6937 1.2.4.2 wiz bset &z_bit,%d0 # yes; set zero ccode bit
6938 1.2.4.2 wiz
6939 1.2.4.2 wiz unf_res4_cont:
6940 1.2.4.2 wiz
6941 1.2.4.2 wiz #
6942 1.2.4.2 wiz # can inex1 also be set along with unfl and inex2???
6943 1.2.4.2 wiz #
6944 1.2.4.2 wiz # we know that underflow has occurred. aunfl should be set if INEX2 is also set.
6945 1.2.4.2 wiz #
6946 1.2.4.2 wiz btst &inex2_bit,FPSR_EXCEPT(%a6) # is INEX2 set?
6947 1.2.4.2 wiz beq.b unf_res4_end # no
6948 1.2.4.2 wiz bset &aunfl_bit,FPSR_AEXCEPT(%a6) # yes; set aunfl
6949 1.2.4.2 wiz
6950 1.2.4.2 wiz unf_res4_end:
6951 1.2.4.2 wiz add.l &0x4,%sp # clear stack
6952 1.2.4.2 wiz rts
6953 1.2.4.2 wiz
6954 1.2.4.2 wiz #########################################################################
6955 1.2.4.2 wiz # XDEF **************************************************************** #
6956 1.2.4.2 wiz # ovf_res(): routine to produce the default overflow result of #
6957 1.2.4.2 wiz # an overflowing number. #
6958 1.2.4.2 wiz # ovf_res2(): same as above but the rnd mode/prec are passed #
6959 1.2.4.2 wiz # differently. #
6960 1.2.4.2 wiz # #
6961 1.2.4.2 wiz # XREF **************************************************************** #
6962 1.2.4.2 wiz # none #
6963 1.2.4.2 wiz # #
6964 1.2.4.2 wiz # INPUT *************************************************************** #
6965 1.2.4.2 wiz # d1.b = '-1' => (-); '0' => (+) #
6966 1.2.4.2 wiz # ovf_res(): #
6967 1.2.4.2 wiz # d0 = rnd mode/prec #
6968 1.2.4.2 wiz # ovf_res2(): #
6969 1.2.4.2 wiz # hi(d0) = rnd prec #
6970 1.2.4.2 wiz # lo(d0) = rnd mode #
6971 1.2.4.2 wiz # #
6972 1.2.4.2 wiz # OUTPUT ************************************************************** #
6973 1.2.4.2 wiz # a0 = points to extended precision result #
6974 1.2.4.2 wiz # d0.b = condition code bits #
6975 1.2.4.2 wiz # #
6976 1.2.4.2 wiz # ALGORITHM *********************************************************** #
6977 1.2.4.2 wiz # The default overflow result can be determined by the sign of #
6978 1.2.4.2 wiz # the result and the rounding mode/prec in effect. These bits are #
6979 1.2.4.2 wiz # concatenated together to create an index into the default result #
6980 1.2.4.2 wiz # table. A pointer to the correct result is returned in a0. The #
6981 1.2.4.2 wiz # resulting condition codes are returned in d0 in case the caller #
6982 1.2.4.2 wiz # doesn't want FPSR_cc altered (as is the case for fmove out). #
6983 1.2.4.2 wiz # #
6984 1.2.4.2 wiz #########################################################################
6985 1.2.4.2 wiz
6986 1.2.4.2 wiz global ovf_res
6987 1.2.4.2 wiz ovf_res:
6988 1.2.4.2 wiz andi.w &0x10,%d1 # keep result sign
6989 1.2.4.2 wiz lsr.b &0x4,%d0 # shift prec/mode
6990 1.2.4.2 wiz or.b %d0,%d1 # concat the two
6991 1.2.4.2 wiz mov.w %d1,%d0 # make a copy
6992 1.2.4.2 wiz lsl.b &0x1,%d1 # multiply d1 by 2
6993 1.2.4.2 wiz bra.b ovf_res_load
6994 1.2.4.2 wiz
6995 1.2.4.2 wiz global ovf_res2
6996 1.2.4.2 wiz ovf_res2:
6997 1.2.4.2 wiz and.w &0x10, %d1 # keep result sign
6998 1.2.4.2 wiz or.b %d0, %d1 # insert rnd mode
6999 1.2.4.2 wiz swap %d0
7000 1.2.4.2 wiz or.b %d0, %d1 # insert rnd prec
7001 1.2.4.2 wiz mov.w %d1, %d0 # make a copy
7002 1.2.4.2 wiz lsl.b &0x1, %d1 # shift left by 1
7003 1.2.4.2 wiz
7004 1.2.4.2 wiz #
7005 1.2.4.2 wiz # use the rounding mode, precision, and result sign as in index into the
7006 1.2.4.2 wiz # two tables below to fetch the default result and the result ccodes.
7007 1.2.4.2 wiz #
7008 1.2.4.2 wiz ovf_res_load:
7009 1.2.4.2 wiz mov.b (tbl_ovfl_cc.b,%pc,%d0.w*1), %d0 # fetch result ccodes
7010 1.2.4.2 wiz lea (tbl_ovfl_result.b,%pc,%d1.w*8), %a0 # return result ptr
7011 1.2.4.2 wiz
7012 1.2.4.2 wiz rts
7013 1.2.4.2 wiz
7014 1.2.4.2 wiz tbl_ovfl_cc:
7015 1.2.4.2 wiz byte 0x2, 0x0, 0x0, 0x2
7016 1.2.4.2 wiz byte 0x2, 0x0, 0x0, 0x2
7017 1.2.4.2 wiz byte 0x2, 0x0, 0x0, 0x2
7018 1.2.4.2 wiz byte 0x0, 0x0, 0x0, 0x0
7019 1.2.4.2 wiz byte 0x2+0x8, 0x8, 0x2+0x8, 0x8
7020 1.2.4.2 wiz byte 0x2+0x8, 0x8, 0x2+0x8, 0x8
7021 1.2.4.2 wiz byte 0x2+0x8, 0x8, 0x2+0x8, 0x8
7022 1.2.4.2 wiz
7023 1.2.4.2 wiz tbl_ovfl_result:
7024 1.2.4.2 wiz long 0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RN
7025 1.2.4.2 wiz long 0x7ffe0000,0xffffffff,0xffffffff,0x00000000 # +EXT; RZ
7026 1.2.4.2 wiz long 0x7ffe0000,0xffffffff,0xffffffff,0x00000000 # +EXT; RM
7027 1.2.4.2 wiz long 0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RP
7028 1.2.4.2 wiz
7029 1.2.4.2 wiz long 0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RN
7030 1.2.4.2 wiz long 0x407e0000,0xffffff00,0x00000000,0x00000000 # +SGL; RZ
7031 1.2.4.2 wiz long 0x407e0000,0xffffff00,0x00000000,0x00000000 # +SGL; RM
7032 1.2.4.2 wiz long 0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RP
7033 1.2.4.2 wiz
7034 1.2.4.2 wiz long 0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RN
7035 1.2.4.2 wiz long 0x43fe0000,0xffffffff,0xfffff800,0x00000000 # +DBL; RZ
7036 1.2.4.2 wiz long 0x43fe0000,0xffffffff,0xfffff800,0x00000000 # +DBL; RM
7037 1.2.4.2 wiz long 0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RP
7038 1.2.4.2 wiz
7039 1.2.4.2 wiz long 0x00000000,0x00000000,0x00000000,0x00000000
7040 1.2.4.2 wiz long 0x00000000,0x00000000,0x00000000,0x00000000
7041 1.2.4.2 wiz long 0x00000000,0x00000000,0x00000000,0x00000000
7042 1.2.4.2 wiz long 0x00000000,0x00000000,0x00000000,0x00000000
7043 1.2.4.2 wiz
7044 1.2.4.2 wiz long 0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RN
7045 1.2.4.2 wiz long 0xfffe0000,0xffffffff,0xffffffff,0x00000000 # -EXT; RZ
7046 1.2.4.2 wiz long 0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RM
7047 1.2.4.2 wiz long 0xfffe0000,0xffffffff,0xffffffff,0x00000000 # -EXT; RP
7048 1.2.4.2 wiz
7049 1.2.4.2 wiz long 0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RN
7050 1.2.4.2 wiz long 0xc07e0000,0xffffff00,0x00000000,0x00000000 # -SGL; RZ
7051 1.2.4.2 wiz long 0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RM
7052 1.2.4.2 wiz long 0xc07e0000,0xffffff00,0x00000000,0x00000000 # -SGL; RP
7053 1.2.4.2 wiz
7054 1.2.4.2 wiz long 0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RN
7055 1.2.4.2 wiz long 0xc3fe0000,0xffffffff,0xfffff800,0x00000000 # -DBL; RZ
7056 1.2.4.2 wiz long 0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RM
7057 1.2.4.2 wiz long 0xc3fe0000,0xffffffff,0xfffff800,0x00000000 # -DBL; RP
7058 1.2.4.2 wiz
7059 1.2.4.2 wiz #########################################################################
7060 1.2.4.2 wiz # XDEF **************************************************************** #
7061 1.2.4.2 wiz # fout(): move from fp register to memory or data register #
7062 1.2.4.2 wiz # #
7063 1.2.4.2 wiz # XREF **************************************************************** #
7064 1.2.4.2 wiz # _round() - needed to create EXOP for sgl/dbl precision #
7065 1.2.4.2 wiz # norm() - needed to create EXOP for extended precision #
7066 1.2.4.2 wiz # ovf_res() - create default overflow result for sgl/dbl precision#
7067 1.2.4.2 wiz # unf_res() - create default underflow result for sgl/dbl prec. #
7068 1.2.4.2 wiz # dst_dbl() - create rounded dbl precision result. #
7069 1.2.4.2 wiz # dst_sgl() - create rounded sgl precision result. #
7070 1.2.4.2 wiz # fetch_dreg() - fetch dynamic k-factor reg for packed. #
7071 1.2.4.2 wiz # bindec() - convert FP binary number to packed number. #
7072 1.2.4.2 wiz # _mem_write() - write data to memory. #
7073 1.2.4.2 wiz # _mem_write2() - write data to memory unless supv mode -(a7) exc.#
7074 1.2.4.2 wiz # _dmem_write_{byte,word,long}() - write data to memory. #
7075 1.2.4.2 wiz # store_dreg_{b,w,l}() - store data to data register file. #
7076 1.2.4.2 wiz # facc_out_{b,w,l,d,x}() - data access error occurred. #
7077 1.2.4.2 wiz # #
7078 1.2.4.2 wiz # INPUT *************************************************************** #
7079 1.2.4.2 wiz # a0 = pointer to extended precision source operand #
7080 1.2.4.2 wiz # d0 = round prec,mode #
7081 1.2.4.2 wiz # #
7082 1.2.4.2 wiz # OUTPUT ************************************************************** #
7083 1.2.4.2 wiz # fp0 : intermediate underflow or overflow result if #
7084 1.2.4.2 wiz # OVFL/UNFL occurred for a sgl or dbl operand #
7085 1.2.4.2 wiz # #
7086 1.2.4.2 wiz # ALGORITHM *********************************************************** #
7087 1.2.4.2 wiz # This routine is accessed by many handlers that need to do an #
7088 1.2.4.2 wiz # opclass three move of an operand out to memory. #
7089 1.2.4.2 wiz # Decode an fmove out (opclass 3) instruction to determine if #
7090 1.2.4.2 wiz # it's b,w,l,s,d,x, or p in size. b,w,l can be stored to either a data #
7091 1.2.4.2 wiz # register or memory. The algorithm uses a standard "fmove" to create #
7092 1.2.4.2 wiz # the rounded result. Also, since exceptions are disabled, this also #
7093 1.2.4.2 wiz # create the correct OPERR default result if appropriate. #
7094 1.2.4.2 wiz # For sgl or dbl precision, overflow or underflow can occur. If #
7095 1.2.4.2 wiz # either occurs and is enabled, the EXOP. #
7096 1.2.4.2 wiz # For extended precision, the stacked <ea> must be fixed along #
7097 1.2.4.2 wiz # w/ the address index register as appropriate w/ _calc_ea_fout(). If #
7098 1.2.4.2 wiz # the source is a denorm and if underflow is enabled, an EXOP must be #
7099 1.2.4.2 wiz # created. #
7100 1.2.4.2 wiz # For packed, the k-factor must be fetched from the instruction #
7101 1.2.4.2 wiz # word or a data register. The <ea> must be fixed as w/ extended #
7102 1.2.4.2 wiz # precision. Then, bindec() is called to create the appropriate #
7103 1.2.4.2 wiz # packed result. #
7104 1.2.4.2 wiz # If at any time an access error is flagged by one of the move- #
7105 1.2.4.2 wiz # to-memory routines, then a special exit must be made so that the #
7106 1.2.4.2 wiz # access error can be handled properly. #
7107 1.2.4.2 wiz # #
7108 1.2.4.2 wiz #########################################################################
7109 1.2.4.2 wiz
7110 1.2.4.2 wiz global fout
7111 1.2.4.2 wiz fout:
7112 1.2.4.2 wiz bfextu EXC_CMDREG(%a6){&3:&3},%d1 # extract dst fmt
7113 1.2.4.2 wiz mov.w (tbl_fout.b,%pc,%d1.w*2),%a1 # use as index
7114 1.2.4.2 wiz jmp (tbl_fout.b,%pc,%a1) # jump to routine
7115 1.2.4.2 wiz
7116 1.2.4.2 wiz swbeg &0x8
7117 1.2.4.2 wiz tbl_fout:
7118 1.2.4.2 wiz short fout_long - tbl_fout
7119 1.2.4.2 wiz short fout_sgl - tbl_fout
7120 1.2.4.2 wiz short fout_ext - tbl_fout
7121 1.2.4.2 wiz short fout_pack - tbl_fout
7122 1.2.4.2 wiz short fout_word - tbl_fout
7123 1.2.4.2 wiz short fout_dbl - tbl_fout
7124 1.2.4.2 wiz short fout_byte - tbl_fout
7125 1.2.4.2 wiz short fout_pack - tbl_fout
7126 1.2.4.2 wiz
7127 1.2.4.2 wiz #################################################################
7128 1.2.4.2 wiz # fmove.b out ###################################################
7129 1.2.4.2 wiz #################################################################
7130 1.2.4.2 wiz
7131 1.2.4.2 wiz # Only "Unimplemented Data Type" exceptions enter here. The operand
7132 1.2.4.2 wiz # is either a DENORM or a NORM.
7133 1.2.4.2 wiz fout_byte:
7134 1.2.4.2 wiz tst.b STAG(%a6) # is operand normalized?
7135 1.2.4.2 wiz bne.b fout_byte_denorm # no
7136 1.2.4.2 wiz
7137 1.2.4.2 wiz fmovm.x SRC(%a0),&0x80 # load value
7138 1.2.4.2 wiz
7139 1.2.4.2 wiz fout_byte_norm:
7140 1.2.4.2 wiz fmov.l %d0,%fpcr # insert rnd prec,mode
7141 1.2.4.2 wiz
7142 1.2.4.2 wiz fmov.b %fp0,%d0 # exec move out w/ correct rnd mode
7143 1.2.4.2 wiz
7144 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
7145 1.2.4.2 wiz fmov.l %fpsr,%d1 # fetch FPSR
7146 1.2.4.2 wiz or.w %d1,2+USER_FPSR(%a6) # save new exc,accrued bits
7147 1.2.4.2 wiz
7148 1.2.4.2 wiz mov.b 1+EXC_OPWORD(%a6),%d1 # extract dst mode
7149 1.2.4.2 wiz andi.b &0x38,%d1 # is mode == 0? (Dreg dst)
7150 1.2.4.2 wiz beq.b fout_byte_dn # must save to integer regfile
7151 1.2.4.2 wiz
7152 1.2.4.2 wiz mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
7153 1.2.4.2 wiz bsr.l _dmem_write_byte # write byte
7154 1.2.4.2 wiz
7155 1.2.4.2 wiz tst.l %d1 # did dstore fail?
7156 1.2.4.2 wiz bne.l facc_out_b # yes
7157 1.2.4.2 wiz
7158 1.2.4.2 wiz rts
7159 1.2.4.2 wiz
7160 1.2.4.2 wiz fout_byte_dn:
7161 1.2.4.2 wiz mov.b 1+EXC_OPWORD(%a6),%d1 # extract Dn
7162 1.2.4.2 wiz andi.w &0x7,%d1
7163 1.2.4.2 wiz bsr.l store_dreg_b
7164 1.2.4.2 wiz rts
7165 1.2.4.2 wiz
7166 1.2.4.2 wiz fout_byte_denorm:
7167 1.2.4.2 wiz mov.l SRC_EX(%a0),%d1
7168 1.2.4.2 wiz andi.l &0x80000000,%d1 # keep DENORM sign
7169 1.2.4.2 wiz ori.l &0x00800000,%d1 # make smallest sgl
7170 1.2.4.2 wiz fmov.s %d1,%fp0
7171 1.2.4.2 wiz bra.b fout_byte_norm
7172 1.2.4.2 wiz
7173 1.2.4.2 wiz #################################################################
7174 1.2.4.2 wiz # fmove.w out ###################################################
7175 1.2.4.2 wiz #################################################################
7176 1.2.4.2 wiz
7177 1.2.4.2 wiz # Only "Unimplemented Data Type" exceptions enter here. The operand
7178 1.2.4.2 wiz # is either a DENORM or a NORM.
7179 1.2.4.2 wiz fout_word:
7180 1.2.4.2 wiz tst.b STAG(%a6) # is operand normalized?
7181 1.2.4.2 wiz bne.b fout_word_denorm # no
7182 1.2.4.2 wiz
7183 1.2.4.2 wiz fmovm.x SRC(%a0),&0x80 # load value
7184 1.2.4.2 wiz
7185 1.2.4.2 wiz fout_word_norm:
7186 1.2.4.2 wiz fmov.l %d0,%fpcr # insert rnd prec:mode
7187 1.2.4.2 wiz
7188 1.2.4.2 wiz fmov.w %fp0,%d0 # exec move out w/ correct rnd mode
7189 1.2.4.2 wiz
7190 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
7191 1.2.4.2 wiz fmov.l %fpsr,%d1 # fetch FPSR
7192 1.2.4.2 wiz or.w %d1,2+USER_FPSR(%a6) # save new exc,accrued bits
7193 1.2.4.2 wiz
7194 1.2.4.2 wiz mov.b 1+EXC_OPWORD(%a6),%d1 # extract dst mode
7195 1.2.4.2 wiz andi.b &0x38,%d1 # is mode == 0? (Dreg dst)
7196 1.2.4.2 wiz beq.b fout_word_dn # must save to integer regfile
7197 1.2.4.2 wiz
7198 1.2.4.2 wiz mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
7199 1.2.4.2 wiz bsr.l _dmem_write_word # write word
7200 1.2.4.2 wiz
7201 1.2.4.2 wiz tst.l %d1 # did dstore fail?
7202 1.2.4.2 wiz bne.l facc_out_w # yes
7203 1.2.4.2 wiz
7204 1.2.4.2 wiz rts
7205 1.2.4.2 wiz
7206 1.2.4.2 wiz fout_word_dn:
7207 1.2.4.2 wiz mov.b 1+EXC_OPWORD(%a6),%d1 # extract Dn
7208 1.2.4.2 wiz andi.w &0x7,%d1
7209 1.2.4.2 wiz bsr.l store_dreg_w
7210 1.2.4.2 wiz rts
7211 1.2.4.2 wiz
7212 1.2.4.2 wiz fout_word_denorm:
7213 1.2.4.2 wiz mov.l SRC_EX(%a0),%d1
7214 1.2.4.2 wiz andi.l &0x80000000,%d1 # keep DENORM sign
7215 1.2.4.2 wiz ori.l &0x00800000,%d1 # make smallest sgl
7216 1.2.4.2 wiz fmov.s %d1,%fp0
7217 1.2.4.2 wiz bra.b fout_word_norm
7218 1.2.4.2 wiz
7219 1.2.4.2 wiz #################################################################
7220 1.2.4.2 wiz # fmove.l out ###################################################
7221 1.2.4.2 wiz #################################################################
7222 1.2.4.2 wiz
7223 1.2.4.2 wiz # Only "Unimplemented Data Type" exceptions enter here. The operand
7224 1.2.4.2 wiz # is either a DENORM or a NORM.
7225 1.2.4.2 wiz fout_long:
7226 1.2.4.2 wiz tst.b STAG(%a6) # is operand normalized?
7227 1.2.4.2 wiz bne.b fout_long_denorm # no
7228 1.2.4.2 wiz
7229 1.2.4.2 wiz fmovm.x SRC(%a0),&0x80 # load value
7230 1.2.4.2 wiz
7231 1.2.4.2 wiz fout_long_norm:
7232 1.2.4.2 wiz fmov.l %d0,%fpcr # insert rnd prec:mode
7233 1.2.4.2 wiz
7234 1.2.4.2 wiz fmov.l %fp0,%d0 # exec move out w/ correct rnd mode
7235 1.2.4.2 wiz
7236 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
7237 1.2.4.2 wiz fmov.l %fpsr,%d1 # fetch FPSR
7238 1.2.4.2 wiz or.w %d1,2+USER_FPSR(%a6) # save new exc,accrued bits
7239 1.2.4.2 wiz
7240 1.2.4.2 wiz fout_long_write:
7241 1.2.4.2 wiz mov.b 1+EXC_OPWORD(%a6),%d1 # extract dst mode
7242 1.2.4.2 wiz andi.b &0x38,%d1 # is mode == 0? (Dreg dst)
7243 1.2.4.2 wiz beq.b fout_long_dn # must save to integer regfile
7244 1.2.4.2 wiz
7245 1.2.4.2 wiz mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
7246 1.2.4.2 wiz bsr.l _dmem_write_long # write long
7247 1.2.4.2 wiz
7248 1.2.4.2 wiz tst.l %d1 # did dstore fail?
7249 1.2.4.2 wiz bne.l facc_out_l # yes
7250 1.2.4.2 wiz
7251 1.2.4.2 wiz rts
7252 1.2.4.2 wiz
7253 1.2.4.2 wiz fout_long_dn:
7254 1.2.4.2 wiz mov.b 1+EXC_OPWORD(%a6),%d1 # extract Dn
7255 1.2.4.2 wiz andi.w &0x7,%d1
7256 1.2.4.2 wiz bsr.l store_dreg_l
7257 1.2.4.2 wiz rts
7258 1.2.4.2 wiz
7259 1.2.4.2 wiz fout_long_denorm:
7260 1.2.4.2 wiz mov.l SRC_EX(%a0),%d1
7261 1.2.4.2 wiz andi.l &0x80000000,%d1 # keep DENORM sign
7262 1.2.4.2 wiz ori.l &0x00800000,%d1 # make smallest sgl
7263 1.2.4.2 wiz fmov.s %d1,%fp0
7264 1.2.4.2 wiz bra.b fout_long_norm
7265 1.2.4.2 wiz
7266 1.2.4.2 wiz #################################################################
7267 1.2.4.2 wiz # fmove.x out ###################################################
7268 1.2.4.2 wiz #################################################################
7269 1.2.4.2 wiz
7270 1.2.4.2 wiz # Only "Unimplemented Data Type" exceptions enter here. The operand
7271 1.2.4.2 wiz # is either a DENORM or a NORM.
7272 1.2.4.2 wiz # The DENORM causes an Underflow exception.
7273 1.2.4.2 wiz fout_ext:
7274 1.2.4.2 wiz
7275 1.2.4.2 wiz # we copy the extended precision result to FP_SCR0 so that the reserved
7276 1.2.4.2 wiz # 16-bit field gets zeroed. we do this since we promise not to disturb
7277 1.2.4.2 wiz # what's at SRC(a0).
7278 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
7279 1.2.4.2 wiz clr.w 2+FP_SCR0_EX(%a6) # clear reserved field
7280 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
7281 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
7282 1.2.4.2 wiz
7283 1.2.4.2 wiz fmovm.x SRC(%a0),&0x80 # return result
7284 1.2.4.2 wiz
7285 1.2.4.2 wiz bsr.l _calc_ea_fout # fix stacked <ea>
7286 1.2.4.2 wiz
7287 1.2.4.2 wiz mov.l %a0,%a1 # pass: dst addr
7288 1.2.4.2 wiz lea FP_SCR0(%a6),%a0 # pass: src addr
7289 1.2.4.2 wiz mov.l &0xc,%d0 # pass: opsize is 12 bytes
7290 1.2.4.2 wiz
7291 1.2.4.2 wiz # we must not yet write the extended precision data to the stack
7292 1.2.4.2 wiz # in the pre-decrement case from supervisor mode or else we'll corrupt
7293 1.2.4.2 wiz # the stack frame. so, leave it in FP_SRC for now and deal with it later...
7294 1.2.4.2 wiz cmpi.b SPCOND_FLG(%a6),&mda7_flg
7295 1.2.4.2 wiz beq.b fout_ext_a7
7296 1.2.4.2 wiz
7297 1.2.4.2 wiz bsr.l _dmem_write # write ext prec number to memory
7298 1.2.4.2 wiz
7299 1.2.4.2 wiz tst.l %d1 # did dstore fail?
7300 1.2.4.2 wiz bne.w fout_ext_err # yes
7301 1.2.4.2 wiz
7302 1.2.4.2 wiz tst.b STAG(%a6) # is operand normalized?
7303 1.2.4.2 wiz bne.b fout_ext_denorm # no
7304 1.2.4.2 wiz rts
7305 1.2.4.2 wiz
7306 1.2.4.2 wiz # the number is a DENORM. must set the underflow exception bit
7307 1.2.4.2 wiz fout_ext_denorm:
7308 1.2.4.2 wiz bset &unfl_bit,FPSR_EXCEPT(%a6) # set underflow exc bit
7309 1.2.4.2 wiz
7310 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d0
7311 1.2.4.2 wiz andi.b &0x0a,%d0 # is UNFL or INEX enabled?
7312 1.2.4.2 wiz bne.b fout_ext_exc # yes
7313 1.2.4.2 wiz rts
7314 1.2.4.2 wiz
7315 1.2.4.2 wiz # we don't want to do the write if the exception occurred in supervisor mode
7316 1.2.4.2 wiz # so _mem_write2() handles this for us.
7317 1.2.4.2 wiz fout_ext_a7:
7318 1.2.4.2 wiz bsr.l _mem_write2 # write ext prec number to memory
7319 1.2.4.2 wiz
7320 1.2.4.2 wiz tst.l %d1 # did dstore fail?
7321 1.2.4.2 wiz bne.w fout_ext_err # yes
7322 1.2.4.2 wiz
7323 1.2.4.2 wiz tst.b STAG(%a6) # is operand normalized?
7324 1.2.4.2 wiz bne.b fout_ext_denorm # no
7325 1.2.4.2 wiz rts
7326 1.2.4.2 wiz
7327 1.2.4.2 wiz fout_ext_exc:
7328 1.2.4.2 wiz lea FP_SCR0(%a6),%a0
7329 1.2.4.2 wiz bsr.l norm # normalize the mantissa
7330 1.2.4.2 wiz neg.w %d0 # new exp = -(shft amt)
7331 1.2.4.2 wiz andi.w &0x7fff,%d0
7332 1.2.4.2 wiz andi.w &0x8000,FP_SCR0_EX(%a6) # keep only old sign
7333 1.2.4.2 wiz or.w %d0,FP_SCR0_EX(%a6) # insert new exponent
7334 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
7335 1.2.4.2 wiz rts
7336 1.2.4.2 wiz
7337 1.2.4.2 wiz fout_ext_err:
7338 1.2.4.2 wiz mov.l EXC_A6(%a6),(%a6) # fix stacked a6
7339 1.2.4.2 wiz bra.l facc_out_x
7340 1.2.4.2 wiz
7341 1.2.4.2 wiz #########################################################################
7342 1.2.4.2 wiz # fmove.s out ###########################################################
7343 1.2.4.2 wiz #########################################################################
7344 1.2.4.2 wiz fout_sgl:
7345 1.2.4.2 wiz andi.b &0x30,%d0 # clear rnd prec
7346 1.2.4.2 wiz ori.b &s_mode*0x10,%d0 # insert sgl prec
7347 1.2.4.2 wiz mov.l %d0,L_SCR3(%a6) # save rnd prec,mode on stack
7348 1.2.4.2 wiz
7349 1.2.4.2 wiz #
7350 1.2.4.2 wiz # operand is a normalized number. first, we check to see if the move out
7351 1.2.4.2 wiz # would cause either an underflow or overflow. these cases are handled
7352 1.2.4.2 wiz # separately. otherwise, set the FPCR to the proper rounding mode and
7353 1.2.4.2 wiz # execute the move.
7354 1.2.4.2 wiz #
7355 1.2.4.2 wiz mov.w SRC_EX(%a0),%d0 # extract exponent
7356 1.2.4.2 wiz andi.w &0x7fff,%d0 # strip sign
7357 1.2.4.2 wiz
7358 1.2.4.2 wiz cmpi.w %d0,&SGL_HI # will operand overflow?
7359 1.2.4.2 wiz bgt.w fout_sgl_ovfl # yes; go handle OVFL
7360 1.2.4.2 wiz beq.w fout_sgl_may_ovfl # maybe; go handle possible OVFL
7361 1.2.4.2 wiz cmpi.w %d0,&SGL_LO # will operand underflow?
7362 1.2.4.2 wiz blt.w fout_sgl_unfl # yes; go handle underflow
7363 1.2.4.2 wiz
7364 1.2.4.2 wiz #
7365 1.2.4.2 wiz # NORMs(in range) can be stored out by a simple "fmov.s"
7366 1.2.4.2 wiz # Unnormalized inputs can come through this point.
7367 1.2.4.2 wiz #
7368 1.2.4.2 wiz fout_sgl_exg:
7369 1.2.4.2 wiz fmovm.x SRC(%a0),&0x80 # fetch fop from stack
7370 1.2.4.2 wiz
7371 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
7372 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
7373 1.2.4.2 wiz
7374 1.2.4.2 wiz fmov.s %fp0,%d0 # store does convert and round
7375 1.2.4.2 wiz
7376 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
7377 1.2.4.2 wiz fmov.l %fpsr,%d1 # save FPSR
7378 1.2.4.2 wiz
7379 1.2.4.2 wiz or.w %d1,2+USER_FPSR(%a6) # set possible inex2/ainex
7380 1.2.4.2 wiz
7381 1.2.4.2 wiz fout_sgl_exg_write:
7382 1.2.4.2 wiz mov.b 1+EXC_OPWORD(%a6),%d1 # extract dst mode
7383 1.2.4.2 wiz andi.b &0x38,%d1 # is mode == 0? (Dreg dst)
7384 1.2.4.2 wiz beq.b fout_sgl_exg_write_dn # must save to integer regfile
7385 1.2.4.2 wiz
7386 1.2.4.2 wiz mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
7387 1.2.4.2 wiz bsr.l _dmem_write_long # write long
7388 1.2.4.2 wiz
7389 1.2.4.2 wiz tst.l %d1 # did dstore fail?
7390 1.2.4.2 wiz bne.l facc_out_l # yes
7391 1.2.4.2 wiz
7392 1.2.4.2 wiz rts
7393 1.2.4.2 wiz
7394 1.2.4.2 wiz fout_sgl_exg_write_dn:
7395 1.2.4.2 wiz mov.b 1+EXC_OPWORD(%a6),%d1 # extract Dn
7396 1.2.4.2 wiz andi.w &0x7,%d1
7397 1.2.4.2 wiz bsr.l store_dreg_l
7398 1.2.4.2 wiz rts
7399 1.2.4.2 wiz
7400 1.2.4.2 wiz #
7401 1.2.4.2 wiz # here, we know that the operand would UNFL if moved out to single prec,
7402 1.2.4.2 wiz # so, denorm and round and then use generic store single routine to
7403 1.2.4.2 wiz # write the value to memory.
7404 1.2.4.2 wiz #
7405 1.2.4.2 wiz fout_sgl_unfl:
7406 1.2.4.2 wiz bset &unfl_bit,FPSR_EXCEPT(%a6) # set UNFL
7407 1.2.4.2 wiz
7408 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
7409 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
7410 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
7411 1.2.4.2 wiz mov.l %a0,-(%sp)
7412 1.2.4.2 wiz
7413 1.2.4.2 wiz clr.l %d0 # pass: S.F. = 0
7414 1.2.4.2 wiz
7415 1.2.4.2 wiz cmpi.b STAG(%a6),&DENORM # fetch src optype tag
7416 1.2.4.2 wiz bne.b fout_sgl_unfl_cont # let DENORMs fall through
7417 1.2.4.2 wiz
7418 1.2.4.2 wiz lea FP_SCR0(%a6),%a0
7419 1.2.4.2 wiz bsr.l norm # normalize the DENORM
7420 1.2.4.2 wiz
7421 1.2.4.2 wiz fout_sgl_unfl_cont:
7422 1.2.4.2 wiz lea FP_SCR0(%a6),%a0 # pass: ptr to operand
7423 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
7424 1.2.4.2 wiz bsr.l unf_res # calc default underflow result
7425 1.2.4.2 wiz
7426 1.2.4.2 wiz lea FP_SCR0(%a6),%a0 # pass: ptr to fop
7427 1.2.4.2 wiz bsr.l dst_sgl # convert to single prec
7428 1.2.4.2 wiz
7429 1.2.4.2 wiz mov.b 1+EXC_OPWORD(%a6),%d1 # extract dst mode
7430 1.2.4.2 wiz andi.b &0x38,%d1 # is mode == 0? (Dreg dst)
7431 1.2.4.2 wiz beq.b fout_sgl_unfl_dn # must save to integer regfile
7432 1.2.4.2 wiz
7433 1.2.4.2 wiz mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
7434 1.2.4.2 wiz bsr.l _dmem_write_long # write long
7435 1.2.4.2 wiz
7436 1.2.4.2 wiz tst.l %d1 # did dstore fail?
7437 1.2.4.2 wiz bne.l facc_out_l # yes
7438 1.2.4.2 wiz
7439 1.2.4.2 wiz bra.b fout_sgl_unfl_chkexc
7440 1.2.4.2 wiz
7441 1.2.4.2 wiz fout_sgl_unfl_dn:
7442 1.2.4.2 wiz mov.b 1+EXC_OPWORD(%a6),%d1 # extract Dn
7443 1.2.4.2 wiz andi.w &0x7,%d1
7444 1.2.4.2 wiz bsr.l store_dreg_l
7445 1.2.4.2 wiz
7446 1.2.4.2 wiz fout_sgl_unfl_chkexc:
7447 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d1
7448 1.2.4.2 wiz andi.b &0x0a,%d1 # is UNFL or INEX enabled?
7449 1.2.4.2 wiz bne.w fout_sd_exc_unfl # yes
7450 1.2.4.2 wiz addq.l &0x4,%sp
7451 1.2.4.2 wiz rts
7452 1.2.4.2 wiz
7453 1.2.4.2 wiz #
7454 1.2.4.2 wiz # it's definitely an overflow so call ovf_res to get the correct answer
7455 1.2.4.2 wiz #
7456 1.2.4.2 wiz fout_sgl_ovfl:
7457 1.2.4.2 wiz tst.b 3+SRC_HI(%a0) # is result inexact?
7458 1.2.4.2 wiz bne.b fout_sgl_ovfl_inex2
7459 1.2.4.2 wiz tst.l SRC_LO(%a0) # is result inexact?
7460 1.2.4.2 wiz bne.b fout_sgl_ovfl_inex2
7461 1.2.4.2 wiz ori.w &ovfl_inx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex
7462 1.2.4.2 wiz bra.b fout_sgl_ovfl_cont
7463 1.2.4.2 wiz fout_sgl_ovfl_inex2:
7464 1.2.4.2 wiz ori.w &ovfinx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex/inex2
7465 1.2.4.2 wiz
7466 1.2.4.2 wiz fout_sgl_ovfl_cont:
7467 1.2.4.2 wiz mov.l %a0,-(%sp)
7468 1.2.4.2 wiz
7469 1.2.4.2 wiz # call ovf_res() w/ sgl prec and the correct rnd mode to create the default
7470 1.2.4.2 wiz # overflow result. DON'T save the returned ccodes from ovf_res() since
7471 1.2.4.2 wiz # fmove out doesn't alter them.
7472 1.2.4.2 wiz tst.b SRC_EX(%a0) # is operand negative?
7473 1.2.4.2 wiz smi %d1 # set if so
7474 1.2.4.2 wiz mov.l L_SCR3(%a6),%d0 # pass: sgl prec,rnd mode
7475 1.2.4.2 wiz bsr.l ovf_res # calc OVFL result
7476 1.2.4.2 wiz fmovm.x (%a0),&0x80 # load default overflow result
7477 1.2.4.2 wiz fmov.s %fp0,%d0 # store to single
7478 1.2.4.2 wiz
7479 1.2.4.2 wiz mov.b 1+EXC_OPWORD(%a6),%d1 # extract dst mode
7480 1.2.4.2 wiz andi.b &0x38,%d1 # is mode == 0? (Dreg dst)
7481 1.2.4.2 wiz beq.b fout_sgl_ovfl_dn # must save to integer regfile
7482 1.2.4.2 wiz
7483 1.2.4.2 wiz mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
7484 1.2.4.2 wiz bsr.l _dmem_write_long # write long
7485 1.2.4.2 wiz
7486 1.2.4.2 wiz tst.l %d1 # did dstore fail?
7487 1.2.4.2 wiz bne.l facc_out_l # yes
7488 1.2.4.2 wiz
7489 1.2.4.2 wiz bra.b fout_sgl_ovfl_chkexc
7490 1.2.4.2 wiz
7491 1.2.4.2 wiz fout_sgl_ovfl_dn:
7492 1.2.4.2 wiz mov.b 1+EXC_OPWORD(%a6),%d1 # extract Dn
7493 1.2.4.2 wiz andi.w &0x7,%d1
7494 1.2.4.2 wiz bsr.l store_dreg_l
7495 1.2.4.2 wiz
7496 1.2.4.2 wiz fout_sgl_ovfl_chkexc:
7497 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d1
7498 1.2.4.2 wiz andi.b &0x0a,%d1 # is UNFL or INEX enabled?
7499 1.2.4.2 wiz bne.w fout_sd_exc_ovfl # yes
7500 1.2.4.2 wiz addq.l &0x4,%sp
7501 1.2.4.2 wiz rts
7502 1.2.4.2 wiz
7503 1.2.4.2 wiz #
7504 1.2.4.2 wiz # move out MAY overflow:
7505 1.2.4.2 wiz # (1) force the exp to 0x3fff
7506 1.2.4.2 wiz # (2) do a move w/ appropriate rnd mode
7507 1.2.4.2 wiz # (3) if exp still equals zero, then insert original exponent
7508 1.2.4.2 wiz # for the correct result.
7509 1.2.4.2 wiz # if exp now equals one, then it overflowed so call ovf_res.
7510 1.2.4.2 wiz #
7511 1.2.4.2 wiz fout_sgl_may_ovfl:
7512 1.2.4.2 wiz mov.w SRC_EX(%a0),%d1 # fetch current sign
7513 1.2.4.2 wiz andi.w &0x8000,%d1 # keep it,clear exp
7514 1.2.4.2 wiz ori.w &0x3fff,%d1 # insert exp = 0
7515 1.2.4.2 wiz mov.w %d1,FP_SCR0_EX(%a6) # insert scaled exp
7516 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6) # copy hi(man)
7517 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6) # copy lo(man)
7518 1.2.4.2 wiz
7519 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
7520 1.2.4.2 wiz
7521 1.2.4.2 wiz fmov.x FP_SCR0(%a6),%fp0 # force fop to be rounded
7522 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
7523 1.2.4.2 wiz
7524 1.2.4.2 wiz fabs.x %fp0 # need absolute value
7525 1.2.4.2 wiz fcmp.b %fp0,&0x2 # did exponent increase?
7526 1.2.4.2 wiz fblt.w fout_sgl_exg # no; go finish NORM
7527 1.2.4.2 wiz bra.w fout_sgl_ovfl # yes; go handle overflow
7528 1.2.4.2 wiz
7529 1.2.4.2 wiz ################
7530 1.2.4.2 wiz
7531 1.2.4.2 wiz fout_sd_exc_unfl:
7532 1.2.4.2 wiz mov.l (%sp)+,%a0
7533 1.2.4.2 wiz
7534 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
7535 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
7536 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
7537 1.2.4.2 wiz
7538 1.2.4.2 wiz cmpi.b STAG(%a6),&DENORM # was src a DENORM?
7539 1.2.4.2 wiz bne.b fout_sd_exc_cont # no
7540 1.2.4.2 wiz
7541 1.2.4.2 wiz lea FP_SCR0(%a6),%a0
7542 1.2.4.2 wiz bsr.l norm
7543 1.2.4.2 wiz neg.l %d0
7544 1.2.4.2 wiz andi.w &0x7fff,%d0
7545 1.2.4.2 wiz bfins %d0,FP_SCR0_EX(%a6){&1:&15}
7546 1.2.4.2 wiz bra.b fout_sd_exc_cont
7547 1.2.4.2 wiz
7548 1.2.4.2 wiz fout_sd_exc:
7549 1.2.4.2 wiz fout_sd_exc_ovfl:
7550 1.2.4.2 wiz mov.l (%sp)+,%a0 # restore a0
7551 1.2.4.2 wiz
7552 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
7553 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
7554 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
7555 1.2.4.2 wiz
7556 1.2.4.2 wiz fout_sd_exc_cont:
7557 1.2.4.2 wiz bclr &0x7,FP_SCR0_EX(%a6) # clear sign bit
7558 1.2.4.2 wiz sne.b 2+FP_SCR0_EX(%a6) # set internal sign bit
7559 1.2.4.2 wiz lea FP_SCR0(%a6),%a0 # pass: ptr to DENORM
7560 1.2.4.2 wiz
7561 1.2.4.2 wiz mov.b 3+L_SCR3(%a6),%d1
7562 1.2.4.2 wiz lsr.b &0x4,%d1
7563 1.2.4.2 wiz andi.w &0x0c,%d1
7564 1.2.4.2 wiz swap %d1
7565 1.2.4.2 wiz mov.b 3+L_SCR3(%a6),%d1
7566 1.2.4.2 wiz lsr.b &0x4,%d1
7567 1.2.4.2 wiz andi.w &0x03,%d1
7568 1.2.4.2 wiz clr.l %d0 # pass: zero g,r,s
7569 1.2.4.2 wiz bsr.l _round # round the DENORM
7570 1.2.4.2 wiz
7571 1.2.4.2 wiz tst.b 2+FP_SCR0_EX(%a6) # is EXOP negative?
7572 1.2.4.2 wiz beq.b fout_sd_exc_done # no
7573 1.2.4.2 wiz bset &0x7,FP_SCR0_EX(%a6) # yes
7574 1.2.4.2 wiz
7575 1.2.4.2 wiz fout_sd_exc_done:
7576 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
7577 1.2.4.2 wiz rts
7578 1.2.4.2 wiz
7579 1.2.4.2 wiz #################################################################
7580 1.2.4.2 wiz # fmove.d out ###################################################
7581 1.2.4.2 wiz #################################################################
7582 1.2.4.2 wiz fout_dbl:
7583 1.2.4.2 wiz andi.b &0x30,%d0 # clear rnd prec
7584 1.2.4.2 wiz ori.b &d_mode*0x10,%d0 # insert dbl prec
7585 1.2.4.2 wiz mov.l %d0,L_SCR3(%a6) # save rnd prec,mode on stack
7586 1.2.4.2 wiz
7587 1.2.4.2 wiz #
7588 1.2.4.2 wiz # operand is a normalized number. first, we check to see if the move out
7589 1.2.4.2 wiz # would cause either an underflow or overflow. these cases are handled
7590 1.2.4.2 wiz # separately. otherwise, set the FPCR to the proper rounding mode and
7591 1.2.4.2 wiz # execute the move.
7592 1.2.4.2 wiz #
7593 1.2.4.2 wiz mov.w SRC_EX(%a0),%d0 # extract exponent
7594 1.2.4.2 wiz andi.w &0x7fff,%d0 # strip sign
7595 1.2.4.2 wiz
7596 1.2.4.2 wiz cmpi.w %d0,&DBL_HI # will operand overflow?
7597 1.2.4.2 wiz bgt.w fout_dbl_ovfl # yes; go handle OVFL
7598 1.2.4.2 wiz beq.w fout_dbl_may_ovfl # maybe; go handle possible OVFL
7599 1.2.4.2 wiz cmpi.w %d0,&DBL_LO # will operand underflow?
7600 1.2.4.2 wiz blt.w fout_dbl_unfl # yes; go handle underflow
7601 1.2.4.2 wiz
7602 1.2.4.2 wiz #
7603 1.2.4.2 wiz # NORMs(in range) can be stored out by a simple "fmov.d"
7604 1.2.4.2 wiz # Unnormalized inputs can come through this point.
7605 1.2.4.2 wiz #
7606 1.2.4.2 wiz fout_dbl_exg:
7607 1.2.4.2 wiz fmovm.x SRC(%a0),&0x80 # fetch fop from stack
7608 1.2.4.2 wiz
7609 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
7610 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
7611 1.2.4.2 wiz
7612 1.2.4.2 wiz fmov.d %fp0,L_SCR1(%a6) # store does convert and round
7613 1.2.4.2 wiz
7614 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
7615 1.2.4.2 wiz fmov.l %fpsr,%d0 # save FPSR
7616 1.2.4.2 wiz
7617 1.2.4.2 wiz or.w %d0,2+USER_FPSR(%a6) # set possible inex2/ainex
7618 1.2.4.2 wiz
7619 1.2.4.2 wiz mov.l EXC_EA(%a6),%a1 # pass: dst addr
7620 1.2.4.2 wiz lea L_SCR1(%a6),%a0 # pass: src addr
7621 1.2.4.2 wiz movq.l &0x8,%d0 # pass: opsize is 8 bytes
7622 1.2.4.2 wiz bsr.l _dmem_write # store dbl fop to memory
7623 1.2.4.2 wiz
7624 1.2.4.2 wiz tst.l %d1 # did dstore fail?
7625 1.2.4.2 wiz bne.l facc_out_d # yes
7626 1.2.4.2 wiz
7627 1.2.4.2 wiz rts # no; so we're finished
7628 1.2.4.2 wiz
7629 1.2.4.2 wiz #
7630 1.2.4.2 wiz # here, we know that the operand would UNFL if moved out to double prec,
7631 1.2.4.2 wiz # so, denorm and round and then use generic store double routine to
7632 1.2.4.2 wiz # write the value to memory.
7633 1.2.4.2 wiz #
7634 1.2.4.2 wiz fout_dbl_unfl:
7635 1.2.4.2 wiz bset &unfl_bit,FPSR_EXCEPT(%a6) # set UNFL
7636 1.2.4.2 wiz
7637 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
7638 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
7639 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
7640 1.2.4.2 wiz mov.l %a0,-(%sp)
7641 1.2.4.2 wiz
7642 1.2.4.2 wiz clr.l %d0 # pass: S.F. = 0
7643 1.2.4.2 wiz
7644 1.2.4.2 wiz cmpi.b STAG(%a6),&DENORM # fetch src optype tag
7645 1.2.4.2 wiz bne.b fout_dbl_unfl_cont # let DENORMs fall through
7646 1.2.4.2 wiz
7647 1.2.4.2 wiz lea FP_SCR0(%a6),%a0
7648 1.2.4.2 wiz bsr.l norm # normalize the DENORM
7649 1.2.4.2 wiz
7650 1.2.4.2 wiz fout_dbl_unfl_cont:
7651 1.2.4.2 wiz lea FP_SCR0(%a6),%a0 # pass: ptr to operand
7652 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
7653 1.2.4.2 wiz bsr.l unf_res # calc default underflow result
7654 1.2.4.2 wiz
7655 1.2.4.2 wiz lea FP_SCR0(%a6),%a0 # pass: ptr to fop
7656 1.2.4.2 wiz bsr.l dst_dbl # convert to single prec
7657 1.2.4.2 wiz mov.l %d0,L_SCR1(%a6)
7658 1.2.4.2 wiz mov.l %d1,L_SCR2(%a6)
7659 1.2.4.2 wiz
7660 1.2.4.2 wiz mov.l EXC_EA(%a6),%a1 # pass: dst addr
7661 1.2.4.2 wiz lea L_SCR1(%a6),%a0 # pass: src addr
7662 1.2.4.2 wiz movq.l &0x8,%d0 # pass: opsize is 8 bytes
7663 1.2.4.2 wiz bsr.l _dmem_write # store dbl fop to memory
7664 1.2.4.2 wiz
7665 1.2.4.2 wiz tst.l %d1 # did dstore fail?
7666 1.2.4.2 wiz bne.l facc_out_d # yes
7667 1.2.4.2 wiz
7668 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d1
7669 1.2.4.2 wiz andi.b &0x0a,%d1 # is UNFL or INEX enabled?
7670 1.2.4.2 wiz bne.w fout_sd_exc_unfl # yes
7671 1.2.4.2 wiz addq.l &0x4,%sp
7672 1.2.4.2 wiz rts
7673 1.2.4.2 wiz
7674 1.2.4.2 wiz #
7675 1.2.4.2 wiz # it's definitely an overflow so call ovf_res to get the correct answer
7676 1.2.4.2 wiz #
7677 1.2.4.2 wiz fout_dbl_ovfl:
7678 1.2.4.2 wiz mov.w 2+SRC_LO(%a0),%d0
7679 1.2.4.2 wiz andi.w &0x7ff,%d0
7680 1.2.4.2 wiz bne.b fout_dbl_ovfl_inex2
7681 1.2.4.2 wiz
7682 1.2.4.2 wiz ori.w &ovfl_inx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex
7683 1.2.4.2 wiz bra.b fout_dbl_ovfl_cont
7684 1.2.4.2 wiz fout_dbl_ovfl_inex2:
7685 1.2.4.2 wiz ori.w &ovfinx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex/inex2
7686 1.2.4.2 wiz
7687 1.2.4.2 wiz fout_dbl_ovfl_cont:
7688 1.2.4.2 wiz mov.l %a0,-(%sp)
7689 1.2.4.2 wiz
7690 1.2.4.2 wiz # call ovf_res() w/ dbl prec and the correct rnd mode to create the default
7691 1.2.4.2 wiz # overflow result. DON'T save the returned ccodes from ovf_res() since
7692 1.2.4.2 wiz # fmove out doesn't alter them.
7693 1.2.4.2 wiz tst.b SRC_EX(%a0) # is operand negative?
7694 1.2.4.2 wiz smi %d1 # set if so
7695 1.2.4.2 wiz mov.l L_SCR3(%a6),%d0 # pass: dbl prec,rnd mode
7696 1.2.4.2 wiz bsr.l ovf_res # calc OVFL result
7697 1.2.4.2 wiz fmovm.x (%a0),&0x80 # load default overflow result
7698 1.2.4.2 wiz fmov.d %fp0,L_SCR1(%a6) # store to double
7699 1.2.4.2 wiz
7700 1.2.4.2 wiz mov.l EXC_EA(%a6),%a1 # pass: dst addr
7701 1.2.4.2 wiz lea L_SCR1(%a6),%a0 # pass: src addr
7702 1.2.4.2 wiz movq.l &0x8,%d0 # pass: opsize is 8 bytes
7703 1.2.4.2 wiz bsr.l _dmem_write # store dbl fop to memory
7704 1.2.4.2 wiz
7705 1.2.4.2 wiz tst.l %d1 # did dstore fail?
7706 1.2.4.2 wiz bne.l facc_out_d # yes
7707 1.2.4.2 wiz
7708 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d1
7709 1.2.4.2 wiz andi.b &0x0a,%d1 # is UNFL or INEX enabled?
7710 1.2.4.2 wiz bne.w fout_sd_exc_ovfl # yes
7711 1.2.4.2 wiz addq.l &0x4,%sp
7712 1.2.4.2 wiz rts
7713 1.2.4.2 wiz
7714 1.2.4.2 wiz #
7715 1.2.4.2 wiz # move out MAY overflow:
7716 1.2.4.2 wiz # (1) force the exp to 0x3fff
7717 1.2.4.2 wiz # (2) do a move w/ appropriate rnd mode
7718 1.2.4.2 wiz # (3) if exp still equals zero, then insert original exponent
7719 1.2.4.2 wiz # for the correct result.
7720 1.2.4.2 wiz # if exp now equals one, then it overflowed so call ovf_res.
7721 1.2.4.2 wiz #
7722 1.2.4.2 wiz fout_dbl_may_ovfl:
7723 1.2.4.2 wiz mov.w SRC_EX(%a0),%d1 # fetch current sign
7724 1.2.4.2 wiz andi.w &0x8000,%d1 # keep it,clear exp
7725 1.2.4.2 wiz ori.w &0x3fff,%d1 # insert exp = 0
7726 1.2.4.2 wiz mov.w %d1,FP_SCR0_EX(%a6) # insert scaled exp
7727 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6) # copy hi(man)
7728 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6) # copy lo(man)
7729 1.2.4.2 wiz
7730 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
7731 1.2.4.2 wiz
7732 1.2.4.2 wiz fmov.x FP_SCR0(%a6),%fp0 # force fop to be rounded
7733 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
7734 1.2.4.2 wiz
7735 1.2.4.2 wiz fabs.x %fp0 # need absolute value
7736 1.2.4.2 wiz fcmp.b %fp0,&0x2 # did exponent increase?
7737 1.2.4.2 wiz fblt.w fout_dbl_exg # no; go finish NORM
7738 1.2.4.2 wiz bra.w fout_dbl_ovfl # yes; go handle overflow
7739 1.2.4.2 wiz
7740 1.2.4.2 wiz #########################################################################
7741 1.2.4.2 wiz # XDEF **************************************************************** #
7742 1.2.4.2 wiz # dst_dbl(): create double precision value from extended prec. #
7743 1.2.4.2 wiz # #
7744 1.2.4.2 wiz # XREF **************************************************************** #
7745 1.2.4.2 wiz # None #
7746 1.2.4.2 wiz # #
7747 1.2.4.2 wiz # INPUT *************************************************************** #
7748 1.2.4.2 wiz # a0 = pointer to source operand in extended precision #
7749 1.2.4.2 wiz # #
7750 1.2.4.2 wiz # OUTPUT ************************************************************** #
7751 1.2.4.2 wiz # d0 = hi(double precision result) #
7752 1.2.4.2 wiz # d1 = lo(double precision result) #
7753 1.2.4.2 wiz # #
7754 1.2.4.2 wiz # ALGORITHM *********************************************************** #
7755 1.2.4.2 wiz # #
7756 1.2.4.2 wiz # Changes extended precision to double precision. #
7757 1.2.4.2 wiz # Note: no attempt is made to round the extended value to double. #
7758 1.2.4.2 wiz # dbl_sign = ext_sign #
7759 1.2.4.2 wiz # dbl_exp = ext_exp - $3fff(ext bias) + $7ff(dbl bias) #
7760 1.2.4.2 wiz # get rid of ext integer bit #
7761 1.2.4.2 wiz # dbl_mant = ext_mant{62:12} #
7762 1.2.4.2 wiz # #
7763 1.2.4.2 wiz # --------------- --------------- --------------- #
7764 1.2.4.2 wiz # extended -> |s| exp | |1| ms mant | | ls mant | #
7765 1.2.4.2 wiz # --------------- --------------- --------------- #
7766 1.2.4.2 wiz # 95 64 63 62 32 31 11 0 #
7767 1.2.4.2 wiz # | | #
7768 1.2.4.2 wiz # | | #
7769 1.2.4.2 wiz # | | #
7770 1.2.4.2 wiz # v v #
7771 1.2.4.2 wiz # --------------- --------------- #
7772 1.2.4.2 wiz # double -> |s|exp| mant | | mant | #
7773 1.2.4.2 wiz # --------------- --------------- #
7774 1.2.4.2 wiz # 63 51 32 31 0 #
7775 1.2.4.2 wiz # #
7776 1.2.4.2 wiz #########################################################################
7777 1.2.4.2 wiz
7778 1.2.4.2 wiz dst_dbl:
7779 1.2.4.2 wiz clr.l %d0 # clear d0
7780 1.2.4.2 wiz mov.w FTEMP_EX(%a0),%d0 # get exponent
7781 1.2.4.2 wiz subi.w &EXT_BIAS,%d0 # subtract extended precision bias
7782 1.2.4.2 wiz addi.w &DBL_BIAS,%d0 # add double precision bias
7783 1.2.4.2 wiz tst.b FTEMP_HI(%a0) # is number a denorm?
7784 1.2.4.2 wiz bmi.b dst_get_dupper # no
7785 1.2.4.2 wiz subq.w &0x1,%d0 # yes; denorm bias = DBL_BIAS - 1
7786 1.2.4.2 wiz dst_get_dupper:
7787 1.2.4.2 wiz swap %d0 # d0 now in upper word
7788 1.2.4.2 wiz lsl.l &0x4,%d0 # d0 in proper place for dbl prec exp
7789 1.2.4.2 wiz tst.b FTEMP_EX(%a0) # test sign
7790 1.2.4.2 wiz bpl.b dst_get_dman # if postive, go process mantissa
7791 1.2.4.2 wiz bset &0x1f,%d0 # if negative, set sign
7792 1.2.4.2 wiz dst_get_dman:
7793 1.2.4.2 wiz mov.l FTEMP_HI(%a0),%d1 # get ms mantissa
7794 1.2.4.2 wiz bfextu %d1{&1:&20},%d1 # get upper 20 bits of ms
7795 1.2.4.2 wiz or.l %d1,%d0 # put these bits in ms word of double
7796 1.2.4.2 wiz mov.l %d0,L_SCR1(%a6) # put the new exp back on the stack
7797 1.2.4.2 wiz mov.l FTEMP_HI(%a0),%d1 # get ms mantissa
7798 1.2.4.2 wiz mov.l &21,%d0 # load shift count
7799 1.2.4.2 wiz lsl.l %d0,%d1 # put lower 11 bits in upper bits
7800 1.2.4.2 wiz mov.l %d1,L_SCR2(%a6) # build lower lword in memory
7801 1.2.4.2 wiz mov.l FTEMP_LO(%a0),%d1 # get ls mantissa
7802 1.2.4.2 wiz bfextu %d1{&0:&21},%d0 # get ls 21 bits of double
7803 1.2.4.2 wiz mov.l L_SCR2(%a6),%d1
7804 1.2.4.2 wiz or.l %d0,%d1 # put them in double result
7805 1.2.4.2 wiz mov.l L_SCR1(%a6),%d0
7806 1.2.4.2 wiz rts
7807 1.2.4.2 wiz
7808 1.2.4.2 wiz #########################################################################
7809 1.2.4.2 wiz # XDEF **************************************************************** #
7810 1.2.4.2 wiz # dst_sgl(): create single precision value from extended prec #
7811 1.2.4.2 wiz # #
7812 1.2.4.2 wiz # XREF **************************************************************** #
7813 1.2.4.2 wiz # #
7814 1.2.4.2 wiz # INPUT *************************************************************** #
7815 1.2.4.2 wiz # a0 = pointer to source operand in extended precision #
7816 1.2.4.2 wiz # #
7817 1.2.4.2 wiz # OUTPUT ************************************************************** #
7818 1.2.4.2 wiz # d0 = single precision result #
7819 1.2.4.2 wiz # #
7820 1.2.4.2 wiz # ALGORITHM *********************************************************** #
7821 1.2.4.2 wiz # #
7822 1.2.4.2 wiz # Changes extended precision to single precision. #
7823 1.2.4.2 wiz # sgl_sign = ext_sign #
7824 1.2.4.2 wiz # sgl_exp = ext_exp - $3fff(ext bias) + $7f(sgl bias) #
7825 1.2.4.2 wiz # get rid of ext integer bit #
7826 1.2.4.2 wiz # sgl_mant = ext_mant{62:12} #
7827 1.2.4.2 wiz # #
7828 1.2.4.2 wiz # --------------- --------------- --------------- #
7829 1.2.4.2 wiz # extended -> |s| exp | |1| ms mant | | ls mant | #
7830 1.2.4.2 wiz # --------------- --------------- --------------- #
7831 1.2.4.2 wiz # 95 64 63 62 40 32 31 12 0 #
7832 1.2.4.2 wiz # | | #
7833 1.2.4.2 wiz # | | #
7834 1.2.4.2 wiz # | | #
7835 1.2.4.2 wiz # v v #
7836 1.2.4.2 wiz # --------------- #
7837 1.2.4.2 wiz # single -> |s|exp| mant | #
7838 1.2.4.2 wiz # --------------- #
7839 1.2.4.2 wiz # 31 22 0 #
7840 1.2.4.2 wiz # #
7841 1.2.4.2 wiz #########################################################################
7842 1.2.4.2 wiz
7843 1.2.4.2 wiz dst_sgl:
7844 1.2.4.2 wiz clr.l %d0
7845 1.2.4.2 wiz mov.w FTEMP_EX(%a0),%d0 # get exponent
7846 1.2.4.2 wiz subi.w &EXT_BIAS,%d0 # subtract extended precision bias
7847 1.2.4.2 wiz addi.w &SGL_BIAS,%d0 # add single precision bias
7848 1.2.4.2 wiz tst.b FTEMP_HI(%a0) # is number a denorm?
7849 1.2.4.2 wiz bmi.b dst_get_supper # no
7850 1.2.4.2 wiz subq.w &0x1,%d0 # yes; denorm bias = SGL_BIAS - 1
7851 1.2.4.2 wiz dst_get_supper:
7852 1.2.4.2 wiz swap %d0 # put exp in upper word of d0
7853 1.2.4.2 wiz lsl.l &0x7,%d0 # shift it into single exp bits
7854 1.2.4.2 wiz tst.b FTEMP_EX(%a0) # test sign
7855 1.2.4.2 wiz bpl.b dst_get_sman # if positive, continue
7856 1.2.4.2 wiz bset &0x1f,%d0 # if negative, put in sign first
7857 1.2.4.2 wiz dst_get_sman:
7858 1.2.4.2 wiz mov.l FTEMP_HI(%a0),%d1 # get ms mantissa
7859 1.2.4.2 wiz andi.l &0x7fffff00,%d1 # get upper 23 bits of ms
7860 1.2.4.2 wiz lsr.l &0x8,%d1 # and put them flush right
7861 1.2.4.2 wiz or.l %d1,%d0 # put these bits in ms word of single
7862 1.2.4.2 wiz rts
7863 1.2.4.2 wiz
7864 1.2.4.2 wiz ##############################################################################
7865 1.2.4.2 wiz fout_pack:
7866 1.2.4.2 wiz bsr.l _calc_ea_fout # fetch the <ea>
7867 1.2.4.2 wiz mov.l %a0,-(%sp)
7868 1.2.4.2 wiz
7869 1.2.4.2 wiz mov.b STAG(%a6),%d0 # fetch input type
7870 1.2.4.2 wiz bne.w fout_pack_not_norm # input is not NORM
7871 1.2.4.2 wiz
7872 1.2.4.2 wiz fout_pack_norm:
7873 1.2.4.2 wiz btst &0x4,EXC_CMDREG(%a6) # static or dynamic?
7874 1.2.4.2 wiz beq.b fout_pack_s # static
7875 1.2.4.2 wiz
7876 1.2.4.2 wiz fout_pack_d:
7877 1.2.4.2 wiz mov.b 1+EXC_CMDREG(%a6),%d1 # fetch dynamic reg
7878 1.2.4.2 wiz lsr.b &0x4,%d1
7879 1.2.4.2 wiz andi.w &0x7,%d1
7880 1.2.4.2 wiz
7881 1.2.4.2 wiz bsr.l fetch_dreg # fetch Dn w/ k-factor
7882 1.2.4.2 wiz
7883 1.2.4.2 wiz bra.b fout_pack_type
7884 1.2.4.2 wiz fout_pack_s:
7885 1.2.4.2 wiz mov.b 1+EXC_CMDREG(%a6),%d0 # fetch static field
7886 1.2.4.2 wiz
7887 1.2.4.2 wiz fout_pack_type:
7888 1.2.4.2 wiz bfexts %d0{&25:&7},%d0 # extract k-factor
7889 1.2.4.2 wiz mov.l %d0,-(%sp)
7890 1.2.4.2 wiz
7891 1.2.4.2 wiz lea FP_SRC(%a6),%a0 # pass: ptr to input
7892 1.2.4.2 wiz
7893 1.2.4.2 wiz # bindec is currently scrambling FP_SRC for denorm inputs.
7894 1.2.4.2 wiz # we'll have to change this, but for now, tough luck!!!
7895 1.2.4.2 wiz bsr.l bindec # convert xprec to packed
7896 1.2.4.2 wiz
7897 1.2.4.2 wiz # andi.l &0xcfff000f,FP_SCR0(%a6) # clear unused fields
7898 1.2.4.2 wiz andi.l &0xcffff00f,FP_SCR0(%a6) # clear unused fields
7899 1.2.4.2 wiz
7900 1.2.4.2 wiz mov.l (%sp)+,%d0
7901 1.2.4.2 wiz
7902 1.2.4.2 wiz tst.b 3+FP_SCR0_EX(%a6)
7903 1.2.4.2 wiz bne.b fout_pack_set
7904 1.2.4.2 wiz tst.l FP_SCR0_HI(%a6)
7905 1.2.4.2 wiz bne.b fout_pack_set
7906 1.2.4.2 wiz tst.l FP_SCR0_LO(%a6)
7907 1.2.4.2 wiz bne.b fout_pack_set
7908 1.2.4.2 wiz
7909 1.2.4.2 wiz # add the extra condition that only if the k-factor was zero, too, should
7910 1.2.4.2 wiz # we zero the exponent
7911 1.2.4.2 wiz tst.l %d0
7912 1.2.4.2 wiz bne.b fout_pack_set
7913 1.2.4.2 wiz # "mantissa" is all zero which means that the answer is zero. but, the '040
7914 1.2.4.2 wiz # algorithm allows the exponent to be non-zero. the 881/2 do not. therefore,
7915 1.2.4.2 wiz # if the mantissa is zero, I will zero the exponent, too.
7916 1.2.4.2 wiz # the question now is whether the exponents sign bit is allowed to be non-zero
7917 1.2.4.2 wiz # for a zero, also...
7918 1.2.4.2 wiz andi.w &0xf000,FP_SCR0(%a6)
7919 1.2.4.2 wiz
7920 1.2.4.2 wiz fout_pack_set:
7921 1.2.4.2 wiz
7922 1.2.4.2 wiz lea FP_SCR0(%a6),%a0 # pass: src addr
7923 1.2.4.2 wiz
7924 1.2.4.2 wiz fout_pack_write:
7925 1.2.4.2 wiz mov.l (%sp)+,%a1 # pass: dst addr
7926 1.2.4.2 wiz mov.l &0xc,%d0 # pass: opsize is 12 bytes
7927 1.2.4.2 wiz
7928 1.2.4.2 wiz cmpi.b SPCOND_FLG(%a6),&mda7_flg
7929 1.2.4.2 wiz beq.b fout_pack_a7
7930 1.2.4.2 wiz
7931 1.2.4.2 wiz bsr.l _dmem_write # write ext prec number to memory
7932 1.2.4.2 wiz
7933 1.2.4.2 wiz tst.l %d1 # did dstore fail?
7934 1.2.4.2 wiz bne.w fout_ext_err # yes
7935 1.2.4.2 wiz
7936 1.2.4.2 wiz rts
7937 1.2.4.2 wiz
7938 1.2.4.2 wiz # we don't want to do the write if the exception occurred in supervisor mode
7939 1.2.4.2 wiz # so _mem_write2() handles this for us.
7940 1.2.4.2 wiz fout_pack_a7:
7941 1.2.4.2 wiz bsr.l _mem_write2 # write ext prec number to memory
7942 1.2.4.2 wiz
7943 1.2.4.2 wiz tst.l %d1 # did dstore fail?
7944 1.2.4.2 wiz bne.w fout_ext_err # yes
7945 1.2.4.2 wiz
7946 1.2.4.2 wiz rts
7947 1.2.4.2 wiz
7948 1.2.4.2 wiz fout_pack_not_norm:
7949 1.2.4.2 wiz cmpi.b %d0,&DENORM # is it a DENORM?
7950 1.2.4.2 wiz beq.w fout_pack_norm # yes
7951 1.2.4.2 wiz lea FP_SRC(%a6),%a0
7952 1.2.4.2 wiz clr.w 2+FP_SRC_EX(%a6)
7953 1.2.4.2 wiz cmpi.b %d0,&SNAN # is it an SNAN?
7954 1.2.4.2 wiz beq.b fout_pack_snan # yes
7955 1.2.4.2 wiz bra.b fout_pack_write # no
7956 1.2.4.2 wiz
7957 1.2.4.2 wiz fout_pack_snan:
7958 1.2.4.2 wiz ori.w &snaniop2_mask,FPSR_EXCEPT(%a6) # set SNAN/AIOP
7959 1.2.4.2 wiz bset &0x6,FP_SRC_HI(%a6) # set snan bit
7960 1.2.4.2 wiz bra.b fout_pack_write
7961 1.2.4.2 wiz
7962 1.2.4.2 wiz #########################################################################
7963 1.2.4.2 wiz # XDEF **************************************************************** #
7964 1.2.4.2 wiz # fmul(): emulates the fmul instruction #
7965 1.2.4.2 wiz # fsmul(): emulates the fsmul instruction #
7966 1.2.4.2 wiz # fdmul(): emulates the fdmul instruction #
7967 1.2.4.2 wiz # #
7968 1.2.4.2 wiz # XREF **************************************************************** #
7969 1.2.4.2 wiz # scale_to_zero_src() - scale src exponent to zero #
7970 1.2.4.2 wiz # scale_to_zero_dst() - scale dst exponent to zero #
7971 1.2.4.2 wiz # unf_res() - return default underflow result #
7972 1.2.4.2 wiz # ovf_res() - return default overflow result #
7973 1.2.4.2 wiz # res_qnan() - return QNAN result #
7974 1.2.4.2 wiz # res_snan() - return SNAN result #
7975 1.2.4.2 wiz # #
7976 1.2.4.2 wiz # INPUT *************************************************************** #
7977 1.2.4.2 wiz # a0 = pointer to extended precision source operand #
7978 1.2.4.2 wiz # a1 = pointer to extended precision destination operand #
7979 1.2.4.2 wiz # d0 rnd prec,mode #
7980 1.2.4.2 wiz # #
7981 1.2.4.2 wiz # OUTPUT ************************************************************** #
7982 1.2.4.2 wiz # fp0 = result #
7983 1.2.4.2 wiz # fp1 = EXOP (if exception occurred) #
7984 1.2.4.2 wiz # #
7985 1.2.4.2 wiz # ALGORITHM *********************************************************** #
7986 1.2.4.2 wiz # Handle NANs, infinities, and zeroes as special cases. Divide #
7987 1.2.4.2 wiz # norms/denorms into ext/sgl/dbl precision. #
7988 1.2.4.2 wiz # For norms/denorms, scale the exponents such that a multiply #
7989 1.2.4.2 wiz # instruction won't cause an exception. Use the regular fmul to #
7990 1.2.4.2 wiz # compute a result. Check if the regular operands would have taken #
7991 1.2.4.2 wiz # an exception. If so, return the default overflow/underflow result #
7992 1.2.4.2 wiz # and return the EXOP if exceptions are enabled. Else, scale the #
7993 1.2.4.2 wiz # result operand to the proper exponent. #
7994 1.2.4.2 wiz # #
7995 1.2.4.2 wiz #########################################################################
7996 1.2.4.2 wiz
7997 1.2.4.2 wiz align 0x10
7998 1.2.4.2 wiz tbl_fmul_ovfl:
7999 1.2.4.2 wiz long 0x3fff - 0x7ffe # ext_max
8000 1.2.4.2 wiz long 0x3fff - 0x407e # sgl_max
8001 1.2.4.2 wiz long 0x3fff - 0x43fe # dbl_max
8002 1.2.4.2 wiz tbl_fmul_unfl:
8003 1.2.4.2 wiz long 0x3fff + 0x0001 # ext_unfl
8004 1.2.4.2 wiz long 0x3fff - 0x3f80 # sgl_unfl
8005 1.2.4.2 wiz long 0x3fff - 0x3c00 # dbl_unfl
8006 1.2.4.2 wiz
8007 1.2.4.2 wiz global fsmul
8008 1.2.4.2 wiz fsmul:
8009 1.2.4.2 wiz andi.b &0x30,%d0 # clear rnd prec
8010 1.2.4.2 wiz ori.b &s_mode*0x10,%d0 # insert sgl prec
8011 1.2.4.2 wiz bra.b fmul
8012 1.2.4.2 wiz
8013 1.2.4.2 wiz global fdmul
8014 1.2.4.2 wiz fdmul:
8015 1.2.4.2 wiz andi.b &0x30,%d0
8016 1.2.4.2 wiz ori.b &d_mode*0x10,%d0 # insert dbl prec
8017 1.2.4.2 wiz
8018 1.2.4.2 wiz global fmul
8019 1.2.4.2 wiz fmul:
8020 1.2.4.2 wiz mov.l %d0,L_SCR3(%a6) # store rnd info
8021 1.2.4.2 wiz
8022 1.2.4.2 wiz clr.w %d1
8023 1.2.4.2 wiz mov.b DTAG(%a6),%d1
8024 1.2.4.2 wiz lsl.b &0x3,%d1
8025 1.2.4.2 wiz or.b STAG(%a6),%d1 # combine src tags
8026 1.2.4.2 wiz bne.w fmul_not_norm # optimize on non-norm input
8027 1.2.4.2 wiz
8028 1.2.4.2 wiz fmul_norm:
8029 1.2.4.2 wiz mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
8030 1.2.4.2 wiz mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
8031 1.2.4.2 wiz mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
8032 1.2.4.2 wiz
8033 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
8034 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
8035 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
8036 1.2.4.2 wiz
8037 1.2.4.2 wiz bsr.l scale_to_zero_src # scale src exponent
8038 1.2.4.2 wiz mov.l %d0,-(%sp) # save scale factor 1
8039 1.2.4.2 wiz
8040 1.2.4.2 wiz bsr.l scale_to_zero_dst # scale dst exponent
8041 1.2.4.2 wiz
8042 1.2.4.2 wiz add.l %d0,(%sp) # SCALE_FACTOR = scale1 + scale2
8043 1.2.4.2 wiz
8044 1.2.4.2 wiz mov.w 2+L_SCR3(%a6),%d1 # fetch precision
8045 1.2.4.2 wiz lsr.b &0x6,%d1 # shift to lo bits
8046 1.2.4.2 wiz mov.l (%sp)+,%d0 # load S.F.
8047 1.2.4.2 wiz cmp.l %d0,(tbl_fmul_ovfl.w,%pc,%d1.w*4) # would result ovfl?
8048 1.2.4.2 wiz beq.w fmul_may_ovfl # result may rnd to overflow
8049 1.2.4.2 wiz blt.w fmul_ovfl # result will overflow
8050 1.2.4.2 wiz
8051 1.2.4.2 wiz cmp.l %d0,(tbl_fmul_unfl.w,%pc,%d1.w*4) # would result unfl?
8052 1.2.4.2 wiz beq.w fmul_may_unfl # result may rnd to no unfl
8053 1.2.4.2 wiz bgt.w fmul_unfl # result will underflow
8054 1.2.4.2 wiz
8055 1.2.4.2 wiz #
8056 1.2.4.2 wiz # NORMAL:
8057 1.2.4.2 wiz # - the result of the multiply operation will neither overflow nor underflow.
8058 1.2.4.2 wiz # - do the multiply to the proper precision and rounding mode.
8059 1.2.4.2 wiz # - scale the result exponent using the scale factor. if both operands were
8060 1.2.4.2 wiz # normalized then we really don't need to go through this scaling. but for now,
8061 1.2.4.2 wiz # this will do.
8062 1.2.4.2 wiz #
8063 1.2.4.2 wiz fmul_normal:
8064 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst operand
8065 1.2.4.2 wiz
8066 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
8067 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
8068 1.2.4.2 wiz
8069 1.2.4.2 wiz fmul.x FP_SCR0(%a6),%fp0 # execute multiply
8070 1.2.4.2 wiz
8071 1.2.4.2 wiz fmov.l %fpsr,%d1 # save status
8072 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
8073 1.2.4.2 wiz
8074 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
8075 1.2.4.2 wiz
8076 1.2.4.2 wiz fmul_normal_exit:
8077 1.2.4.2 wiz fmovm.x &0x80,FP_SCR0(%a6) # store out result
8078 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
8079 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # load {sgn,exp}
8080 1.2.4.2 wiz mov.l %d1,%d2 # make a copy
8081 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
8082 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
8083 1.2.4.2 wiz sub.l %d0,%d1 # add scale factor
8084 1.2.4.2 wiz or.w %d2,%d1 # concat old sign,new exp
8085 1.2.4.2 wiz mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
8086 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
8087 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
8088 1.2.4.2 wiz rts
8089 1.2.4.2 wiz
8090 1.2.4.2 wiz #
8091 1.2.4.2 wiz # OVERFLOW:
8092 1.2.4.2 wiz # - the result of the multiply operation is an overflow.
8093 1.2.4.2 wiz # - do the multiply to the proper precision and rounding mode in order to
8094 1.2.4.2 wiz # set the inexact bits.
8095 1.2.4.2 wiz # - calculate the default result and return it in fp0.
8096 1.2.4.2 wiz # - if overflow or inexact is enabled, we need a multiply result rounded to
8097 1.2.4.2 wiz # extended precision. if the original operation was extended, then we have this
8098 1.2.4.2 wiz # result. if the original operation was single or double, we have to do another
8099 1.2.4.2 wiz # multiply using extended precision and the correct rounding mode. the result
8100 1.2.4.2 wiz # of this operation then has its exponent scaled by -0x6000 to create the
8101 1.2.4.2 wiz # exceptional operand.
8102 1.2.4.2 wiz #
8103 1.2.4.2 wiz fmul_ovfl:
8104 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst operand
8105 1.2.4.2 wiz
8106 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
8107 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
8108 1.2.4.2 wiz
8109 1.2.4.2 wiz fmul.x FP_SCR0(%a6),%fp0 # execute multiply
8110 1.2.4.2 wiz
8111 1.2.4.2 wiz fmov.l %fpsr,%d1 # save status
8112 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
8113 1.2.4.2 wiz
8114 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
8115 1.2.4.2 wiz
8116 1.2.4.2 wiz # save setting this until now because this is where fmul_may_ovfl may jump in
8117 1.2.4.2 wiz fmul_ovfl_tst:
8118 1.2.4.2 wiz or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
8119 1.2.4.2 wiz
8120 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d1
8121 1.2.4.2 wiz andi.b &0x13,%d1 # is OVFL or INEX enabled?
8122 1.2.4.2 wiz bne.b fmul_ovfl_ena # yes
8123 1.2.4.2 wiz
8124 1.2.4.2 wiz # calculate the default result
8125 1.2.4.2 wiz fmul_ovfl_dis:
8126 1.2.4.2 wiz btst &neg_bit,FPSR_CC(%a6) # is result negative?
8127 1.2.4.2 wiz sne %d1 # set sign param accordingly
8128 1.2.4.2 wiz mov.l L_SCR3(%a6),%d0 # pass rnd prec,mode
8129 1.2.4.2 wiz bsr.l ovf_res # calculate default result
8130 1.2.4.2 wiz or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
8131 1.2.4.2 wiz fmovm.x (%a0),&0x80 # return default result in fp0
8132 1.2.4.2 wiz rts
8133 1.2.4.2 wiz
8134 1.2.4.2 wiz #
8135 1.2.4.2 wiz # OVFL is enabled; Create EXOP:
8136 1.2.4.2 wiz # - if precision is extended, then we have the EXOP. simply bias the exponent
8137 1.2.4.2 wiz # with an extra -0x6000. if the precision is single or double, we need to
8138 1.2.4.2 wiz # calculate a result rounded to extended precision.
8139 1.2.4.2 wiz #
8140 1.2.4.2 wiz fmul_ovfl_ena:
8141 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1
8142 1.2.4.2 wiz andi.b &0xc0,%d1 # test the rnd prec
8143 1.2.4.2 wiz bne.b fmul_ovfl_ena_sd # it's sgl or dbl
8144 1.2.4.2 wiz
8145 1.2.4.2 wiz fmul_ovfl_ena_cont:
8146 1.2.4.2 wiz fmovm.x &0x80,FP_SCR0(%a6) # move result to stack
8147 1.2.4.2 wiz
8148 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
8149 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
8150 1.2.4.2 wiz mov.w %d1,%d2 # make a copy
8151 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
8152 1.2.4.2 wiz sub.l %d0,%d1 # add scale factor
8153 1.2.4.2 wiz subi.l &0x6000,%d1 # subtract bias
8154 1.2.4.2 wiz andi.w &0x7fff,%d1 # clear sign bit
8155 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
8156 1.2.4.2 wiz or.w %d2,%d1 # concat old sign,new exp
8157 1.2.4.2 wiz mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
8158 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
8159 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
8160 1.2.4.2 wiz bra.b fmul_ovfl_dis
8161 1.2.4.2 wiz
8162 1.2.4.2 wiz fmul_ovfl_ena_sd:
8163 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst operand
8164 1.2.4.2 wiz
8165 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1
8166 1.2.4.2 wiz andi.b &0x30,%d1 # keep rnd mode only
8167 1.2.4.2 wiz fmov.l %d1,%fpcr # set FPCR
8168 1.2.4.2 wiz
8169 1.2.4.2 wiz fmul.x FP_SCR0(%a6),%fp0 # execute multiply
8170 1.2.4.2 wiz
8171 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
8172 1.2.4.2 wiz bra.b fmul_ovfl_ena_cont
8173 1.2.4.2 wiz
8174 1.2.4.2 wiz #
8175 1.2.4.2 wiz # may OVERFLOW:
8176 1.2.4.2 wiz # - the result of the multiply operation MAY overflow.
8177 1.2.4.2 wiz # - do the multiply to the proper precision and rounding mode in order to
8178 1.2.4.2 wiz # set the inexact bits.
8179 1.2.4.2 wiz # - calculate the default result and return it in fp0.
8180 1.2.4.2 wiz #
8181 1.2.4.2 wiz fmul_may_ovfl:
8182 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst op
8183 1.2.4.2 wiz
8184 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
8185 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
8186 1.2.4.2 wiz
8187 1.2.4.2 wiz fmul.x FP_SCR0(%a6),%fp0 # execute multiply
8188 1.2.4.2 wiz
8189 1.2.4.2 wiz fmov.l %fpsr,%d1 # save status
8190 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
8191 1.2.4.2 wiz
8192 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
8193 1.2.4.2 wiz
8194 1.2.4.2 wiz fabs.x %fp0,%fp1 # make a copy of result
8195 1.2.4.2 wiz fcmp.b %fp1,&0x2 # is |result| >= 2.b?
8196 1.2.4.2 wiz fbge.w fmul_ovfl_tst # yes; overflow has occurred
8197 1.2.4.2 wiz
8198 1.2.4.2 wiz # no, it didn't overflow; we have correct result
8199 1.2.4.2 wiz bra.w fmul_normal_exit
8200 1.2.4.2 wiz
8201 1.2.4.2 wiz #
8202 1.2.4.2 wiz # UNDERFLOW:
8203 1.2.4.2 wiz # - the result of the multiply operation is an underflow.
8204 1.2.4.2 wiz # - do the multiply to the proper precision and rounding mode in order to
8205 1.2.4.2 wiz # set the inexact bits.
8206 1.2.4.2 wiz # - calculate the default result and return it in fp0.
8207 1.2.4.2 wiz # - if overflow or inexact is enabled, we need a multiply result rounded to
8208 1.2.4.2 wiz # extended precision. if the original operation was extended, then we have this
8209 1.2.4.2 wiz # result. if the original operation was single or double, we have to do another
8210 1.2.4.2 wiz # multiply using extended precision and the correct rounding mode. the result
8211 1.2.4.2 wiz # of this operation then has its exponent scaled by -0x6000 to create the
8212 1.2.4.2 wiz # exceptional operand.
8213 1.2.4.2 wiz #
8214 1.2.4.2 wiz fmul_unfl:
8215 1.2.4.2 wiz bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
8216 1.2.4.2 wiz
8217 1.2.4.2 wiz # for fun, let's use only extended precision, round to zero. then, let
8218 1.2.4.2 wiz # the unf_res() routine figure out all the rest.
8219 1.2.4.2 wiz # will we get the correct answer.
8220 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst operand
8221 1.2.4.2 wiz
8222 1.2.4.2 wiz fmov.l &rz_mode*0x10,%fpcr # set FPCR
8223 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
8224 1.2.4.2 wiz
8225 1.2.4.2 wiz fmul.x FP_SCR0(%a6),%fp0 # execute multiply
8226 1.2.4.2 wiz
8227 1.2.4.2 wiz fmov.l %fpsr,%d1 # save status
8228 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
8229 1.2.4.2 wiz
8230 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
8231 1.2.4.2 wiz
8232 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d1
8233 1.2.4.2 wiz andi.b &0x0b,%d1 # is UNFL or INEX enabled?
8234 1.2.4.2 wiz bne.b fmul_unfl_ena # yes
8235 1.2.4.2 wiz
8236 1.2.4.2 wiz fmul_unfl_dis:
8237 1.2.4.2 wiz fmovm.x &0x80,FP_SCR0(%a6) # store out result
8238 1.2.4.2 wiz
8239 1.2.4.2 wiz lea FP_SCR0(%a6),%a0 # pass: result addr
8240 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
8241 1.2.4.2 wiz bsr.l unf_res # calculate default result
8242 1.2.4.2 wiz or.b %d0,FPSR_CC(%a6) # unf_res2 may have set 'Z'
8243 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
8244 1.2.4.2 wiz rts
8245 1.2.4.2 wiz
8246 1.2.4.2 wiz #
8247 1.2.4.2 wiz # UNFL is enabled.
8248 1.2.4.2 wiz #
8249 1.2.4.2 wiz fmul_unfl_ena:
8250 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x40 # load dst op
8251 1.2.4.2 wiz
8252 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1
8253 1.2.4.2 wiz andi.b &0xc0,%d1 # is precision extended?
8254 1.2.4.2 wiz bne.b fmul_unfl_ena_sd # no, sgl or dbl
8255 1.2.4.2 wiz
8256 1.2.4.2 wiz # if the rnd mode is anything but RZ, then we have to re-do the above
8257 1.2.4.2 wiz # multiplication becuase we used RZ for all.
8258 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
8259 1.2.4.2 wiz
8260 1.2.4.2 wiz fmul_unfl_ena_cont:
8261 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
8262 1.2.4.2 wiz
8263 1.2.4.2 wiz fmul.x FP_SCR0(%a6),%fp1 # execute multiply
8264 1.2.4.2 wiz
8265 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
8266 1.2.4.2 wiz
8267 1.2.4.2 wiz fmovm.x &0x40,FP_SCR0(%a6) # save result to stack
8268 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
8269 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
8270 1.2.4.2 wiz mov.l %d1,%d2 # make a copy
8271 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
8272 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
8273 1.2.4.2 wiz sub.l %d0,%d1 # add scale factor
8274 1.2.4.2 wiz addi.l &0x6000,%d1 # add bias
8275 1.2.4.2 wiz andi.w &0x7fff,%d1
8276 1.2.4.2 wiz or.w %d2,%d1 # concat old sign,new exp
8277 1.2.4.2 wiz mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
8278 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
8279 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
8280 1.2.4.2 wiz bra.w fmul_unfl_dis
8281 1.2.4.2 wiz
8282 1.2.4.2 wiz fmul_unfl_ena_sd:
8283 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1
8284 1.2.4.2 wiz andi.b &0x30,%d1 # use only rnd mode
8285 1.2.4.2 wiz fmov.l %d1,%fpcr # set FPCR
8286 1.2.4.2 wiz
8287 1.2.4.2 wiz bra.b fmul_unfl_ena_cont
8288 1.2.4.2 wiz
8289 1.2.4.2 wiz # MAY UNDERFLOW:
8290 1.2.4.2 wiz # -use the correct rounding mode and precision. this code favors operations
8291 1.2.4.2 wiz # that do not underflow.
8292 1.2.4.2 wiz fmul_may_unfl:
8293 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst operand
8294 1.2.4.2 wiz
8295 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
8296 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
8297 1.2.4.2 wiz
8298 1.2.4.2 wiz fmul.x FP_SCR0(%a6),%fp0 # execute multiply
8299 1.2.4.2 wiz
8300 1.2.4.2 wiz fmov.l %fpsr,%d1 # save status
8301 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
8302 1.2.4.2 wiz
8303 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
8304 1.2.4.2 wiz
8305 1.2.4.2 wiz fabs.x %fp0,%fp1 # make a copy of result
8306 1.2.4.2 wiz fcmp.b %fp1,&0x2 # is |result| > 2.b?
8307 1.2.4.2 wiz fbgt.w fmul_normal_exit # no; no underflow occurred
8308 1.2.4.2 wiz fblt.w fmul_unfl # yes; underflow occurred
8309 1.2.4.2 wiz
8310 1.2.4.2 wiz #
8311 1.2.4.2 wiz # we still don't know if underflow occurred. result is ~ equal to 2. but,
8312 1.2.4.2 wiz # we don't know if the result was an underflow that rounded up to a 2 or
8313 1.2.4.2 wiz # a normalized number that rounded down to a 2. so, redo the entire operation
8314 1.2.4.2 wiz # using RZ as the rounding mode to see what the pre-rounded result is.
8315 1.2.4.2 wiz # this case should be relatively rare.
8316 1.2.4.2 wiz #
8317 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x40 # load dst operand
8318 1.2.4.2 wiz
8319 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1
8320 1.2.4.2 wiz andi.b &0xc0,%d1 # keep rnd prec
8321 1.2.4.2 wiz ori.b &rz_mode*0x10,%d1 # insert RZ
8322 1.2.4.2 wiz
8323 1.2.4.2 wiz fmov.l %d1,%fpcr # set FPCR
8324 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
8325 1.2.4.2 wiz
8326 1.2.4.2 wiz fmul.x FP_SCR0(%a6),%fp1 # execute multiply
8327 1.2.4.2 wiz
8328 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
8329 1.2.4.2 wiz fabs.x %fp1 # make absolute value
8330 1.2.4.2 wiz fcmp.b %fp1,&0x2 # is |result| < 2.b?
8331 1.2.4.2 wiz fbge.w fmul_normal_exit # no; no underflow occurred
8332 1.2.4.2 wiz bra.w fmul_unfl # yes, underflow occurred
8333 1.2.4.2 wiz
8334 1.2.4.2 wiz ################################################################################
8335 1.2.4.2 wiz
8336 1.2.4.2 wiz #
8337 1.2.4.2 wiz # Multiply: inputs are not both normalized; what are they?
8338 1.2.4.2 wiz #
8339 1.2.4.2 wiz fmul_not_norm:
8340 1.2.4.2 wiz mov.w (tbl_fmul_op.b,%pc,%d1.w*2),%d1
8341 1.2.4.2 wiz jmp (tbl_fmul_op.b,%pc,%d1.w)
8342 1.2.4.2 wiz
8343 1.2.4.2 wiz swbeg &48
8344 1.2.4.2 wiz tbl_fmul_op:
8345 1.2.4.2 wiz short fmul_norm - tbl_fmul_op # NORM x NORM
8346 1.2.4.2 wiz short fmul_zero - tbl_fmul_op # NORM x ZERO
8347 1.2.4.2 wiz short fmul_inf_src - tbl_fmul_op # NORM x INF
8348 1.2.4.2 wiz short fmul_res_qnan - tbl_fmul_op # NORM x QNAN
8349 1.2.4.2 wiz short fmul_norm - tbl_fmul_op # NORM x DENORM
8350 1.2.4.2 wiz short fmul_res_snan - tbl_fmul_op # NORM x SNAN
8351 1.2.4.2 wiz short tbl_fmul_op - tbl_fmul_op #
8352 1.2.4.2 wiz short tbl_fmul_op - tbl_fmul_op #
8353 1.2.4.2 wiz
8354 1.2.4.2 wiz short fmul_zero - tbl_fmul_op # ZERO x NORM
8355 1.2.4.2 wiz short fmul_zero - tbl_fmul_op # ZERO x ZERO
8356 1.2.4.2 wiz short fmul_res_operr - tbl_fmul_op # ZERO x INF
8357 1.2.4.2 wiz short fmul_res_qnan - tbl_fmul_op # ZERO x QNAN
8358 1.2.4.2 wiz short fmul_zero - tbl_fmul_op # ZERO x DENORM
8359 1.2.4.2 wiz short fmul_res_snan - tbl_fmul_op # ZERO x SNAN
8360 1.2.4.2 wiz short tbl_fmul_op - tbl_fmul_op #
8361 1.2.4.2 wiz short tbl_fmul_op - tbl_fmul_op #
8362 1.2.4.2 wiz
8363 1.2.4.2 wiz short fmul_inf_dst - tbl_fmul_op # INF x NORM
8364 1.2.4.2 wiz short fmul_res_operr - tbl_fmul_op # INF x ZERO
8365 1.2.4.2 wiz short fmul_inf_dst - tbl_fmul_op # INF x INF
8366 1.2.4.2 wiz short fmul_res_qnan - tbl_fmul_op # INF x QNAN
8367 1.2.4.2 wiz short fmul_inf_dst - tbl_fmul_op # INF x DENORM
8368 1.2.4.2 wiz short fmul_res_snan - tbl_fmul_op # INF x SNAN
8369 1.2.4.2 wiz short tbl_fmul_op - tbl_fmul_op #
8370 1.2.4.2 wiz short tbl_fmul_op - tbl_fmul_op #
8371 1.2.4.2 wiz
8372 1.2.4.2 wiz short fmul_res_qnan - tbl_fmul_op # QNAN x NORM
8373 1.2.4.2 wiz short fmul_res_qnan - tbl_fmul_op # QNAN x ZERO
8374 1.2.4.2 wiz short fmul_res_qnan - tbl_fmul_op # QNAN x INF
8375 1.2.4.2 wiz short fmul_res_qnan - tbl_fmul_op # QNAN x QNAN
8376 1.2.4.2 wiz short fmul_res_qnan - tbl_fmul_op # QNAN x DENORM
8377 1.2.4.2 wiz short fmul_res_snan - tbl_fmul_op # QNAN x SNAN
8378 1.2.4.2 wiz short tbl_fmul_op - tbl_fmul_op #
8379 1.2.4.2 wiz short tbl_fmul_op - tbl_fmul_op #
8380 1.2.4.2 wiz
8381 1.2.4.2 wiz short fmul_norm - tbl_fmul_op # NORM x NORM
8382 1.2.4.2 wiz short fmul_zero - tbl_fmul_op # NORM x ZERO
8383 1.2.4.2 wiz short fmul_inf_src - tbl_fmul_op # NORM x INF
8384 1.2.4.2 wiz short fmul_res_qnan - tbl_fmul_op # NORM x QNAN
8385 1.2.4.2 wiz short fmul_norm - tbl_fmul_op # NORM x DENORM
8386 1.2.4.2 wiz short fmul_res_snan - tbl_fmul_op # NORM x SNAN
8387 1.2.4.2 wiz short tbl_fmul_op - tbl_fmul_op #
8388 1.2.4.2 wiz short tbl_fmul_op - tbl_fmul_op #
8389 1.2.4.2 wiz
8390 1.2.4.2 wiz short fmul_res_snan - tbl_fmul_op # SNAN x NORM
8391 1.2.4.2 wiz short fmul_res_snan - tbl_fmul_op # SNAN x ZERO
8392 1.2.4.2 wiz short fmul_res_snan - tbl_fmul_op # SNAN x INF
8393 1.2.4.2 wiz short fmul_res_snan - tbl_fmul_op # SNAN x QNAN
8394 1.2.4.2 wiz short fmul_res_snan - tbl_fmul_op # SNAN x DENORM
8395 1.2.4.2 wiz short fmul_res_snan - tbl_fmul_op # SNAN x SNAN
8396 1.2.4.2 wiz short tbl_fmul_op - tbl_fmul_op #
8397 1.2.4.2 wiz short tbl_fmul_op - tbl_fmul_op #
8398 1.2.4.2 wiz
8399 1.2.4.2 wiz fmul_res_operr:
8400 1.2.4.2 wiz bra.l res_operr
8401 1.2.4.2 wiz fmul_res_snan:
8402 1.2.4.2 wiz bra.l res_snan
8403 1.2.4.2 wiz fmul_res_qnan:
8404 1.2.4.2 wiz bra.l res_qnan
8405 1.2.4.2 wiz
8406 1.2.4.2 wiz #
8407 1.2.4.2 wiz # Multiply: (Zero x Zero) || (Zero x norm) || (Zero x denorm)
8408 1.2.4.2 wiz #
8409 1.2.4.2 wiz global fmul_zero # global for fsglmul
8410 1.2.4.2 wiz fmul_zero:
8411 1.2.4.2 wiz mov.b SRC_EX(%a0),%d0 # exclusive or the signs
8412 1.2.4.2 wiz mov.b DST_EX(%a1),%d1
8413 1.2.4.2 wiz eor.b %d0,%d1
8414 1.2.4.2 wiz bpl.b fmul_zero_p # result ZERO is pos.
8415 1.2.4.2 wiz fmul_zero_n:
8416 1.2.4.2 wiz fmov.s &0x80000000,%fp0 # load -ZERO
8417 1.2.4.2 wiz mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set Z/N
8418 1.2.4.2 wiz rts
8419 1.2.4.2 wiz fmul_zero_p:
8420 1.2.4.2 wiz fmov.s &0x00000000,%fp0 # load +ZERO
8421 1.2.4.2 wiz mov.b &z_bmask,FPSR_CC(%a6) # set Z
8422 1.2.4.2 wiz rts
8423 1.2.4.2 wiz
8424 1.2.4.2 wiz #
8425 1.2.4.2 wiz # Multiply: (inf x inf) || (inf x norm) || (inf x denorm)
8426 1.2.4.2 wiz #
8427 1.2.4.2 wiz # Note: The j-bit for an infinity is a don't-care. However, to be
8428 1.2.4.2 wiz # strictly compatible w/ the 68881/882, we make sure to return an
8429 1.2.4.2 wiz # INF w/ the j-bit set if the input INF j-bit was set. Destination
8430 1.2.4.2 wiz # INFs take priority.
8431 1.2.4.2 wiz #
8432 1.2.4.2 wiz global fmul_inf_dst # global for fsglmul
8433 1.2.4.2 wiz fmul_inf_dst:
8434 1.2.4.2 wiz fmovm.x DST(%a1),&0x80 # return INF result in fp0
8435 1.2.4.2 wiz mov.b SRC_EX(%a0),%d0 # exclusive or the signs
8436 1.2.4.2 wiz mov.b DST_EX(%a1),%d1
8437 1.2.4.2 wiz eor.b %d0,%d1
8438 1.2.4.2 wiz bpl.b fmul_inf_dst_p # result INF is pos.
8439 1.2.4.2 wiz fmul_inf_dst_n:
8440 1.2.4.2 wiz fabs.x %fp0 # clear result sign
8441 1.2.4.2 wiz fneg.x %fp0 # set result sign
8442 1.2.4.2 wiz mov.b &inf_bmask+neg_bmask,FPSR_CC(%a6) # set INF/N
8443 1.2.4.2 wiz rts
8444 1.2.4.2 wiz fmul_inf_dst_p:
8445 1.2.4.2 wiz fabs.x %fp0 # clear result sign
8446 1.2.4.2 wiz mov.b &inf_bmask,FPSR_CC(%a6) # set INF
8447 1.2.4.2 wiz rts
8448 1.2.4.2 wiz
8449 1.2.4.2 wiz global fmul_inf_src # global for fsglmul
8450 1.2.4.2 wiz fmul_inf_src:
8451 1.2.4.2 wiz fmovm.x SRC(%a0),&0x80 # return INF result in fp0
8452 1.2.4.2 wiz mov.b SRC_EX(%a0),%d0 # exclusive or the signs
8453 1.2.4.2 wiz mov.b DST_EX(%a1),%d1
8454 1.2.4.2 wiz eor.b %d0,%d1
8455 1.2.4.2 wiz bpl.b fmul_inf_dst_p # result INF is pos.
8456 1.2.4.2 wiz bra.b fmul_inf_dst_n
8457 1.2.4.2 wiz
8458 1.2.4.2 wiz #########################################################################
8459 1.2.4.2 wiz # XDEF **************************************************************** #
8460 1.2.4.2 wiz # fin(): emulates the fmove instruction #
8461 1.2.4.2 wiz # fsin(): emulates the fsmove instruction #
8462 1.2.4.2 wiz # fdin(): emulates the fdmove instruction #
8463 1.2.4.2 wiz # #
8464 1.2.4.2 wiz # XREF **************************************************************** #
8465 1.2.4.2 wiz # norm() - normalize mantissa for EXOP on denorm #
8466 1.2.4.2 wiz # scale_to_zero_src() - scale src exponent to zero #
8467 1.2.4.2 wiz # ovf_res() - return default overflow result #
8468 1.2.4.2 wiz # unf_res() - return default underflow result #
8469 1.2.4.2 wiz # res_qnan_1op() - return QNAN result #
8470 1.2.4.2 wiz # res_snan_1op() - return SNAN result #
8471 1.2.4.2 wiz # #
8472 1.2.4.2 wiz # INPUT *************************************************************** #
8473 1.2.4.2 wiz # a0 = pointer to extended precision source operand #
8474 1.2.4.2 wiz # d0 = round prec/mode #
8475 1.2.4.2 wiz # #
8476 1.2.4.2 wiz # OUTPUT ************************************************************** #
8477 1.2.4.2 wiz # fp0 = result #
8478 1.2.4.2 wiz # fp1 = EXOP (if exception occurred) #
8479 1.2.4.2 wiz # #
8480 1.2.4.2 wiz # ALGORITHM *********************************************************** #
8481 1.2.4.2 wiz # Handle NANs, infinities, and zeroes as special cases. Divide #
8482 1.2.4.2 wiz # norms into extended, single, and double precision. #
8483 1.2.4.2 wiz # Norms can be emulated w/ a regular fmove instruction. For #
8484 1.2.4.2 wiz # sgl/dbl, must scale exponent and perform an "fmove". Check to see #
8485 1.2.4.2 wiz # if the result would have overflowed/underflowed. If so, use unf_res() #
8486 1.2.4.2 wiz # or ovf_res() to return the default result. Also return EXOP if #
8487 1.2.4.2 wiz # exception is enabled. If no exception, return the default result. #
8488 1.2.4.2 wiz # Unnorms don't pass through here. #
8489 1.2.4.2 wiz # #
8490 1.2.4.2 wiz #########################################################################
8491 1.2.4.2 wiz
8492 1.2.4.2 wiz global fsin
8493 1.2.4.2 wiz fsin:
8494 1.2.4.2 wiz andi.b &0x30,%d0 # clear rnd prec
8495 1.2.4.2 wiz ori.b &s_mode*0x10,%d0 # insert sgl precision
8496 1.2.4.2 wiz bra.b fin
8497 1.2.4.2 wiz
8498 1.2.4.2 wiz global fdin
8499 1.2.4.2 wiz fdin:
8500 1.2.4.2 wiz andi.b &0x30,%d0 # clear rnd prec
8501 1.2.4.2 wiz ori.b &d_mode*0x10,%d0 # insert dbl precision
8502 1.2.4.2 wiz
8503 1.2.4.2 wiz global fin
8504 1.2.4.2 wiz fin:
8505 1.2.4.2 wiz mov.l %d0,L_SCR3(%a6) # store rnd info
8506 1.2.4.2 wiz
8507 1.2.4.2 wiz mov.b STAG(%a6),%d1 # fetch src optype tag
8508 1.2.4.2 wiz bne.w fin_not_norm # optimize on non-norm input
8509 1.2.4.2 wiz
8510 1.2.4.2 wiz #
8511 1.2.4.2 wiz # FP MOVE IN: NORMs and DENORMs ONLY!
8512 1.2.4.2 wiz #
8513 1.2.4.2 wiz fin_norm:
8514 1.2.4.2 wiz andi.b &0xc0,%d0 # is precision extended?
8515 1.2.4.2 wiz bne.w fin_not_ext # no, so go handle dbl or sgl
8516 1.2.4.2 wiz
8517 1.2.4.2 wiz #
8518 1.2.4.2 wiz # precision selected is extended. so...we cannot get an underflow
8519 1.2.4.2 wiz # or overflow because of rounding to the correct precision. so...
8520 1.2.4.2 wiz # skip the scaling and unscaling...
8521 1.2.4.2 wiz #
8522 1.2.4.2 wiz tst.b SRC_EX(%a0) # is the operand negative?
8523 1.2.4.2 wiz bpl.b fin_norm_done # no
8524 1.2.4.2 wiz bset &neg_bit,FPSR_CC(%a6) # yes, so set 'N' ccode bit
8525 1.2.4.2 wiz fin_norm_done:
8526 1.2.4.2 wiz fmovm.x SRC(%a0),&0x80 # return result in fp0
8527 1.2.4.2 wiz rts
8528 1.2.4.2 wiz
8529 1.2.4.2 wiz #
8530 1.2.4.2 wiz # for an extended precision DENORM, the UNFL exception bit is set
8531 1.2.4.2 wiz # the accrued bit is NOT set in this instance(no inexactness!)
8532 1.2.4.2 wiz #
8533 1.2.4.2 wiz fin_denorm:
8534 1.2.4.2 wiz andi.b &0xc0,%d0 # is precision extended?
8535 1.2.4.2 wiz bne.w fin_not_ext # no, so go handle dbl or sgl
8536 1.2.4.2 wiz
8537 1.2.4.2 wiz bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
8538 1.2.4.2 wiz tst.b SRC_EX(%a0) # is the operand negative?
8539 1.2.4.2 wiz bpl.b fin_denorm_done # no
8540 1.2.4.2 wiz bset &neg_bit,FPSR_CC(%a6) # yes, so set 'N' ccode bit
8541 1.2.4.2 wiz fin_denorm_done:
8542 1.2.4.2 wiz fmovm.x SRC(%a0),&0x80 # return result in fp0
8543 1.2.4.2 wiz btst &unfl_bit,FPCR_ENABLE(%a6) # is UNFL enabled?
8544 1.2.4.2 wiz bne.b fin_denorm_unfl_ena # yes
8545 1.2.4.2 wiz rts
8546 1.2.4.2 wiz
8547 1.2.4.2 wiz #
8548 1.2.4.2 wiz # the input is an extended DENORM and underflow is enabled in the FPCR.
8549 1.2.4.2 wiz # normalize the mantissa and add the bias of 0x6000 to the resulting negative
8550 1.2.4.2 wiz # exponent and insert back into the operand.
8551 1.2.4.2 wiz #
8552 1.2.4.2 wiz fin_denorm_unfl_ena:
8553 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
8554 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
8555 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
8556 1.2.4.2 wiz lea FP_SCR0(%a6),%a0 # pass: ptr to operand
8557 1.2.4.2 wiz bsr.l norm # normalize result
8558 1.2.4.2 wiz neg.w %d0 # new exponent = -(shft val)
8559 1.2.4.2 wiz addi.w &0x6000,%d0 # add new bias to exponent
8560 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # fetch old sign,exp
8561 1.2.4.2 wiz andi.w &0x8000,%d1 # keep old sign
8562 1.2.4.2 wiz andi.w &0x7fff,%d0 # clear sign position
8563 1.2.4.2 wiz or.w %d1,%d0 # concat new exo,old sign
8564 1.2.4.2 wiz mov.w %d0,FP_SCR0_EX(%a6) # insert new exponent
8565 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
8566 1.2.4.2 wiz rts
8567 1.2.4.2 wiz
8568 1.2.4.2 wiz #
8569 1.2.4.2 wiz # operand is to be rounded to single or double precision
8570 1.2.4.2 wiz #
8571 1.2.4.2 wiz fin_not_ext:
8572 1.2.4.2 wiz cmpi.b %d0,&s_mode*0x10 # separate sgl/dbl prec
8573 1.2.4.2 wiz bne.b fin_dbl
8574 1.2.4.2 wiz
8575 1.2.4.2 wiz #
8576 1.2.4.2 wiz # operand is to be rounded to single precision
8577 1.2.4.2 wiz #
8578 1.2.4.2 wiz fin_sgl:
8579 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
8580 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
8581 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
8582 1.2.4.2 wiz bsr.l scale_to_zero_src # calculate scale factor
8583 1.2.4.2 wiz
8584 1.2.4.2 wiz cmpi.l %d0,&0x3fff-0x3f80 # will move in underflow?
8585 1.2.4.2 wiz bge.w fin_sd_unfl # yes; go handle underflow
8586 1.2.4.2 wiz cmpi.l %d0,&0x3fff-0x407e # will move in overflow?
8587 1.2.4.2 wiz beq.w fin_sd_may_ovfl # maybe; go check
8588 1.2.4.2 wiz blt.w fin_sd_ovfl # yes; go handle overflow
8589 1.2.4.2 wiz
8590 1.2.4.2 wiz #
8591 1.2.4.2 wiz # operand will NOT overflow or underflow when moved into the fp reg file
8592 1.2.4.2 wiz #
8593 1.2.4.2 wiz fin_sd_normal:
8594 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
8595 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
8596 1.2.4.2 wiz
8597 1.2.4.2 wiz fmov.x FP_SCR0(%a6),%fp0 # perform move
8598 1.2.4.2 wiz
8599 1.2.4.2 wiz fmov.l %fpsr,%d1 # save FPSR
8600 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
8601 1.2.4.2 wiz
8602 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
8603 1.2.4.2 wiz
8604 1.2.4.2 wiz fin_sd_normal_exit:
8605 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
8606 1.2.4.2 wiz fmovm.x &0x80,FP_SCR0(%a6) # store out result
8607 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # load {sgn,exp}
8608 1.2.4.2 wiz mov.w %d1,%d2 # make a copy
8609 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
8610 1.2.4.2 wiz sub.l %d0,%d1 # add scale factor
8611 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
8612 1.2.4.2 wiz or.w %d1,%d2 # concat old sign,new exponent
8613 1.2.4.2 wiz mov.w %d2,FP_SCR0_EX(%a6) # insert new exponent
8614 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
8615 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
8616 1.2.4.2 wiz rts
8617 1.2.4.2 wiz
8618 1.2.4.2 wiz #
8619 1.2.4.2 wiz # operand is to be rounded to double precision
8620 1.2.4.2 wiz #
8621 1.2.4.2 wiz fin_dbl:
8622 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
8623 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
8624 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
8625 1.2.4.2 wiz bsr.l scale_to_zero_src # calculate scale factor
8626 1.2.4.2 wiz
8627 1.2.4.2 wiz cmpi.l %d0,&0x3fff-0x3c00 # will move in underflow?
8628 1.2.4.2 wiz bge.w fin_sd_unfl # yes; go handle underflow
8629 1.2.4.2 wiz cmpi.l %d0,&0x3fff-0x43fe # will move in overflow?
8630 1.2.4.2 wiz beq.w fin_sd_may_ovfl # maybe; go check
8631 1.2.4.2 wiz blt.w fin_sd_ovfl # yes; go handle overflow
8632 1.2.4.2 wiz bra.w fin_sd_normal # no; ho handle normalized op
8633 1.2.4.2 wiz
8634 1.2.4.2 wiz #
8635 1.2.4.2 wiz # operand WILL underflow when moved in to the fp register file
8636 1.2.4.2 wiz #
8637 1.2.4.2 wiz fin_sd_unfl:
8638 1.2.4.2 wiz bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
8639 1.2.4.2 wiz
8640 1.2.4.2 wiz tst.b FP_SCR0_EX(%a6) # is operand negative?
8641 1.2.4.2 wiz bpl.b fin_sd_unfl_tst
8642 1.2.4.2 wiz bset &neg_bit,FPSR_CC(%a6) # set 'N' ccode bit
8643 1.2.4.2 wiz
8644 1.2.4.2 wiz # if underflow or inexact is enabled, then go calculate the EXOP first.
8645 1.2.4.2 wiz fin_sd_unfl_tst:
8646 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d1
8647 1.2.4.2 wiz andi.b &0x0b,%d1 # is UNFL or INEX enabled?
8648 1.2.4.2 wiz bne.b fin_sd_unfl_ena # yes
8649 1.2.4.2 wiz
8650 1.2.4.2 wiz fin_sd_unfl_dis:
8651 1.2.4.2 wiz lea FP_SCR0(%a6),%a0 # pass: result addr
8652 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
8653 1.2.4.2 wiz bsr.l unf_res # calculate default result
8654 1.2.4.2 wiz or.b %d0,FPSR_CC(%a6) # unf_res may have set 'Z'
8655 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
8656 1.2.4.2 wiz rts
8657 1.2.4.2 wiz
8658 1.2.4.2 wiz #
8659 1.2.4.2 wiz # operand will underflow AND underflow or inexact is enabled.
8660 1.2.4.2 wiz # therefore, we must return the result rounded to extended precision.
8661 1.2.4.2 wiz #
8662 1.2.4.2 wiz fin_sd_unfl_ena:
8663 1.2.4.2 wiz mov.l FP_SCR0_HI(%a6),FP_SCR1_HI(%a6)
8664 1.2.4.2 wiz mov.l FP_SCR0_LO(%a6),FP_SCR1_LO(%a6)
8665 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # load current exponent
8666 1.2.4.2 wiz
8667 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
8668 1.2.4.2 wiz mov.w %d1,%d2 # make a copy
8669 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
8670 1.2.4.2 wiz sub.l %d0,%d1 # subtract scale factor
8671 1.2.4.2 wiz andi.w &0x8000,%d2 # extract old sign
8672 1.2.4.2 wiz addi.l &0x6000,%d1 # add new bias
8673 1.2.4.2 wiz andi.w &0x7fff,%d1
8674 1.2.4.2 wiz or.w %d1,%d2 # concat old sign,new exp
8675 1.2.4.2 wiz mov.w %d2,FP_SCR1_EX(%a6) # insert new exponent
8676 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x40 # return EXOP in fp1
8677 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
8678 1.2.4.2 wiz bra.b fin_sd_unfl_dis
8679 1.2.4.2 wiz
8680 1.2.4.2 wiz #
8681 1.2.4.2 wiz # operand WILL overflow.
8682 1.2.4.2 wiz #
8683 1.2.4.2 wiz fin_sd_ovfl:
8684 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
8685 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
8686 1.2.4.2 wiz
8687 1.2.4.2 wiz fmov.x FP_SCR0(%a6),%fp0 # perform move
8688 1.2.4.2 wiz
8689 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
8690 1.2.4.2 wiz fmov.l %fpsr,%d1 # save FPSR
8691 1.2.4.2 wiz
8692 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
8693 1.2.4.2 wiz
8694 1.2.4.2 wiz fin_sd_ovfl_tst:
8695 1.2.4.2 wiz or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
8696 1.2.4.2 wiz
8697 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d1
8698 1.2.4.2 wiz andi.b &0x13,%d1 # is OVFL or INEX enabled?
8699 1.2.4.2 wiz bne.b fin_sd_ovfl_ena # yes
8700 1.2.4.2 wiz
8701 1.2.4.2 wiz #
8702 1.2.4.2 wiz # OVFL is not enabled; therefore, we must create the default result by
8703 1.2.4.2 wiz # calling ovf_res().
8704 1.2.4.2 wiz #
8705 1.2.4.2 wiz fin_sd_ovfl_dis:
8706 1.2.4.2 wiz btst &neg_bit,FPSR_CC(%a6) # is result negative?
8707 1.2.4.2 wiz sne %d1 # set sign param accordingly
8708 1.2.4.2 wiz mov.l L_SCR3(%a6),%d0 # pass: prec,mode
8709 1.2.4.2 wiz bsr.l ovf_res # calculate default result
8710 1.2.4.2 wiz or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
8711 1.2.4.2 wiz fmovm.x (%a0),&0x80 # return default result in fp0
8712 1.2.4.2 wiz rts
8713 1.2.4.2 wiz
8714 1.2.4.2 wiz #
8715 1.2.4.2 wiz # OVFL is enabled.
8716 1.2.4.2 wiz # the INEX2 bit has already been updated by the round to the correct precision.
8717 1.2.4.2 wiz # now, round to extended(and don't alter the FPSR).
8718 1.2.4.2 wiz #
8719 1.2.4.2 wiz fin_sd_ovfl_ena:
8720 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
8721 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
8722 1.2.4.2 wiz mov.l %d1,%d2 # make a copy
8723 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
8724 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
8725 1.2.4.2 wiz sub.l %d0,%d1 # add scale factor
8726 1.2.4.2 wiz sub.l &0x6000,%d1 # subtract bias
8727 1.2.4.2 wiz andi.w &0x7fff,%d1
8728 1.2.4.2 wiz or.w %d2,%d1
8729 1.2.4.2 wiz mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
8730 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
8731 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
8732 1.2.4.2 wiz bra.b fin_sd_ovfl_dis
8733 1.2.4.2 wiz
8734 1.2.4.2 wiz #
8735 1.2.4.2 wiz # the move in MAY overflow. so...
8736 1.2.4.2 wiz #
8737 1.2.4.2 wiz fin_sd_may_ovfl:
8738 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
8739 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
8740 1.2.4.2 wiz
8741 1.2.4.2 wiz fmov.x FP_SCR0(%a6),%fp0 # perform the move
8742 1.2.4.2 wiz
8743 1.2.4.2 wiz fmov.l %fpsr,%d1 # save status
8744 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
8745 1.2.4.2 wiz
8746 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
8747 1.2.4.2 wiz
8748 1.2.4.2 wiz fabs.x %fp0,%fp1 # make a copy of result
8749 1.2.4.2 wiz fcmp.b %fp1,&0x2 # is |result| >= 2.b?
8750 1.2.4.2 wiz fbge.w fin_sd_ovfl_tst # yes; overflow has occurred
8751 1.2.4.2 wiz
8752 1.2.4.2 wiz # no, it didn't overflow; we have correct result
8753 1.2.4.2 wiz bra.w fin_sd_normal_exit
8754 1.2.4.2 wiz
8755 1.2.4.2 wiz ##########################################################################
8756 1.2.4.2 wiz
8757 1.2.4.2 wiz #
8758 1.2.4.2 wiz # operand is not a NORM: check its optype and branch accordingly
8759 1.2.4.2 wiz #
8760 1.2.4.2 wiz fin_not_norm:
8761 1.2.4.2 wiz cmpi.b %d1,&DENORM # weed out DENORM
8762 1.2.4.2 wiz beq.w fin_denorm
8763 1.2.4.2 wiz cmpi.b %d1,&SNAN # weed out SNANs
8764 1.2.4.2 wiz beq.l res_snan_1op
8765 1.2.4.2 wiz cmpi.b %d1,&QNAN # weed out QNANs
8766 1.2.4.2 wiz beq.l res_qnan_1op
8767 1.2.4.2 wiz
8768 1.2.4.2 wiz #
8769 1.2.4.2 wiz # do the fmove in; at this point, only possible ops are ZERO and INF.
8770 1.2.4.2 wiz # use fmov to determine ccodes.
8771 1.2.4.2 wiz # prec:mode should be zero at this point but it won't affect answer anyways.
8772 1.2.4.2 wiz #
8773 1.2.4.2 wiz fmov.x SRC(%a0),%fp0 # do fmove in
8774 1.2.4.2 wiz fmov.l %fpsr,%d0 # no exceptions possible
8775 1.2.4.2 wiz rol.l &0x8,%d0 # put ccodes in lo byte
8776 1.2.4.2 wiz mov.b %d0,FPSR_CC(%a6) # insert correct ccodes
8777 1.2.4.2 wiz rts
8778 1.2.4.2 wiz
8779 1.2.4.2 wiz #########################################################################
8780 1.2.4.2 wiz # XDEF **************************************************************** #
8781 1.2.4.2 wiz # fdiv(): emulates the fdiv instruction #
8782 1.2.4.2 wiz # fsdiv(): emulates the fsdiv instruction #
8783 1.2.4.2 wiz # fddiv(): emulates the fddiv instruction #
8784 1.2.4.2 wiz # #
8785 1.2.4.2 wiz # XREF **************************************************************** #
8786 1.2.4.2 wiz # scale_to_zero_src() - scale src exponent to zero #
8787 1.2.4.2 wiz # scale_to_zero_dst() - scale dst exponent to zero #
8788 1.2.4.2 wiz # unf_res() - return default underflow result #
8789 1.2.4.2 wiz # ovf_res() - return default overflow result #
8790 1.2.4.2 wiz # res_qnan() - return QNAN result #
8791 1.2.4.2 wiz # res_snan() - return SNAN result #
8792 1.2.4.2 wiz # #
8793 1.2.4.2 wiz # INPUT *************************************************************** #
8794 1.2.4.2 wiz # a0 = pointer to extended precision source operand #
8795 1.2.4.2 wiz # a1 = pointer to extended precision destination operand #
8796 1.2.4.2 wiz # d0 rnd prec,mode #
8797 1.2.4.2 wiz # #
8798 1.2.4.2 wiz # OUTPUT ************************************************************** #
8799 1.2.4.2 wiz # fp0 = result #
8800 1.2.4.2 wiz # fp1 = EXOP (if exception occurred) #
8801 1.2.4.2 wiz # #
8802 1.2.4.2 wiz # ALGORITHM *********************************************************** #
8803 1.2.4.2 wiz # Handle NANs, infinities, and zeroes as special cases. Divide #
8804 1.2.4.2 wiz # norms/denorms into ext/sgl/dbl precision. #
8805 1.2.4.2 wiz # For norms/denorms, scale the exponents such that a divide #
8806 1.2.4.2 wiz # instruction won't cause an exception. Use the regular fdiv to #
8807 1.2.4.2 wiz # compute a result. Check if the regular operands would have taken #
8808 1.2.4.2 wiz # an exception. If so, return the default overflow/underflow result #
8809 1.2.4.2 wiz # and return the EXOP if exceptions are enabled. Else, scale the #
8810 1.2.4.2 wiz # result operand to the proper exponent. #
8811 1.2.4.2 wiz # #
8812 1.2.4.2 wiz #########################################################################
8813 1.2.4.2 wiz
8814 1.2.4.2 wiz align 0x10
8815 1.2.4.2 wiz tbl_fdiv_unfl:
8816 1.2.4.2 wiz long 0x3fff - 0x0000 # ext_unfl
8817 1.2.4.2 wiz long 0x3fff - 0x3f81 # sgl_unfl
8818 1.2.4.2 wiz long 0x3fff - 0x3c01 # dbl_unfl
8819 1.2.4.2 wiz
8820 1.2.4.2 wiz tbl_fdiv_ovfl:
8821 1.2.4.2 wiz long 0x3fff - 0x7ffe # ext overflow exponent
8822 1.2.4.2 wiz long 0x3fff - 0x407e # sgl overflow exponent
8823 1.2.4.2 wiz long 0x3fff - 0x43fe # dbl overflow exponent
8824 1.2.4.2 wiz
8825 1.2.4.2 wiz global fsdiv
8826 1.2.4.2 wiz fsdiv:
8827 1.2.4.2 wiz andi.b &0x30,%d0 # clear rnd prec
8828 1.2.4.2 wiz ori.b &s_mode*0x10,%d0 # insert sgl prec
8829 1.2.4.2 wiz bra.b fdiv
8830 1.2.4.2 wiz
8831 1.2.4.2 wiz global fddiv
8832 1.2.4.2 wiz fddiv:
8833 1.2.4.2 wiz andi.b &0x30,%d0 # clear rnd prec
8834 1.2.4.2 wiz ori.b &d_mode*0x10,%d0 # insert dbl prec
8835 1.2.4.2 wiz
8836 1.2.4.2 wiz global fdiv
8837 1.2.4.2 wiz fdiv:
8838 1.2.4.2 wiz mov.l %d0,L_SCR3(%a6) # store rnd info
8839 1.2.4.2 wiz
8840 1.2.4.2 wiz clr.w %d1
8841 1.2.4.2 wiz mov.b DTAG(%a6),%d1
8842 1.2.4.2 wiz lsl.b &0x3,%d1
8843 1.2.4.2 wiz or.b STAG(%a6),%d1 # combine src tags
8844 1.2.4.2 wiz
8845 1.2.4.2 wiz bne.w fdiv_not_norm # optimize on non-norm input
8846 1.2.4.2 wiz
8847 1.2.4.2 wiz #
8848 1.2.4.2 wiz # DIVIDE: NORMs and DENORMs ONLY!
8849 1.2.4.2 wiz #
8850 1.2.4.2 wiz fdiv_norm:
8851 1.2.4.2 wiz mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
8852 1.2.4.2 wiz mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
8853 1.2.4.2 wiz mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
8854 1.2.4.2 wiz
8855 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
8856 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
8857 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
8858 1.2.4.2 wiz
8859 1.2.4.2 wiz bsr.l scale_to_zero_src # scale src exponent
8860 1.2.4.2 wiz mov.l %d0,-(%sp) # save scale factor 1
8861 1.2.4.2 wiz
8862 1.2.4.2 wiz bsr.l scale_to_zero_dst # scale dst exponent
8863 1.2.4.2 wiz
8864 1.2.4.2 wiz neg.l (%sp) # SCALE FACTOR = scale1 - scale2
8865 1.2.4.2 wiz add.l %d0,(%sp)
8866 1.2.4.2 wiz
8867 1.2.4.2 wiz mov.w 2+L_SCR3(%a6),%d1 # fetch precision
8868 1.2.4.2 wiz lsr.b &0x6,%d1 # shift to lo bits
8869 1.2.4.2 wiz mov.l (%sp)+,%d0 # load S.F.
8870 1.2.4.2 wiz cmp.l %d0,(tbl_fdiv_ovfl.b,%pc,%d1.w*4) # will result overflow?
8871 1.2.4.2 wiz ble.w fdiv_may_ovfl # result will overflow
8872 1.2.4.2 wiz
8873 1.2.4.2 wiz cmp.l %d0,(tbl_fdiv_unfl.w,%pc,%d1.w*4) # will result underflow?
8874 1.2.4.2 wiz beq.w fdiv_may_unfl # maybe
8875 1.2.4.2 wiz bgt.w fdiv_unfl # yes; go handle underflow
8876 1.2.4.2 wiz
8877 1.2.4.2 wiz fdiv_normal:
8878 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst op
8879 1.2.4.2 wiz
8880 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # save FPCR
8881 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
8882 1.2.4.2 wiz
8883 1.2.4.2 wiz fdiv.x FP_SCR0(%a6),%fp0 # perform divide
8884 1.2.4.2 wiz
8885 1.2.4.2 wiz fmov.l %fpsr,%d1 # save FPSR
8886 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
8887 1.2.4.2 wiz
8888 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
8889 1.2.4.2 wiz
8890 1.2.4.2 wiz fdiv_normal_exit:
8891 1.2.4.2 wiz fmovm.x &0x80,FP_SCR0(%a6) # store result on stack
8892 1.2.4.2 wiz mov.l %d2,-(%sp) # store d2
8893 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # load {sgn,exp}
8894 1.2.4.2 wiz mov.l %d1,%d2 # make a copy
8895 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
8896 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
8897 1.2.4.2 wiz sub.l %d0,%d1 # add scale factor
8898 1.2.4.2 wiz or.w %d2,%d1 # concat old sign,new exp
8899 1.2.4.2 wiz mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
8900 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
8901 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
8902 1.2.4.2 wiz rts
8903 1.2.4.2 wiz
8904 1.2.4.2 wiz tbl_fdiv_ovfl2:
8905 1.2.4.2 wiz long 0x7fff
8906 1.2.4.2 wiz long 0x407f
8907 1.2.4.2 wiz long 0x43ff
8908 1.2.4.2 wiz
8909 1.2.4.2 wiz fdiv_no_ovfl:
8910 1.2.4.2 wiz mov.l (%sp)+,%d0 # restore scale factor
8911 1.2.4.2 wiz bra.b fdiv_normal_exit
8912 1.2.4.2 wiz
8913 1.2.4.2 wiz fdiv_may_ovfl:
8914 1.2.4.2 wiz mov.l %d0,-(%sp) # save scale factor
8915 1.2.4.2 wiz
8916 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst op
8917 1.2.4.2 wiz
8918 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
8919 1.2.4.2 wiz fmov.l &0x0,%fpsr # set FPSR
8920 1.2.4.2 wiz
8921 1.2.4.2 wiz fdiv.x FP_SCR0(%a6),%fp0 # execute divide
8922 1.2.4.2 wiz
8923 1.2.4.2 wiz fmov.l %fpsr,%d0
8924 1.2.4.2 wiz fmov.l &0x0,%fpcr
8925 1.2.4.2 wiz
8926 1.2.4.2 wiz or.l %d0,USER_FPSR(%a6) # save INEX,N
8927 1.2.4.2 wiz
8928 1.2.4.2 wiz fmovm.x &0x01,-(%sp) # save result to stack
8929 1.2.4.2 wiz mov.w (%sp),%d0 # fetch new exponent
8930 1.2.4.2 wiz add.l &0xc,%sp # clear result from stack
8931 1.2.4.2 wiz andi.l &0x7fff,%d0 # strip sign
8932 1.2.4.2 wiz sub.l (%sp),%d0 # add scale factor
8933 1.2.4.2 wiz cmp.l %d0,(tbl_fdiv_ovfl2.b,%pc,%d1.w*4)
8934 1.2.4.2 wiz blt.b fdiv_no_ovfl
8935 1.2.4.2 wiz mov.l (%sp)+,%d0
8936 1.2.4.2 wiz
8937 1.2.4.2 wiz fdiv_ovfl_tst:
8938 1.2.4.2 wiz or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
8939 1.2.4.2 wiz
8940 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d1
8941 1.2.4.2 wiz andi.b &0x13,%d1 # is OVFL or INEX enabled?
8942 1.2.4.2 wiz bne.b fdiv_ovfl_ena # yes
8943 1.2.4.2 wiz
8944 1.2.4.2 wiz fdiv_ovfl_dis:
8945 1.2.4.2 wiz btst &neg_bit,FPSR_CC(%a6) # is result negative?
8946 1.2.4.2 wiz sne %d1 # set sign param accordingly
8947 1.2.4.2 wiz mov.l L_SCR3(%a6),%d0 # pass prec:rnd
8948 1.2.4.2 wiz bsr.l ovf_res # calculate default result
8949 1.2.4.2 wiz or.b %d0,FPSR_CC(%a6) # set INF if applicable
8950 1.2.4.2 wiz fmovm.x (%a0),&0x80 # return default result in fp0
8951 1.2.4.2 wiz rts
8952 1.2.4.2 wiz
8953 1.2.4.2 wiz fdiv_ovfl_ena:
8954 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1
8955 1.2.4.2 wiz andi.b &0xc0,%d1 # is precision extended?
8956 1.2.4.2 wiz bne.b fdiv_ovfl_ena_sd # no, do sgl or dbl
8957 1.2.4.2 wiz
8958 1.2.4.2 wiz fdiv_ovfl_ena_cont:
8959 1.2.4.2 wiz fmovm.x &0x80,FP_SCR0(%a6) # move result to stack
8960 1.2.4.2 wiz
8961 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
8962 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
8963 1.2.4.2 wiz mov.w %d1,%d2 # make a copy
8964 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
8965 1.2.4.2 wiz sub.l %d0,%d1 # add scale factor
8966 1.2.4.2 wiz subi.l &0x6000,%d1 # subtract bias
8967 1.2.4.2 wiz andi.w &0x7fff,%d1 # clear sign bit
8968 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
8969 1.2.4.2 wiz or.w %d2,%d1 # concat old sign,new exp
8970 1.2.4.2 wiz mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
8971 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
8972 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
8973 1.2.4.2 wiz bra.b fdiv_ovfl_dis
8974 1.2.4.2 wiz
8975 1.2.4.2 wiz fdiv_ovfl_ena_sd:
8976 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst operand
8977 1.2.4.2 wiz
8978 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1
8979 1.2.4.2 wiz andi.b &0x30,%d1 # keep rnd mode
8980 1.2.4.2 wiz fmov.l %d1,%fpcr # set FPCR
8981 1.2.4.2 wiz
8982 1.2.4.2 wiz fdiv.x FP_SCR0(%a6),%fp0 # execute divide
8983 1.2.4.2 wiz
8984 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
8985 1.2.4.2 wiz bra.b fdiv_ovfl_ena_cont
8986 1.2.4.2 wiz
8987 1.2.4.2 wiz fdiv_unfl:
8988 1.2.4.2 wiz bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
8989 1.2.4.2 wiz
8990 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst op
8991 1.2.4.2 wiz
8992 1.2.4.2 wiz fmov.l &rz_mode*0x10,%fpcr # set FPCR
8993 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
8994 1.2.4.2 wiz
8995 1.2.4.2 wiz fdiv.x FP_SCR0(%a6),%fp0 # execute divide
8996 1.2.4.2 wiz
8997 1.2.4.2 wiz fmov.l %fpsr,%d1 # save status
8998 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
8999 1.2.4.2 wiz
9000 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
9001 1.2.4.2 wiz
9002 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d1
9003 1.2.4.2 wiz andi.b &0x0b,%d1 # is UNFL or INEX enabled?
9004 1.2.4.2 wiz bne.b fdiv_unfl_ena # yes
9005 1.2.4.2 wiz
9006 1.2.4.2 wiz fdiv_unfl_dis:
9007 1.2.4.2 wiz fmovm.x &0x80,FP_SCR0(%a6) # store out result
9008 1.2.4.2 wiz
9009 1.2.4.2 wiz lea FP_SCR0(%a6),%a0 # pass: result addr
9010 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
9011 1.2.4.2 wiz bsr.l unf_res # calculate default result
9012 1.2.4.2 wiz or.b %d0,FPSR_CC(%a6) # 'Z' may have been set
9013 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
9014 1.2.4.2 wiz rts
9015 1.2.4.2 wiz
9016 1.2.4.2 wiz #
9017 1.2.4.2 wiz # UNFL is enabled.
9018 1.2.4.2 wiz #
9019 1.2.4.2 wiz fdiv_unfl_ena:
9020 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x40 # load dst op
9021 1.2.4.2 wiz
9022 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1
9023 1.2.4.2 wiz andi.b &0xc0,%d1 # is precision extended?
9024 1.2.4.2 wiz bne.b fdiv_unfl_ena_sd # no, sgl or dbl
9025 1.2.4.2 wiz
9026 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
9027 1.2.4.2 wiz
9028 1.2.4.2 wiz fdiv_unfl_ena_cont:
9029 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
9030 1.2.4.2 wiz
9031 1.2.4.2 wiz fdiv.x FP_SCR0(%a6),%fp1 # execute divide
9032 1.2.4.2 wiz
9033 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
9034 1.2.4.2 wiz
9035 1.2.4.2 wiz fmovm.x &0x40,FP_SCR0(%a6) # save result to stack
9036 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
9037 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
9038 1.2.4.2 wiz mov.l %d1,%d2 # make a copy
9039 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
9040 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
9041 1.2.4.2 wiz sub.l %d0,%d1 # add scale factoer
9042 1.2.4.2 wiz addi.l &0x6000,%d1 # add bias
9043 1.2.4.2 wiz andi.w &0x7fff,%d1
9044 1.2.4.2 wiz or.w %d2,%d1 # concat old sign,new exp
9045 1.2.4.2 wiz mov.w %d1,FP_SCR0_EX(%a6) # insert new exp
9046 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
9047 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
9048 1.2.4.2 wiz bra.w fdiv_unfl_dis
9049 1.2.4.2 wiz
9050 1.2.4.2 wiz fdiv_unfl_ena_sd:
9051 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1
9052 1.2.4.2 wiz andi.b &0x30,%d1 # use only rnd mode
9053 1.2.4.2 wiz fmov.l %d1,%fpcr # set FPCR
9054 1.2.4.2 wiz
9055 1.2.4.2 wiz bra.b fdiv_unfl_ena_cont
9056 1.2.4.2 wiz
9057 1.2.4.2 wiz #
9058 1.2.4.2 wiz # the divide operation MAY underflow:
9059 1.2.4.2 wiz #
9060 1.2.4.2 wiz fdiv_may_unfl:
9061 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst op
9062 1.2.4.2 wiz
9063 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
9064 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
9065 1.2.4.2 wiz
9066 1.2.4.2 wiz fdiv.x FP_SCR0(%a6),%fp0 # execute divide
9067 1.2.4.2 wiz
9068 1.2.4.2 wiz fmov.l %fpsr,%d1 # save status
9069 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
9070 1.2.4.2 wiz
9071 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
9072 1.2.4.2 wiz
9073 1.2.4.2 wiz fabs.x %fp0,%fp1 # make a copy of result
9074 1.2.4.2 wiz fcmp.b %fp1,&0x1 # is |result| > 1.b?
9075 1.2.4.2 wiz fbgt.w fdiv_normal_exit # no; no underflow occurred
9076 1.2.4.2 wiz fblt.w fdiv_unfl # yes; underflow occurred
9077 1.2.4.2 wiz
9078 1.2.4.2 wiz #
9079 1.2.4.2 wiz # we still don't know if underflow occurred. result is ~ equal to 1. but,
9080 1.2.4.2 wiz # we don't know if the result was an underflow that rounded up to a 1
9081 1.2.4.2 wiz # or a normalized number that rounded down to a 1. so, redo the entire
9082 1.2.4.2 wiz # operation using RZ as the rounding mode to see what the pre-rounded
9083 1.2.4.2 wiz # result is. this case should be relatively rare.
9084 1.2.4.2 wiz #
9085 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x40 # load dst op into fp1
9086 1.2.4.2 wiz
9087 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1
9088 1.2.4.2 wiz andi.b &0xc0,%d1 # keep rnd prec
9089 1.2.4.2 wiz ori.b &rz_mode*0x10,%d1 # insert RZ
9090 1.2.4.2 wiz
9091 1.2.4.2 wiz fmov.l %d1,%fpcr # set FPCR
9092 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
9093 1.2.4.2 wiz
9094 1.2.4.2 wiz fdiv.x FP_SCR0(%a6),%fp1 # execute divide
9095 1.2.4.2 wiz
9096 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
9097 1.2.4.2 wiz fabs.x %fp1 # make absolute value
9098 1.2.4.2 wiz fcmp.b %fp1,&0x1 # is |result| < 1.b?
9099 1.2.4.2 wiz fbge.w fdiv_normal_exit # no; no underflow occurred
9100 1.2.4.2 wiz bra.w fdiv_unfl # yes; underflow occurred
9101 1.2.4.2 wiz
9102 1.2.4.2 wiz ############################################################################
9103 1.2.4.2 wiz
9104 1.2.4.2 wiz #
9105 1.2.4.2 wiz # Divide: inputs are not both normalized; what are they?
9106 1.2.4.2 wiz #
9107 1.2.4.2 wiz fdiv_not_norm:
9108 1.2.4.2 wiz mov.w (tbl_fdiv_op.b,%pc,%d1.w*2),%d1
9109 1.2.4.2 wiz jmp (tbl_fdiv_op.b,%pc,%d1.w*1)
9110 1.2.4.2 wiz
9111 1.2.4.2 wiz swbeg &48
9112 1.2.4.2 wiz tbl_fdiv_op:
9113 1.2.4.2 wiz short fdiv_norm - tbl_fdiv_op # NORM / NORM
9114 1.2.4.2 wiz short fdiv_inf_load - tbl_fdiv_op # NORM / ZERO
9115 1.2.4.2 wiz short fdiv_zero_load - tbl_fdiv_op # NORM / INF
9116 1.2.4.2 wiz short fdiv_res_qnan - tbl_fdiv_op # NORM / QNAN
9117 1.2.4.2 wiz short fdiv_norm - tbl_fdiv_op # NORM / DENORM
9118 1.2.4.2 wiz short fdiv_res_snan - tbl_fdiv_op # NORM / SNAN
9119 1.2.4.2 wiz short tbl_fdiv_op - tbl_fdiv_op #
9120 1.2.4.2 wiz short tbl_fdiv_op - tbl_fdiv_op #
9121 1.2.4.2 wiz
9122 1.2.4.2 wiz short fdiv_zero_load - tbl_fdiv_op # ZERO / NORM
9123 1.2.4.2 wiz short fdiv_res_operr - tbl_fdiv_op # ZERO / ZERO
9124 1.2.4.2 wiz short fdiv_zero_load - tbl_fdiv_op # ZERO / INF
9125 1.2.4.2 wiz short fdiv_res_qnan - tbl_fdiv_op # ZERO / QNAN
9126 1.2.4.2 wiz short fdiv_zero_load - tbl_fdiv_op # ZERO / DENORM
9127 1.2.4.2 wiz short fdiv_res_snan - tbl_fdiv_op # ZERO / SNAN
9128 1.2.4.2 wiz short tbl_fdiv_op - tbl_fdiv_op #
9129 1.2.4.2 wiz short tbl_fdiv_op - tbl_fdiv_op #
9130 1.2.4.2 wiz
9131 1.2.4.2 wiz short fdiv_inf_dst - tbl_fdiv_op # INF / NORM
9132 1.2.4.2 wiz short fdiv_inf_dst - tbl_fdiv_op # INF / ZERO
9133 1.2.4.2 wiz short fdiv_res_operr - tbl_fdiv_op # INF / INF
9134 1.2.4.2 wiz short fdiv_res_qnan - tbl_fdiv_op # INF / QNAN
9135 1.2.4.2 wiz short fdiv_inf_dst - tbl_fdiv_op # INF / DENORM
9136 1.2.4.2 wiz short fdiv_res_snan - tbl_fdiv_op # INF / SNAN
9137 1.2.4.2 wiz short tbl_fdiv_op - tbl_fdiv_op #
9138 1.2.4.2 wiz short tbl_fdiv_op - tbl_fdiv_op #
9139 1.2.4.2 wiz
9140 1.2.4.2 wiz short fdiv_res_qnan - tbl_fdiv_op # QNAN / NORM
9141 1.2.4.2 wiz short fdiv_res_qnan - tbl_fdiv_op # QNAN / ZERO
9142 1.2.4.2 wiz short fdiv_res_qnan - tbl_fdiv_op # QNAN / INF
9143 1.2.4.2 wiz short fdiv_res_qnan - tbl_fdiv_op # QNAN / QNAN
9144 1.2.4.2 wiz short fdiv_res_qnan - tbl_fdiv_op # QNAN / DENORM
9145 1.2.4.2 wiz short fdiv_res_snan - tbl_fdiv_op # QNAN / SNAN
9146 1.2.4.2 wiz short tbl_fdiv_op - tbl_fdiv_op #
9147 1.2.4.2 wiz short tbl_fdiv_op - tbl_fdiv_op #
9148 1.2.4.2 wiz
9149 1.2.4.2 wiz short fdiv_norm - tbl_fdiv_op # DENORM / NORM
9150 1.2.4.2 wiz short fdiv_inf_load - tbl_fdiv_op # DENORM / ZERO
9151 1.2.4.2 wiz short fdiv_zero_load - tbl_fdiv_op # DENORM / INF
9152 1.2.4.2 wiz short fdiv_res_qnan - tbl_fdiv_op # DENORM / QNAN
9153 1.2.4.2 wiz short fdiv_norm - tbl_fdiv_op # DENORM / DENORM
9154 1.2.4.2 wiz short fdiv_res_snan - tbl_fdiv_op # DENORM / SNAN
9155 1.2.4.2 wiz short tbl_fdiv_op - tbl_fdiv_op #
9156 1.2.4.2 wiz short tbl_fdiv_op - tbl_fdiv_op #
9157 1.2.4.2 wiz
9158 1.2.4.2 wiz short fdiv_res_snan - tbl_fdiv_op # SNAN / NORM
9159 1.2.4.2 wiz short fdiv_res_snan - tbl_fdiv_op # SNAN / ZERO
9160 1.2.4.2 wiz short fdiv_res_snan - tbl_fdiv_op # SNAN / INF
9161 1.2.4.2 wiz short fdiv_res_snan - tbl_fdiv_op # SNAN / QNAN
9162 1.2.4.2 wiz short fdiv_res_snan - tbl_fdiv_op # SNAN / DENORM
9163 1.2.4.2 wiz short fdiv_res_snan - tbl_fdiv_op # SNAN / SNAN
9164 1.2.4.2 wiz short tbl_fdiv_op - tbl_fdiv_op #
9165 1.2.4.2 wiz short tbl_fdiv_op - tbl_fdiv_op #
9166 1.2.4.2 wiz
9167 1.2.4.2 wiz fdiv_res_qnan:
9168 1.2.4.2 wiz bra.l res_qnan
9169 1.2.4.2 wiz fdiv_res_snan:
9170 1.2.4.2 wiz bra.l res_snan
9171 1.2.4.2 wiz fdiv_res_operr:
9172 1.2.4.2 wiz bra.l res_operr
9173 1.2.4.2 wiz
9174 1.2.4.2 wiz global fdiv_zero_load # global for fsgldiv
9175 1.2.4.2 wiz fdiv_zero_load:
9176 1.2.4.2 wiz mov.b SRC_EX(%a0),%d0 # result sign is exclusive
9177 1.2.4.2 wiz mov.b DST_EX(%a1),%d1 # or of input signs.
9178 1.2.4.2 wiz eor.b %d0,%d1
9179 1.2.4.2 wiz bpl.b fdiv_zero_load_p # result is positive
9180 1.2.4.2 wiz fmov.s &0x80000000,%fp0 # load a -ZERO
9181 1.2.4.2 wiz mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set Z/N
9182 1.2.4.2 wiz rts
9183 1.2.4.2 wiz fdiv_zero_load_p:
9184 1.2.4.2 wiz fmov.s &0x00000000,%fp0 # load a +ZERO
9185 1.2.4.2 wiz mov.b &z_bmask,FPSR_CC(%a6) # set Z
9186 1.2.4.2 wiz rts
9187 1.2.4.2 wiz
9188 1.2.4.2 wiz #
9189 1.2.4.2 wiz # The destination was In Range and the source was a ZERO. The result,
9190 1.2.4.2 wiz # therefore, is an INF w/ the proper sign.
9191 1.2.4.2 wiz # So, determine the sign and return a new INF (w/ the j-bit cleared).
9192 1.2.4.2 wiz #
9193 1.2.4.2 wiz global fdiv_inf_load # global for fsgldiv
9194 1.2.4.2 wiz fdiv_inf_load:
9195 1.2.4.2 wiz ori.w &dz_mask+adz_mask,2+USER_FPSR(%a6) # no; set DZ/ADZ
9196 1.2.4.2 wiz mov.b SRC_EX(%a0),%d0 # load both signs
9197 1.2.4.2 wiz mov.b DST_EX(%a1),%d1
9198 1.2.4.2 wiz eor.b %d0,%d1
9199 1.2.4.2 wiz bpl.b fdiv_inf_load_p # result is positive
9200 1.2.4.2 wiz fmov.s &0xff800000,%fp0 # make result -INF
9201 1.2.4.2 wiz mov.b &inf_bmask+neg_bmask,FPSR_CC(%a6) # set INF/N
9202 1.2.4.2 wiz rts
9203 1.2.4.2 wiz fdiv_inf_load_p:
9204 1.2.4.2 wiz fmov.s &0x7f800000,%fp0 # make result +INF
9205 1.2.4.2 wiz mov.b &inf_bmask,FPSR_CC(%a6) # set INF
9206 1.2.4.2 wiz rts
9207 1.2.4.2 wiz
9208 1.2.4.2 wiz #
9209 1.2.4.2 wiz # The destination was an INF w/ an In Range or ZERO source, the result is
9210 1.2.4.2 wiz # an INF w/ the proper sign.
9211 1.2.4.2 wiz # The 68881/882 returns the destination INF w/ the new sign(if the j-bit of the
9212 1.2.4.2 wiz # dst INF is set, then then j-bit of the result INF is also set).
9213 1.2.4.2 wiz #
9214 1.2.4.2 wiz global fdiv_inf_dst # global for fsgldiv
9215 1.2.4.2 wiz fdiv_inf_dst:
9216 1.2.4.2 wiz mov.b DST_EX(%a1),%d0 # load both signs
9217 1.2.4.2 wiz mov.b SRC_EX(%a0),%d1
9218 1.2.4.2 wiz eor.b %d0,%d1
9219 1.2.4.2 wiz bpl.b fdiv_inf_dst_p # result is positive
9220 1.2.4.2 wiz
9221 1.2.4.2 wiz fmovm.x DST(%a1),&0x80 # return result in fp0
9222 1.2.4.2 wiz fabs.x %fp0 # clear sign bit
9223 1.2.4.2 wiz fneg.x %fp0 # set sign bit
9224 1.2.4.2 wiz mov.b &inf_bmask+neg_bmask,FPSR_CC(%a6) # set INF/NEG
9225 1.2.4.2 wiz rts
9226 1.2.4.2 wiz
9227 1.2.4.2 wiz fdiv_inf_dst_p:
9228 1.2.4.2 wiz fmovm.x DST(%a1),&0x80 # return result in fp0
9229 1.2.4.2 wiz fabs.x %fp0 # return positive INF
9230 1.2.4.2 wiz mov.b &inf_bmask,FPSR_CC(%a6) # set INF
9231 1.2.4.2 wiz rts
9232 1.2.4.2 wiz
9233 1.2.4.2 wiz #########################################################################
9234 1.2.4.2 wiz # XDEF **************************************************************** #
9235 1.2.4.2 wiz # fneg(): emulates the fneg instruction #
9236 1.2.4.2 wiz # fsneg(): emulates the fsneg instruction #
9237 1.2.4.2 wiz # fdneg(): emulates the fdneg instruction #
9238 1.2.4.2 wiz # #
9239 1.2.4.2 wiz # XREF **************************************************************** #
9240 1.2.4.2 wiz # norm() - normalize a denorm to provide EXOP #
9241 1.2.4.2 wiz # scale_to_zero_src() - scale sgl/dbl source exponent #
9242 1.2.4.2 wiz # ovf_res() - return default overflow result #
9243 1.2.4.2 wiz # unf_res() - return default underflow result #
9244 1.2.4.2 wiz # res_qnan_1op() - return QNAN result #
9245 1.2.4.2 wiz # res_snan_1op() - return SNAN result #
9246 1.2.4.2 wiz # #
9247 1.2.4.2 wiz # INPUT *************************************************************** #
9248 1.2.4.2 wiz # a0 = pointer to extended precision source operand #
9249 1.2.4.2 wiz # d0 = rnd prec,mode #
9250 1.2.4.2 wiz # #
9251 1.2.4.2 wiz # OUTPUT ************************************************************** #
9252 1.2.4.2 wiz # fp0 = result #
9253 1.2.4.2 wiz # fp1 = EXOP (if exception occurred) #
9254 1.2.4.2 wiz # #
9255 1.2.4.2 wiz # ALGORITHM *********************************************************** #
9256 1.2.4.2 wiz # Handle NANs, zeroes, and infinities as special cases. Separate #
9257 1.2.4.2 wiz # norms/denorms into ext/sgl/dbl precisions. Extended precision can be #
9258 1.2.4.2 wiz # emulated by simply setting sign bit. Sgl/dbl operands must be scaled #
9259 1.2.4.2 wiz # and an actual fneg performed to see if overflow/underflow would have #
9260 1.2.4.2 wiz # occurred. If so, return default underflow/overflow result. Else, #
9261 1.2.4.2 wiz # scale the result exponent and return result. FPSR gets set based on #
9262 1.2.4.2 wiz # the result value. #
9263 1.2.4.2 wiz # #
9264 1.2.4.2 wiz #########################################################################
9265 1.2.4.2 wiz
9266 1.2.4.2 wiz global fsneg
9267 1.2.4.2 wiz fsneg:
9268 1.2.4.2 wiz andi.b &0x30,%d0 # clear rnd prec
9269 1.2.4.2 wiz ori.b &s_mode*0x10,%d0 # insert sgl precision
9270 1.2.4.2 wiz bra.b fneg
9271 1.2.4.2 wiz
9272 1.2.4.2 wiz global fdneg
9273 1.2.4.2 wiz fdneg:
9274 1.2.4.2 wiz andi.b &0x30,%d0 # clear rnd prec
9275 1.2.4.2 wiz ori.b &d_mode*0x10,%d0 # insert dbl prec
9276 1.2.4.2 wiz
9277 1.2.4.2 wiz global fneg
9278 1.2.4.2 wiz fneg:
9279 1.2.4.2 wiz mov.l %d0,L_SCR3(%a6) # store rnd info
9280 1.2.4.2 wiz mov.b STAG(%a6),%d1
9281 1.2.4.2 wiz bne.w fneg_not_norm # optimize on non-norm input
9282 1.2.4.2 wiz
9283 1.2.4.2 wiz #
9284 1.2.4.2 wiz # NEGATE SIGN : norms and denorms ONLY!
9285 1.2.4.2 wiz #
9286 1.2.4.2 wiz fneg_norm:
9287 1.2.4.2 wiz andi.b &0xc0,%d0 # is precision extended?
9288 1.2.4.2 wiz bne.w fneg_not_ext # no; go handle sgl or dbl
9289 1.2.4.2 wiz
9290 1.2.4.2 wiz #
9291 1.2.4.2 wiz # precision selected is extended. so...we can not get an underflow
9292 1.2.4.2 wiz # or overflow because of rounding to the correct precision. so...
9293 1.2.4.2 wiz # skip the scaling and unscaling...
9294 1.2.4.2 wiz #
9295 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
9296 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
9297 1.2.4.2 wiz mov.w SRC_EX(%a0),%d0
9298 1.2.4.2 wiz eori.w &0x8000,%d0 # negate sign
9299 1.2.4.2 wiz bpl.b fneg_norm_load # sign is positive
9300 1.2.4.2 wiz mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
9301 1.2.4.2 wiz fneg_norm_load:
9302 1.2.4.2 wiz mov.w %d0,FP_SCR0_EX(%a6)
9303 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
9304 1.2.4.2 wiz rts
9305 1.2.4.2 wiz
9306 1.2.4.2 wiz #
9307 1.2.4.2 wiz # for an extended precision DENORM, the UNFL exception bit is set
9308 1.2.4.2 wiz # the accrued bit is NOT set in this instance(no inexactness!)
9309 1.2.4.2 wiz #
9310 1.2.4.2 wiz fneg_denorm:
9311 1.2.4.2 wiz andi.b &0xc0,%d0 # is precision extended?
9312 1.2.4.2 wiz bne.b fneg_not_ext # no; go handle sgl or dbl
9313 1.2.4.2 wiz
9314 1.2.4.2 wiz bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
9315 1.2.4.2 wiz
9316 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
9317 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
9318 1.2.4.2 wiz mov.w SRC_EX(%a0),%d0
9319 1.2.4.2 wiz eori.w &0x8000,%d0 # negate sign
9320 1.2.4.2 wiz bpl.b fneg_denorm_done # no
9321 1.2.4.2 wiz mov.b &neg_bmask,FPSR_CC(%a6) # yes, set 'N' ccode bit
9322 1.2.4.2 wiz fneg_denorm_done:
9323 1.2.4.2 wiz mov.w %d0,FP_SCR0_EX(%a6)
9324 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
9325 1.2.4.2 wiz
9326 1.2.4.2 wiz btst &unfl_bit,FPCR_ENABLE(%a6) # is UNFL enabled?
9327 1.2.4.2 wiz bne.b fneg_ext_unfl_ena # yes
9328 1.2.4.2 wiz rts
9329 1.2.4.2 wiz
9330 1.2.4.2 wiz #
9331 1.2.4.2 wiz # the input is an extended DENORM and underflow is enabled in the FPCR.
9332 1.2.4.2 wiz # normalize the mantissa and add the bias of 0x6000 to the resulting negative
9333 1.2.4.2 wiz # exponent and insert back into the operand.
9334 1.2.4.2 wiz #
9335 1.2.4.2 wiz fneg_ext_unfl_ena:
9336 1.2.4.2 wiz lea FP_SCR0(%a6),%a0 # pass: ptr to operand
9337 1.2.4.2 wiz bsr.l norm # normalize result
9338 1.2.4.2 wiz neg.w %d0 # new exponent = -(shft val)
9339 1.2.4.2 wiz addi.w &0x6000,%d0 # add new bias to exponent
9340 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # fetch old sign,exp
9341 1.2.4.2 wiz andi.w &0x8000,%d1 # keep old sign
9342 1.2.4.2 wiz andi.w &0x7fff,%d0 # clear sign position
9343 1.2.4.2 wiz or.w %d1,%d0 # concat old sign, new exponent
9344 1.2.4.2 wiz mov.w %d0,FP_SCR0_EX(%a6) # insert new exponent
9345 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
9346 1.2.4.2 wiz rts
9347 1.2.4.2 wiz
9348 1.2.4.2 wiz #
9349 1.2.4.2 wiz # operand is either single or double
9350 1.2.4.2 wiz #
9351 1.2.4.2 wiz fneg_not_ext:
9352 1.2.4.2 wiz cmpi.b %d0,&s_mode*0x10 # separate sgl/dbl prec
9353 1.2.4.2 wiz bne.b fneg_dbl
9354 1.2.4.2 wiz
9355 1.2.4.2 wiz #
9356 1.2.4.2 wiz # operand is to be rounded to single precision
9357 1.2.4.2 wiz #
9358 1.2.4.2 wiz fneg_sgl:
9359 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
9360 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
9361 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
9362 1.2.4.2 wiz bsr.l scale_to_zero_src # calculate scale factor
9363 1.2.4.2 wiz
9364 1.2.4.2 wiz cmpi.l %d0,&0x3fff-0x3f80 # will move in underflow?
9365 1.2.4.2 wiz bge.w fneg_sd_unfl # yes; go handle underflow
9366 1.2.4.2 wiz cmpi.l %d0,&0x3fff-0x407e # will move in overflow?
9367 1.2.4.2 wiz beq.w fneg_sd_may_ovfl # maybe; go check
9368 1.2.4.2 wiz blt.w fneg_sd_ovfl # yes; go handle overflow
9369 1.2.4.2 wiz
9370 1.2.4.2 wiz #
9371 1.2.4.2 wiz # operand will NOT overflow or underflow when moved in to the fp reg file
9372 1.2.4.2 wiz #
9373 1.2.4.2 wiz fneg_sd_normal:
9374 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
9375 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
9376 1.2.4.2 wiz
9377 1.2.4.2 wiz fneg.x FP_SCR0(%a6),%fp0 # perform negation
9378 1.2.4.2 wiz
9379 1.2.4.2 wiz fmov.l %fpsr,%d1 # save FPSR
9380 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
9381 1.2.4.2 wiz
9382 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
9383 1.2.4.2 wiz
9384 1.2.4.2 wiz fneg_sd_normal_exit:
9385 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
9386 1.2.4.2 wiz fmovm.x &0x80,FP_SCR0(%a6) # store out result
9387 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # load sgn,exp
9388 1.2.4.2 wiz mov.w %d1,%d2 # make a copy
9389 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
9390 1.2.4.2 wiz sub.l %d0,%d1 # add scale factor
9391 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
9392 1.2.4.2 wiz or.w %d1,%d2 # concat old sign,new exp
9393 1.2.4.2 wiz mov.w %d2,FP_SCR0_EX(%a6) # insert new exponent
9394 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
9395 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
9396 1.2.4.2 wiz rts
9397 1.2.4.2 wiz
9398 1.2.4.2 wiz #
9399 1.2.4.2 wiz # operand is to be rounded to double precision
9400 1.2.4.2 wiz #
9401 1.2.4.2 wiz fneg_dbl:
9402 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
9403 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
9404 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
9405 1.2.4.2 wiz bsr.l scale_to_zero_src # calculate scale factor
9406 1.2.4.2 wiz
9407 1.2.4.2 wiz cmpi.l %d0,&0x3fff-0x3c00 # will move in underflow?
9408 1.2.4.2 wiz bge.b fneg_sd_unfl # yes; go handle underflow
9409 1.2.4.2 wiz cmpi.l %d0,&0x3fff-0x43fe # will move in overflow?
9410 1.2.4.2 wiz beq.w fneg_sd_may_ovfl # maybe; go check
9411 1.2.4.2 wiz blt.w fneg_sd_ovfl # yes; go handle overflow
9412 1.2.4.2 wiz bra.w fneg_sd_normal # no; ho handle normalized op
9413 1.2.4.2 wiz
9414 1.2.4.2 wiz #
9415 1.2.4.2 wiz # operand WILL underflow when moved in to the fp register file
9416 1.2.4.2 wiz #
9417 1.2.4.2 wiz fneg_sd_unfl:
9418 1.2.4.2 wiz bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
9419 1.2.4.2 wiz
9420 1.2.4.2 wiz eori.b &0x80,FP_SCR0_EX(%a6) # negate sign
9421 1.2.4.2 wiz bpl.b fneg_sd_unfl_tst
9422 1.2.4.2 wiz bset &neg_bit,FPSR_CC(%a6) # set 'N' ccode bit
9423 1.2.4.2 wiz
9424 1.2.4.2 wiz # if underflow or inexact is enabled, go calculate EXOP first.
9425 1.2.4.2 wiz fneg_sd_unfl_tst:
9426 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d1
9427 1.2.4.2 wiz andi.b &0x0b,%d1 # is UNFL or INEX enabled?
9428 1.2.4.2 wiz bne.b fneg_sd_unfl_ena # yes
9429 1.2.4.2 wiz
9430 1.2.4.2 wiz fneg_sd_unfl_dis:
9431 1.2.4.2 wiz lea FP_SCR0(%a6),%a0 # pass: result addr
9432 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
9433 1.2.4.2 wiz bsr.l unf_res # calculate default result
9434 1.2.4.2 wiz or.b %d0,FPSR_CC(%a6) # unf_res may have set 'Z'
9435 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
9436 1.2.4.2 wiz rts
9437 1.2.4.2 wiz
9438 1.2.4.2 wiz #
9439 1.2.4.2 wiz # operand will underflow AND underflow is enabled.
9440 1.2.4.2 wiz # therefore, we must return the result rounded to extended precision.
9441 1.2.4.2 wiz #
9442 1.2.4.2 wiz fneg_sd_unfl_ena:
9443 1.2.4.2 wiz mov.l FP_SCR0_HI(%a6),FP_SCR1_HI(%a6)
9444 1.2.4.2 wiz mov.l FP_SCR0_LO(%a6),FP_SCR1_LO(%a6)
9445 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # load current exponent
9446 1.2.4.2 wiz
9447 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
9448 1.2.4.2 wiz mov.l %d1,%d2 # make a copy
9449 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
9450 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
9451 1.2.4.2 wiz sub.l %d0,%d1 # subtract scale factor
9452 1.2.4.2 wiz addi.l &0x6000,%d1 # add new bias
9453 1.2.4.2 wiz andi.w &0x7fff,%d1
9454 1.2.4.2 wiz or.w %d2,%d1 # concat new sign,new exp
9455 1.2.4.2 wiz mov.w %d1,FP_SCR1_EX(%a6) # insert new exp
9456 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x40 # return EXOP in fp1
9457 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
9458 1.2.4.2 wiz bra.b fneg_sd_unfl_dis
9459 1.2.4.2 wiz
9460 1.2.4.2 wiz #
9461 1.2.4.2 wiz # operand WILL overflow.
9462 1.2.4.2 wiz #
9463 1.2.4.2 wiz fneg_sd_ovfl:
9464 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
9465 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
9466 1.2.4.2 wiz
9467 1.2.4.2 wiz fneg.x FP_SCR0(%a6),%fp0 # perform negation
9468 1.2.4.2 wiz
9469 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
9470 1.2.4.2 wiz fmov.l %fpsr,%d1 # save FPSR
9471 1.2.4.2 wiz
9472 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
9473 1.2.4.2 wiz
9474 1.2.4.2 wiz fneg_sd_ovfl_tst:
9475 1.2.4.2 wiz or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
9476 1.2.4.2 wiz
9477 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d1
9478 1.2.4.2 wiz andi.b &0x13,%d1 # is OVFL or INEX enabled?
9479 1.2.4.2 wiz bne.b fneg_sd_ovfl_ena # yes
9480 1.2.4.2 wiz
9481 1.2.4.2 wiz #
9482 1.2.4.2 wiz # OVFL is not enabled; therefore, we must create the default result by
9483 1.2.4.2 wiz # calling ovf_res().
9484 1.2.4.2 wiz #
9485 1.2.4.2 wiz fneg_sd_ovfl_dis:
9486 1.2.4.2 wiz btst &neg_bit,FPSR_CC(%a6) # is result negative?
9487 1.2.4.2 wiz sne %d1 # set sign param accordingly
9488 1.2.4.2 wiz mov.l L_SCR3(%a6),%d0 # pass: prec,mode
9489 1.2.4.2 wiz bsr.l ovf_res # calculate default result
9490 1.2.4.2 wiz or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
9491 1.2.4.2 wiz fmovm.x (%a0),&0x80 # return default result in fp0
9492 1.2.4.2 wiz rts
9493 1.2.4.2 wiz
9494 1.2.4.2 wiz #
9495 1.2.4.2 wiz # OVFL is enabled.
9496 1.2.4.2 wiz # the INEX2 bit has already been updated by the round to the correct precision.
9497 1.2.4.2 wiz # now, round to extended(and don't alter the FPSR).
9498 1.2.4.2 wiz #
9499 1.2.4.2 wiz fneg_sd_ovfl_ena:
9500 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
9501 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
9502 1.2.4.2 wiz mov.l %d1,%d2 # make a copy
9503 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
9504 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
9505 1.2.4.2 wiz sub.l %d0,%d1 # add scale factor
9506 1.2.4.2 wiz subi.l &0x6000,%d1 # subtract bias
9507 1.2.4.2 wiz andi.w &0x7fff,%d1
9508 1.2.4.2 wiz or.w %d2,%d1 # concat sign,exp
9509 1.2.4.2 wiz mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
9510 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
9511 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
9512 1.2.4.2 wiz bra.b fneg_sd_ovfl_dis
9513 1.2.4.2 wiz
9514 1.2.4.2 wiz #
9515 1.2.4.2 wiz # the move in MAY underflow. so...
9516 1.2.4.2 wiz #
9517 1.2.4.2 wiz fneg_sd_may_ovfl:
9518 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
9519 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
9520 1.2.4.2 wiz
9521 1.2.4.2 wiz fneg.x FP_SCR0(%a6),%fp0 # perform negation
9522 1.2.4.2 wiz
9523 1.2.4.2 wiz fmov.l %fpsr,%d1 # save status
9524 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
9525 1.2.4.2 wiz
9526 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
9527 1.2.4.2 wiz
9528 1.2.4.2 wiz fabs.x %fp0,%fp1 # make a copy of result
9529 1.2.4.2 wiz fcmp.b %fp1,&0x2 # is |result| >= 2.b?
9530 1.2.4.2 wiz fbge.w fneg_sd_ovfl_tst # yes; overflow has occurred
9531 1.2.4.2 wiz
9532 1.2.4.2 wiz # no, it didn't overflow; we have correct result
9533 1.2.4.2 wiz bra.w fneg_sd_normal_exit
9534 1.2.4.2 wiz
9535 1.2.4.2 wiz ##########################################################################
9536 1.2.4.2 wiz
9537 1.2.4.2 wiz #
9538 1.2.4.2 wiz # input is not normalized; what is it?
9539 1.2.4.2 wiz #
9540 1.2.4.2 wiz fneg_not_norm:
9541 1.2.4.2 wiz cmpi.b %d1,&DENORM # weed out DENORM
9542 1.2.4.2 wiz beq.w fneg_denorm
9543 1.2.4.2 wiz cmpi.b %d1,&SNAN # weed out SNAN
9544 1.2.4.2 wiz beq.l res_snan_1op
9545 1.2.4.2 wiz cmpi.b %d1,&QNAN # weed out QNAN
9546 1.2.4.2 wiz beq.l res_qnan_1op
9547 1.2.4.2 wiz
9548 1.2.4.2 wiz #
9549 1.2.4.2 wiz # do the fneg; at this point, only possible ops are ZERO and INF.
9550 1.2.4.2 wiz # use fneg to determine ccodes.
9551 1.2.4.2 wiz # prec:mode should be zero at this point but it won't affect answer anyways.
9552 1.2.4.2 wiz #
9553 1.2.4.2 wiz fneg.x SRC_EX(%a0),%fp0 # do fneg
9554 1.2.4.2 wiz fmov.l %fpsr,%d0
9555 1.2.4.2 wiz rol.l &0x8,%d0 # put ccodes in lo byte
9556 1.2.4.2 wiz mov.b %d0,FPSR_CC(%a6) # insert correct ccodes
9557 1.2.4.2 wiz rts
9558 1.2.4.2 wiz
9559 1.2.4.2 wiz #########################################################################
9560 1.2.4.2 wiz # XDEF **************************************************************** #
9561 1.2.4.2 wiz # ftst(): emulates the ftest instruction #
9562 1.2.4.2 wiz # #
9563 1.2.4.2 wiz # XREF **************************************************************** #
9564 1.2.4.2 wiz # res{s,q}nan_1op() - set NAN result for monadic instruction #
9565 1.2.4.2 wiz # #
9566 1.2.4.2 wiz # INPUT *************************************************************** #
9567 1.2.4.2 wiz # a0 = pointer to extended precision source operand #
9568 1.2.4.2 wiz # #
9569 1.2.4.2 wiz # OUTPUT ************************************************************** #
9570 1.2.4.2 wiz # none #
9571 1.2.4.2 wiz # #
9572 1.2.4.2 wiz # ALGORITHM *********************************************************** #
9573 1.2.4.2 wiz # Check the source operand tag (STAG) and set the FPCR according #
9574 1.2.4.2 wiz # to the operand type and sign. #
9575 1.2.4.2 wiz # #
9576 1.2.4.2 wiz #########################################################################
9577 1.2.4.2 wiz
9578 1.2.4.2 wiz global ftst
9579 1.2.4.2 wiz ftst:
9580 1.2.4.2 wiz mov.b STAG(%a6),%d1
9581 1.2.4.2 wiz bne.b ftst_not_norm # optimize on non-norm input
9582 1.2.4.2 wiz
9583 1.2.4.2 wiz #
9584 1.2.4.2 wiz # Norm:
9585 1.2.4.2 wiz #
9586 1.2.4.2 wiz ftst_norm:
9587 1.2.4.2 wiz tst.b SRC_EX(%a0) # is operand negative?
9588 1.2.4.2 wiz bmi.b ftst_norm_m # yes
9589 1.2.4.2 wiz rts
9590 1.2.4.2 wiz ftst_norm_m:
9591 1.2.4.2 wiz mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
9592 1.2.4.2 wiz rts
9593 1.2.4.2 wiz
9594 1.2.4.2 wiz #
9595 1.2.4.2 wiz # input is not normalized; what is it?
9596 1.2.4.2 wiz #
9597 1.2.4.2 wiz ftst_not_norm:
9598 1.2.4.2 wiz cmpi.b %d1,&ZERO # weed out ZERO
9599 1.2.4.2 wiz beq.b ftst_zero
9600 1.2.4.2 wiz cmpi.b %d1,&INF # weed out INF
9601 1.2.4.2 wiz beq.b ftst_inf
9602 1.2.4.2 wiz cmpi.b %d1,&SNAN # weed out SNAN
9603 1.2.4.2 wiz beq.l res_snan_1op
9604 1.2.4.2 wiz cmpi.b %d1,&QNAN # weed out QNAN
9605 1.2.4.2 wiz beq.l res_qnan_1op
9606 1.2.4.2 wiz
9607 1.2.4.2 wiz #
9608 1.2.4.2 wiz # Denorm:
9609 1.2.4.2 wiz #
9610 1.2.4.2 wiz ftst_denorm:
9611 1.2.4.2 wiz tst.b SRC_EX(%a0) # is operand negative?
9612 1.2.4.2 wiz bmi.b ftst_denorm_m # yes
9613 1.2.4.2 wiz rts
9614 1.2.4.2 wiz ftst_denorm_m:
9615 1.2.4.2 wiz mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
9616 1.2.4.2 wiz rts
9617 1.2.4.2 wiz
9618 1.2.4.2 wiz #
9619 1.2.4.2 wiz # Infinity:
9620 1.2.4.2 wiz #
9621 1.2.4.2 wiz ftst_inf:
9622 1.2.4.2 wiz tst.b SRC_EX(%a0) # is operand negative?
9623 1.2.4.2 wiz bmi.b ftst_inf_m # yes
9624 1.2.4.2 wiz ftst_inf_p:
9625 1.2.4.2 wiz mov.b &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
9626 1.2.4.2 wiz rts
9627 1.2.4.2 wiz ftst_inf_m:
9628 1.2.4.2 wiz mov.b &inf_bmask+neg_bmask,FPSR_CC(%a6) # set 'I','N' ccode bits
9629 1.2.4.2 wiz rts
9630 1.2.4.2 wiz
9631 1.2.4.2 wiz #
9632 1.2.4.2 wiz # Zero:
9633 1.2.4.2 wiz #
9634 1.2.4.2 wiz ftst_zero:
9635 1.2.4.2 wiz tst.b SRC_EX(%a0) # is operand negative?
9636 1.2.4.2 wiz bmi.b ftst_zero_m # yes
9637 1.2.4.2 wiz ftst_zero_p:
9638 1.2.4.2 wiz mov.b &z_bmask,FPSR_CC(%a6) # set 'N' ccode bit
9639 1.2.4.2 wiz rts
9640 1.2.4.2 wiz ftst_zero_m:
9641 1.2.4.2 wiz mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set 'Z','N' ccode bits
9642 1.2.4.2 wiz rts
9643 1.2.4.2 wiz
9644 1.2.4.2 wiz #########################################################################
9645 1.2.4.2 wiz # XDEF **************************************************************** #
9646 1.2.4.2 wiz # fint(): emulates the fint instruction #
9647 1.2.4.2 wiz # #
9648 1.2.4.2 wiz # XREF **************************************************************** #
9649 1.2.4.2 wiz # res_{s,q}nan_1op() - set NAN result for monadic operation #
9650 1.2.4.2 wiz # #
9651 1.2.4.2 wiz # INPUT *************************************************************** #
9652 1.2.4.2 wiz # a0 = pointer to extended precision source operand #
9653 1.2.4.2 wiz # d0 = round precision/mode #
9654 1.2.4.2 wiz # #
9655 1.2.4.2 wiz # OUTPUT ************************************************************** #
9656 1.2.4.2 wiz # fp0 = result #
9657 1.2.4.2 wiz # #
9658 1.2.4.2 wiz # ALGORITHM *********************************************************** #
9659 1.2.4.2 wiz # Separate according to operand type. Unnorms don't pass through #
9660 1.2.4.2 wiz # here. For norms, load the rounding mode/prec, execute a "fint", then #
9661 1.2.4.2 wiz # store the resulting FPSR bits. #
9662 1.2.4.2 wiz # For denorms, force the j-bit to a one and do the same as for #
9663 1.2.4.2 wiz # norms. Denorms are so low that the answer will either be a zero or a #
9664 1.2.4.2 wiz # one. #
9665 1.2.4.2 wiz # For zeroes/infs/NANs, return the same while setting the FPSR #
9666 1.2.4.2 wiz # as appropriate. #
9667 1.2.4.2 wiz # #
9668 1.2.4.2 wiz #########################################################################
9669 1.2.4.2 wiz
9670 1.2.4.2 wiz global fint
9671 1.2.4.2 wiz fint:
9672 1.2.4.2 wiz mov.b STAG(%a6),%d1
9673 1.2.4.2 wiz bne.b fint_not_norm # optimize on non-norm input
9674 1.2.4.2 wiz
9675 1.2.4.2 wiz #
9676 1.2.4.2 wiz # Norm:
9677 1.2.4.2 wiz #
9678 1.2.4.2 wiz fint_norm:
9679 1.2.4.2 wiz andi.b &0x30,%d0 # set prec = ext
9680 1.2.4.2 wiz
9681 1.2.4.2 wiz fmov.l %d0,%fpcr # set FPCR
9682 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
9683 1.2.4.2 wiz
9684 1.2.4.2 wiz fint.x SRC(%a0),%fp0 # execute fint
9685 1.2.4.2 wiz
9686 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
9687 1.2.4.2 wiz fmov.l %fpsr,%d0 # save FPSR
9688 1.2.4.2 wiz or.l %d0,USER_FPSR(%a6) # set exception bits
9689 1.2.4.2 wiz
9690 1.2.4.2 wiz rts
9691 1.2.4.2 wiz
9692 1.2.4.2 wiz #
9693 1.2.4.2 wiz # input is not normalized; what is it?
9694 1.2.4.2 wiz #
9695 1.2.4.2 wiz fint_not_norm:
9696 1.2.4.2 wiz cmpi.b %d1,&ZERO # weed out ZERO
9697 1.2.4.2 wiz beq.b fint_zero
9698 1.2.4.2 wiz cmpi.b %d1,&INF # weed out INF
9699 1.2.4.2 wiz beq.b fint_inf
9700 1.2.4.2 wiz cmpi.b %d1,&DENORM # weed out DENORM
9701 1.2.4.2 wiz beq.b fint_denorm
9702 1.2.4.2 wiz cmpi.b %d1,&SNAN # weed out SNAN
9703 1.2.4.2 wiz beq.l res_snan_1op
9704 1.2.4.2 wiz bra.l res_qnan_1op # weed out QNAN
9705 1.2.4.2 wiz
9706 1.2.4.2 wiz #
9707 1.2.4.2 wiz # Denorm:
9708 1.2.4.2 wiz #
9709 1.2.4.2 wiz # for DENORMs, the result will be either (+/-)ZERO or (+/-)1.
9710 1.2.4.2 wiz # also, the INEX2 and AINEX exception bits will be set.
9711 1.2.4.2 wiz # so, we could either set these manually or force the DENORM
9712 1.2.4.2 wiz # to a very small NORM and ship it to the NORM routine.
9713 1.2.4.2 wiz # I do the latter.
9714 1.2.4.2 wiz #
9715 1.2.4.2 wiz fint_denorm:
9716 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6) # copy sign, zero exp
9717 1.2.4.2 wiz mov.b &0x80,FP_SCR0_HI(%a6) # force DENORM ==> small NORM
9718 1.2.4.2 wiz lea FP_SCR0(%a6),%a0
9719 1.2.4.2 wiz bra.b fint_norm
9720 1.2.4.2 wiz
9721 1.2.4.2 wiz #
9722 1.2.4.2 wiz # Zero:
9723 1.2.4.2 wiz #
9724 1.2.4.2 wiz fint_zero:
9725 1.2.4.2 wiz tst.b SRC_EX(%a0) # is ZERO negative?
9726 1.2.4.2 wiz bmi.b fint_zero_m # yes
9727 1.2.4.2 wiz fint_zero_p:
9728 1.2.4.2 wiz fmov.s &0x00000000,%fp0 # return +ZERO in fp0
9729 1.2.4.2 wiz mov.b &z_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
9730 1.2.4.2 wiz rts
9731 1.2.4.2 wiz fint_zero_m:
9732 1.2.4.2 wiz fmov.s &0x80000000,%fp0 # return -ZERO in fp0
9733 1.2.4.2 wiz mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set 'Z','N' ccode bits
9734 1.2.4.2 wiz rts
9735 1.2.4.2 wiz
9736 1.2.4.2 wiz #
9737 1.2.4.2 wiz # Infinity:
9738 1.2.4.2 wiz #
9739 1.2.4.2 wiz fint_inf:
9740 1.2.4.2 wiz fmovm.x SRC(%a0),&0x80 # return result in fp0
9741 1.2.4.2 wiz tst.b SRC_EX(%a0) # is INF negative?
9742 1.2.4.2 wiz bmi.b fint_inf_m # yes
9743 1.2.4.2 wiz fint_inf_p:
9744 1.2.4.2 wiz mov.b &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
9745 1.2.4.2 wiz rts
9746 1.2.4.2 wiz fint_inf_m:
9747 1.2.4.2 wiz mov.b &inf_bmask+neg_bmask,FPSR_CC(%a6) # set 'N','I' ccode bits
9748 1.2.4.2 wiz rts
9749 1.2.4.2 wiz
9750 1.2.4.2 wiz #########################################################################
9751 1.2.4.2 wiz # XDEF **************************************************************** #
9752 1.2.4.2 wiz # fintrz(): emulates the fintrz instruction #
9753 1.2.4.2 wiz # #
9754 1.2.4.2 wiz # XREF **************************************************************** #
9755 1.2.4.2 wiz # res_{s,q}nan_1op() - set NAN result for monadic operation #
9756 1.2.4.2 wiz # #
9757 1.2.4.2 wiz # INPUT *************************************************************** #
9758 1.2.4.2 wiz # a0 = pointer to extended precision source operand #
9759 1.2.4.2 wiz # d0 = round precision/mode #
9760 1.2.4.2 wiz # #
9761 1.2.4.2 wiz # OUTPUT ************************************************************** #
9762 1.2.4.2 wiz # fp0 = result #
9763 1.2.4.2 wiz # #
9764 1.2.4.2 wiz # ALGORITHM *********************************************************** #
9765 1.2.4.2 wiz # Separate according to operand type. Unnorms don't pass through #
9766 1.2.4.2 wiz # here. For norms, load the rounding mode/prec, execute a "fintrz", #
9767 1.2.4.2 wiz # then store the resulting FPSR bits. #
9768 1.2.4.2 wiz # For denorms, force the j-bit to a one and do the same as for #
9769 1.2.4.2 wiz # norms. Denorms are so low that the answer will either be a zero or a #
9770 1.2.4.2 wiz # one. #
9771 1.2.4.2 wiz # For zeroes/infs/NANs, return the same while setting the FPSR #
9772 1.2.4.2 wiz # as appropriate. #
9773 1.2.4.2 wiz # #
9774 1.2.4.2 wiz #########################################################################
9775 1.2.4.2 wiz
9776 1.2.4.2 wiz global fintrz
9777 1.2.4.2 wiz fintrz:
9778 1.2.4.2 wiz mov.b STAG(%a6),%d1
9779 1.2.4.2 wiz bne.b fintrz_not_norm # optimize on non-norm input
9780 1.2.4.2 wiz
9781 1.2.4.2 wiz #
9782 1.2.4.2 wiz # Norm:
9783 1.2.4.2 wiz #
9784 1.2.4.2 wiz fintrz_norm:
9785 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
9786 1.2.4.2 wiz
9787 1.2.4.2 wiz fintrz.x SRC(%a0),%fp0 # execute fintrz
9788 1.2.4.2 wiz
9789 1.2.4.2 wiz fmov.l %fpsr,%d0 # save FPSR
9790 1.2.4.2 wiz or.l %d0,USER_FPSR(%a6) # set exception bits
9791 1.2.4.2 wiz
9792 1.2.4.2 wiz rts
9793 1.2.4.2 wiz
9794 1.2.4.2 wiz #
9795 1.2.4.2 wiz # input is not normalized; what is it?
9796 1.2.4.2 wiz #
9797 1.2.4.2 wiz fintrz_not_norm:
9798 1.2.4.2 wiz cmpi.b %d1,&ZERO # weed out ZERO
9799 1.2.4.2 wiz beq.b fintrz_zero
9800 1.2.4.2 wiz cmpi.b %d1,&INF # weed out INF
9801 1.2.4.2 wiz beq.b fintrz_inf
9802 1.2.4.2 wiz cmpi.b %d1,&DENORM # weed out DENORM
9803 1.2.4.2 wiz beq.b fintrz_denorm
9804 1.2.4.2 wiz cmpi.b %d1,&SNAN # weed out SNAN
9805 1.2.4.2 wiz beq.l res_snan_1op
9806 1.2.4.2 wiz bra.l res_qnan_1op # weed out QNAN
9807 1.2.4.2 wiz
9808 1.2.4.2 wiz #
9809 1.2.4.2 wiz # Denorm:
9810 1.2.4.2 wiz #
9811 1.2.4.2 wiz # for DENORMs, the result will be (+/-)ZERO.
9812 1.2.4.2 wiz # also, the INEX2 and AINEX exception bits will be set.
9813 1.2.4.2 wiz # so, we could either set these manually or force the DENORM
9814 1.2.4.2 wiz # to a very small NORM and ship it to the NORM routine.
9815 1.2.4.2 wiz # I do the latter.
9816 1.2.4.2 wiz #
9817 1.2.4.2 wiz fintrz_denorm:
9818 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6) # copy sign, zero exp
9819 1.2.4.2 wiz mov.b &0x80,FP_SCR0_HI(%a6) # force DENORM ==> small NORM
9820 1.2.4.2 wiz lea FP_SCR0(%a6),%a0
9821 1.2.4.2 wiz bra.b fintrz_norm
9822 1.2.4.2 wiz
9823 1.2.4.2 wiz #
9824 1.2.4.2 wiz # Zero:
9825 1.2.4.2 wiz #
9826 1.2.4.2 wiz fintrz_zero:
9827 1.2.4.2 wiz tst.b SRC_EX(%a0) # is ZERO negative?
9828 1.2.4.2 wiz bmi.b fintrz_zero_m # yes
9829 1.2.4.2 wiz fintrz_zero_p:
9830 1.2.4.2 wiz fmov.s &0x00000000,%fp0 # return +ZERO in fp0
9831 1.2.4.2 wiz mov.b &z_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
9832 1.2.4.2 wiz rts
9833 1.2.4.2 wiz fintrz_zero_m:
9834 1.2.4.2 wiz fmov.s &0x80000000,%fp0 # return -ZERO in fp0
9835 1.2.4.2 wiz mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set 'Z','N' ccode bits
9836 1.2.4.2 wiz rts
9837 1.2.4.2 wiz
9838 1.2.4.2 wiz #
9839 1.2.4.2 wiz # Infinity:
9840 1.2.4.2 wiz #
9841 1.2.4.2 wiz fintrz_inf:
9842 1.2.4.2 wiz fmovm.x SRC(%a0),&0x80 # return result in fp0
9843 1.2.4.2 wiz tst.b SRC_EX(%a0) # is INF negative?
9844 1.2.4.2 wiz bmi.b fintrz_inf_m # yes
9845 1.2.4.2 wiz fintrz_inf_p:
9846 1.2.4.2 wiz mov.b &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
9847 1.2.4.2 wiz rts
9848 1.2.4.2 wiz fintrz_inf_m:
9849 1.2.4.2 wiz mov.b &inf_bmask+neg_bmask,FPSR_CC(%a6) # set 'N','I' ccode bits
9850 1.2.4.2 wiz rts
9851 1.2.4.2 wiz
9852 1.2.4.2 wiz #########################################################################
9853 1.2.4.2 wiz # XDEF **************************************************************** #
9854 1.2.4.2 wiz # fabs(): emulates the fabs instruction #
9855 1.2.4.2 wiz # fsabs(): emulates the fsabs instruction #
9856 1.2.4.2 wiz # fdabs(): emulates the fdabs instruction #
9857 1.2.4.2 wiz # #
9858 1.2.4.2 wiz # XREF **************************************************************** #
9859 1.2.4.2 wiz # norm() - normalize denorm mantissa to provide EXOP #
9860 1.2.4.2 wiz # scale_to_zero_src() - make exponent. = 0; get scale factor #
9861 1.2.4.2 wiz # unf_res() - calculate underflow result #
9862 1.2.4.2 wiz # ovf_res() - calculate overflow result #
9863 1.2.4.2 wiz # res_{s,q}nan_1op() - set NAN result for monadic operation #
9864 1.2.4.2 wiz # #
9865 1.2.4.2 wiz # INPUT *************************************************************** #
9866 1.2.4.2 wiz # a0 = pointer to extended precision source operand #
9867 1.2.4.2 wiz # d0 = rnd precision/mode #
9868 1.2.4.2 wiz # #
9869 1.2.4.2 wiz # OUTPUT ************************************************************** #
9870 1.2.4.2 wiz # fp0 = result #
9871 1.2.4.2 wiz # fp1 = EXOP (if exception occurred) #
9872 1.2.4.2 wiz # #
9873 1.2.4.2 wiz # ALGORITHM *********************************************************** #
9874 1.2.4.2 wiz # Handle NANs, infinities, and zeroes as special cases. Divide #
9875 1.2.4.2 wiz # norms into extended, single, and double precision. #
9876 1.2.4.2 wiz # Simply clear sign for extended precision norm. Ext prec denorm #
9877 1.2.4.2 wiz # gets an EXOP created for it since it's an underflow. #
9878 1.2.4.2 wiz # Double and single precision can overflow and underflow. First, #
9879 1.2.4.2 wiz # scale the operand such that the exponent is zero. Perform an "fabs" #
9880 1.2.4.2 wiz # using the correct rnd mode/prec. Check to see if the original #
9881 1.2.4.2 wiz # exponent would take an exception. If so, use unf_res() or ovf_res() #
9882 1.2.4.2 wiz # to calculate the default result. Also, create the EXOP for the #
9883 1.2.4.2 wiz # exceptional case. If no exception should occur, insert the correct #
9884 1.2.4.2 wiz # result exponent and return. #
9885 1.2.4.2 wiz # Unnorms don't pass through here. #
9886 1.2.4.2 wiz # #
9887 1.2.4.2 wiz #########################################################################
9888 1.2.4.2 wiz
9889 1.2.4.2 wiz global fsabs
9890 1.2.4.2 wiz fsabs:
9891 1.2.4.2 wiz andi.b &0x30,%d0 # clear rnd prec
9892 1.2.4.2 wiz ori.b &s_mode*0x10,%d0 # insert sgl precision
9893 1.2.4.2 wiz bra.b fabs
9894 1.2.4.2 wiz
9895 1.2.4.2 wiz global fdabs
9896 1.2.4.2 wiz fdabs:
9897 1.2.4.2 wiz andi.b &0x30,%d0 # clear rnd prec
9898 1.2.4.2 wiz ori.b &d_mode*0x10,%d0 # insert dbl precision
9899 1.2.4.2 wiz
9900 1.2.4.2 wiz global fabs
9901 1.2.4.2 wiz fabs:
9902 1.2.4.2 wiz mov.l %d0,L_SCR3(%a6) # store rnd info
9903 1.2.4.2 wiz mov.b STAG(%a6),%d1
9904 1.2.4.2 wiz bne.w fabs_not_norm # optimize on non-norm input
9905 1.2.4.2 wiz
9906 1.2.4.2 wiz #
9907 1.2.4.2 wiz # ABSOLUTE VALUE: norms and denorms ONLY!
9908 1.2.4.2 wiz #
9909 1.2.4.2 wiz fabs_norm:
9910 1.2.4.2 wiz andi.b &0xc0,%d0 # is precision extended?
9911 1.2.4.2 wiz bne.b fabs_not_ext # no; go handle sgl or dbl
9912 1.2.4.2 wiz
9913 1.2.4.2 wiz #
9914 1.2.4.2 wiz # precision selected is extended. so...we can not get an underflow
9915 1.2.4.2 wiz # or overflow because of rounding to the correct precision. so...
9916 1.2.4.2 wiz # skip the scaling and unscaling...
9917 1.2.4.2 wiz #
9918 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
9919 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
9920 1.2.4.2 wiz mov.w SRC_EX(%a0),%d1
9921 1.2.4.2 wiz bclr &15,%d1 # force absolute value
9922 1.2.4.2 wiz mov.w %d1,FP_SCR0_EX(%a6) # insert exponent
9923 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
9924 1.2.4.2 wiz rts
9925 1.2.4.2 wiz
9926 1.2.4.2 wiz #
9927 1.2.4.2 wiz # for an extended precision DENORM, the UNFL exception bit is set
9928 1.2.4.2 wiz # the accrued bit is NOT set in this instance(no inexactness!)
9929 1.2.4.2 wiz #
9930 1.2.4.2 wiz fabs_denorm:
9931 1.2.4.2 wiz andi.b &0xc0,%d0 # is precision extended?
9932 1.2.4.2 wiz bne.b fabs_not_ext # no
9933 1.2.4.2 wiz
9934 1.2.4.2 wiz bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
9935 1.2.4.2 wiz
9936 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
9937 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
9938 1.2.4.2 wiz mov.w SRC_EX(%a0),%d0
9939 1.2.4.2 wiz bclr &15,%d0 # clear sign
9940 1.2.4.2 wiz mov.w %d0,FP_SCR0_EX(%a6) # insert exponent
9941 1.2.4.2 wiz
9942 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
9943 1.2.4.2 wiz
9944 1.2.4.2 wiz btst &unfl_bit,FPCR_ENABLE(%a6) # is UNFL enabled?
9945 1.2.4.2 wiz bne.b fabs_ext_unfl_ena
9946 1.2.4.2 wiz rts
9947 1.2.4.2 wiz
9948 1.2.4.2 wiz #
9949 1.2.4.2 wiz # the input is an extended DENORM and underflow is enabled in the FPCR.
9950 1.2.4.2 wiz # normalize the mantissa and add the bias of 0x6000 to the resulting negative
9951 1.2.4.2 wiz # exponent and insert back into the operand.
9952 1.2.4.2 wiz #
9953 1.2.4.2 wiz fabs_ext_unfl_ena:
9954 1.2.4.2 wiz lea FP_SCR0(%a6),%a0 # pass: ptr to operand
9955 1.2.4.2 wiz bsr.l norm # normalize result
9956 1.2.4.2 wiz neg.w %d0 # new exponent = -(shft val)
9957 1.2.4.2 wiz addi.w &0x6000,%d0 # add new bias to exponent
9958 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # fetch old sign,exp
9959 1.2.4.2 wiz andi.w &0x8000,%d1 # keep old sign
9960 1.2.4.2 wiz andi.w &0x7fff,%d0 # clear sign position
9961 1.2.4.2 wiz or.w %d1,%d0 # concat old sign, new exponent
9962 1.2.4.2 wiz mov.w %d0,FP_SCR0_EX(%a6) # insert new exponent
9963 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
9964 1.2.4.2 wiz rts
9965 1.2.4.2 wiz
9966 1.2.4.2 wiz #
9967 1.2.4.2 wiz # operand is either single or double
9968 1.2.4.2 wiz #
9969 1.2.4.2 wiz fabs_not_ext:
9970 1.2.4.2 wiz cmpi.b %d0,&s_mode*0x10 # separate sgl/dbl prec
9971 1.2.4.2 wiz bne.b fabs_dbl
9972 1.2.4.2 wiz
9973 1.2.4.2 wiz #
9974 1.2.4.2 wiz # operand is to be rounded to single precision
9975 1.2.4.2 wiz #
9976 1.2.4.2 wiz fabs_sgl:
9977 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
9978 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
9979 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
9980 1.2.4.2 wiz bsr.l scale_to_zero_src # calculate scale factor
9981 1.2.4.2 wiz
9982 1.2.4.2 wiz cmpi.l %d0,&0x3fff-0x3f80 # will move in underflow?
9983 1.2.4.2 wiz bge.w fabs_sd_unfl # yes; go handle underflow
9984 1.2.4.2 wiz cmpi.l %d0,&0x3fff-0x407e # will move in overflow?
9985 1.2.4.2 wiz beq.w fabs_sd_may_ovfl # maybe; go check
9986 1.2.4.2 wiz blt.w fabs_sd_ovfl # yes; go handle overflow
9987 1.2.4.2 wiz
9988 1.2.4.2 wiz #
9989 1.2.4.2 wiz # operand will NOT overflow or underflow when moved in to the fp reg file
9990 1.2.4.2 wiz #
9991 1.2.4.2 wiz fabs_sd_normal:
9992 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
9993 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
9994 1.2.4.2 wiz
9995 1.2.4.2 wiz fabs.x FP_SCR0(%a6),%fp0 # perform absolute
9996 1.2.4.2 wiz
9997 1.2.4.2 wiz fmov.l %fpsr,%d1 # save FPSR
9998 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
9999 1.2.4.2 wiz
10000 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
10001 1.2.4.2 wiz
10002 1.2.4.2 wiz fabs_sd_normal_exit:
10003 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
10004 1.2.4.2 wiz fmovm.x &0x80,FP_SCR0(%a6) # store out result
10005 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # load sgn,exp
10006 1.2.4.2 wiz mov.l %d1,%d2 # make a copy
10007 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
10008 1.2.4.2 wiz sub.l %d0,%d1 # add scale factor
10009 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
10010 1.2.4.2 wiz or.w %d1,%d2 # concat old sign,new exp
10011 1.2.4.2 wiz mov.w %d2,FP_SCR0_EX(%a6) # insert new exponent
10012 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
10013 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
10014 1.2.4.2 wiz rts
10015 1.2.4.2 wiz
10016 1.2.4.2 wiz #
10017 1.2.4.2 wiz # operand is to be rounded to double precision
10018 1.2.4.2 wiz #
10019 1.2.4.2 wiz fabs_dbl:
10020 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
10021 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
10022 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
10023 1.2.4.2 wiz bsr.l scale_to_zero_src # calculate scale factor
10024 1.2.4.2 wiz
10025 1.2.4.2 wiz cmpi.l %d0,&0x3fff-0x3c00 # will move in underflow?
10026 1.2.4.2 wiz bge.b fabs_sd_unfl # yes; go handle underflow
10027 1.2.4.2 wiz cmpi.l %d0,&0x3fff-0x43fe # will move in overflow?
10028 1.2.4.2 wiz beq.w fabs_sd_may_ovfl # maybe; go check
10029 1.2.4.2 wiz blt.w fabs_sd_ovfl # yes; go handle overflow
10030 1.2.4.2 wiz bra.w fabs_sd_normal # no; ho handle normalized op
10031 1.2.4.2 wiz
10032 1.2.4.2 wiz #
10033 1.2.4.2 wiz # operand WILL underflow when moved in to the fp register file
10034 1.2.4.2 wiz #
10035 1.2.4.2 wiz fabs_sd_unfl:
10036 1.2.4.2 wiz bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
10037 1.2.4.2 wiz
10038 1.2.4.2 wiz bclr &0x7,FP_SCR0_EX(%a6) # force absolute value
10039 1.2.4.2 wiz
10040 1.2.4.2 wiz # if underflow or inexact is enabled, go calculate EXOP first.
10041 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d1
10042 1.2.4.2 wiz andi.b &0x0b,%d1 # is UNFL or INEX enabled?
10043 1.2.4.2 wiz bne.b fabs_sd_unfl_ena # yes
10044 1.2.4.2 wiz
10045 1.2.4.2 wiz fabs_sd_unfl_dis:
10046 1.2.4.2 wiz lea FP_SCR0(%a6),%a0 # pass: result addr
10047 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
10048 1.2.4.2 wiz bsr.l unf_res # calculate default result
10049 1.2.4.2 wiz or.b %d0,FPSR_CC(%a6) # set possible 'Z' ccode
10050 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
10051 1.2.4.2 wiz rts
10052 1.2.4.2 wiz
10053 1.2.4.2 wiz #
10054 1.2.4.2 wiz # operand will underflow AND underflow is enabled.
10055 1.2.4.2 wiz # therefore, we must return the result rounded to extended precision.
10056 1.2.4.2 wiz #
10057 1.2.4.2 wiz fabs_sd_unfl_ena:
10058 1.2.4.2 wiz mov.l FP_SCR0_HI(%a6),FP_SCR1_HI(%a6)
10059 1.2.4.2 wiz mov.l FP_SCR0_LO(%a6),FP_SCR1_LO(%a6)
10060 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # load current exponent
10061 1.2.4.2 wiz
10062 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
10063 1.2.4.2 wiz mov.l %d1,%d2 # make a copy
10064 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
10065 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
10066 1.2.4.2 wiz sub.l %d0,%d1 # subtract scale factor
10067 1.2.4.2 wiz addi.l &0x6000,%d1 # add new bias
10068 1.2.4.2 wiz andi.w &0x7fff,%d1
10069 1.2.4.2 wiz or.w %d2,%d1 # concat new sign,new exp
10070 1.2.4.2 wiz mov.w %d1,FP_SCR1_EX(%a6) # insert new exp
10071 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x40 # return EXOP in fp1
10072 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
10073 1.2.4.2 wiz bra.b fabs_sd_unfl_dis
10074 1.2.4.2 wiz
10075 1.2.4.2 wiz #
10076 1.2.4.2 wiz # operand WILL overflow.
10077 1.2.4.2 wiz #
10078 1.2.4.2 wiz fabs_sd_ovfl:
10079 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
10080 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
10081 1.2.4.2 wiz
10082 1.2.4.2 wiz fabs.x FP_SCR0(%a6),%fp0 # perform absolute
10083 1.2.4.2 wiz
10084 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
10085 1.2.4.2 wiz fmov.l %fpsr,%d1 # save FPSR
10086 1.2.4.2 wiz
10087 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
10088 1.2.4.2 wiz
10089 1.2.4.2 wiz fabs_sd_ovfl_tst:
10090 1.2.4.2 wiz or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
10091 1.2.4.2 wiz
10092 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d1
10093 1.2.4.2 wiz andi.b &0x13,%d1 # is OVFL or INEX enabled?
10094 1.2.4.2 wiz bne.b fabs_sd_ovfl_ena # yes
10095 1.2.4.2 wiz
10096 1.2.4.2 wiz #
10097 1.2.4.2 wiz # OVFL is not enabled; therefore, we must create the default result by
10098 1.2.4.2 wiz # calling ovf_res().
10099 1.2.4.2 wiz #
10100 1.2.4.2 wiz fabs_sd_ovfl_dis:
10101 1.2.4.2 wiz btst &neg_bit,FPSR_CC(%a6) # is result negative?
10102 1.2.4.2 wiz sne %d1 # set sign param accordingly
10103 1.2.4.2 wiz mov.l L_SCR3(%a6),%d0 # pass: prec,mode
10104 1.2.4.2 wiz bsr.l ovf_res # calculate default result
10105 1.2.4.2 wiz or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
10106 1.2.4.2 wiz fmovm.x (%a0),&0x80 # return default result in fp0
10107 1.2.4.2 wiz rts
10108 1.2.4.2 wiz
10109 1.2.4.2 wiz #
10110 1.2.4.2 wiz # OVFL is enabled.
10111 1.2.4.2 wiz # the INEX2 bit has already been updated by the round to the correct precision.
10112 1.2.4.2 wiz # now, round to extended(and don't alter the FPSR).
10113 1.2.4.2 wiz #
10114 1.2.4.2 wiz fabs_sd_ovfl_ena:
10115 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
10116 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
10117 1.2.4.2 wiz mov.l %d1,%d2 # make a copy
10118 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
10119 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
10120 1.2.4.2 wiz sub.l %d0,%d1 # add scale factor
10121 1.2.4.2 wiz subi.l &0x6000,%d1 # subtract bias
10122 1.2.4.2 wiz andi.w &0x7fff,%d1
10123 1.2.4.2 wiz or.w %d2,%d1 # concat sign,exp
10124 1.2.4.2 wiz mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
10125 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
10126 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
10127 1.2.4.2 wiz bra.b fabs_sd_ovfl_dis
10128 1.2.4.2 wiz
10129 1.2.4.2 wiz #
10130 1.2.4.2 wiz # the move in MAY underflow. so...
10131 1.2.4.2 wiz #
10132 1.2.4.2 wiz fabs_sd_may_ovfl:
10133 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
10134 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
10135 1.2.4.2 wiz
10136 1.2.4.2 wiz fabs.x FP_SCR0(%a6),%fp0 # perform absolute
10137 1.2.4.2 wiz
10138 1.2.4.2 wiz fmov.l %fpsr,%d1 # save status
10139 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
10140 1.2.4.2 wiz
10141 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
10142 1.2.4.2 wiz
10143 1.2.4.2 wiz fabs.x %fp0,%fp1 # make a copy of result
10144 1.2.4.2 wiz fcmp.b %fp1,&0x2 # is |result| >= 2.b?
10145 1.2.4.2 wiz fbge.w fabs_sd_ovfl_tst # yes; overflow has occurred
10146 1.2.4.2 wiz
10147 1.2.4.2 wiz # no, it didn't overflow; we have correct result
10148 1.2.4.2 wiz bra.w fabs_sd_normal_exit
10149 1.2.4.2 wiz
10150 1.2.4.2 wiz ##########################################################################
10151 1.2.4.2 wiz
10152 1.2.4.2 wiz #
10153 1.2.4.2 wiz # input is not normalized; what is it?
10154 1.2.4.2 wiz #
10155 1.2.4.2 wiz fabs_not_norm:
10156 1.2.4.2 wiz cmpi.b %d1,&DENORM # weed out DENORM
10157 1.2.4.2 wiz beq.w fabs_denorm
10158 1.2.4.2 wiz cmpi.b %d1,&SNAN # weed out SNAN
10159 1.2.4.2 wiz beq.l res_snan_1op
10160 1.2.4.2 wiz cmpi.b %d1,&QNAN # weed out QNAN
10161 1.2.4.2 wiz beq.l res_qnan_1op
10162 1.2.4.2 wiz
10163 1.2.4.2 wiz fabs.x SRC(%a0),%fp0 # force absolute value
10164 1.2.4.2 wiz
10165 1.2.4.2 wiz cmpi.b %d1,&INF # weed out INF
10166 1.2.4.2 wiz beq.b fabs_inf
10167 1.2.4.2 wiz fabs_zero:
10168 1.2.4.2 wiz mov.b &z_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
10169 1.2.4.2 wiz rts
10170 1.2.4.2 wiz fabs_inf:
10171 1.2.4.2 wiz mov.b &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
10172 1.2.4.2 wiz rts
10173 1.2.4.2 wiz
10174 1.2.4.2 wiz #########################################################################
10175 1.2.4.2 wiz # XDEF **************************************************************** #
10176 1.2.4.2 wiz # fcmp(): fp compare op routine #
10177 1.2.4.2 wiz # #
10178 1.2.4.2 wiz # XREF **************************************************************** #
10179 1.2.4.2 wiz # res_qnan() - return QNAN result #
10180 1.2.4.2 wiz # res_snan() - return SNAN result #
10181 1.2.4.2 wiz # #
10182 1.2.4.2 wiz # INPUT *************************************************************** #
10183 1.2.4.2 wiz # a0 = pointer to extended precision source operand #
10184 1.2.4.2 wiz # a1 = pointer to extended precision destination operand #
10185 1.2.4.2 wiz # d0 = round prec/mode #
10186 1.2.4.2 wiz # #
10187 1.2.4.2 wiz # OUTPUT ************************************************************** #
10188 1.2.4.2 wiz # None #
10189 1.2.4.2 wiz # #
10190 1.2.4.2 wiz # ALGORITHM *********************************************************** #
10191 1.2.4.2 wiz # Handle NANs and denorms as special cases. For everything else, #
10192 1.2.4.2 wiz # just use the actual fcmp instruction to produce the correct condition #
10193 1.2.4.2 wiz # codes. #
10194 1.2.4.2 wiz # #
10195 1.2.4.2 wiz #########################################################################
10196 1.2.4.2 wiz
10197 1.2.4.2 wiz global fcmp
10198 1.2.4.2 wiz fcmp:
10199 1.2.4.2 wiz clr.w %d1
10200 1.2.4.2 wiz mov.b DTAG(%a6),%d1
10201 1.2.4.2 wiz lsl.b &0x3,%d1
10202 1.2.4.2 wiz or.b STAG(%a6),%d1
10203 1.2.4.2 wiz bne.b fcmp_not_norm # optimize on non-norm input
10204 1.2.4.2 wiz
10205 1.2.4.2 wiz #
10206 1.2.4.2 wiz # COMPARE FP OPs : NORMs, ZEROs, INFs, and "corrected" DENORMs
10207 1.2.4.2 wiz #
10208 1.2.4.2 wiz fcmp_norm:
10209 1.2.4.2 wiz fmovm.x DST(%a1),&0x80 # load dst op
10210 1.2.4.2 wiz
10211 1.2.4.2 wiz fcmp.x %fp0,SRC(%a0) # do compare
10212 1.2.4.2 wiz
10213 1.2.4.2 wiz fmov.l %fpsr,%d0 # save FPSR
10214 1.2.4.2 wiz rol.l &0x8,%d0 # extract ccode bits
10215 1.2.4.2 wiz mov.b %d0,FPSR_CC(%a6) # set ccode bits(no exc bits are set)
10216 1.2.4.2 wiz
10217 1.2.4.2 wiz rts
10218 1.2.4.2 wiz
10219 1.2.4.2 wiz #
10220 1.2.4.2 wiz # fcmp: inputs are not both normalized; what are they?
10221 1.2.4.2 wiz #
10222 1.2.4.2 wiz fcmp_not_norm:
10223 1.2.4.2 wiz mov.w (tbl_fcmp_op.b,%pc,%d1.w*2),%d1
10224 1.2.4.2 wiz jmp (tbl_fcmp_op.b,%pc,%d1.w*1)
10225 1.2.4.2 wiz
10226 1.2.4.2 wiz swbeg &48
10227 1.2.4.2 wiz tbl_fcmp_op:
10228 1.2.4.2 wiz short fcmp_norm - tbl_fcmp_op # NORM - NORM
10229 1.2.4.2 wiz short fcmp_norm - tbl_fcmp_op # NORM - ZERO
10230 1.2.4.2 wiz short fcmp_norm - tbl_fcmp_op # NORM - INF
10231 1.2.4.2 wiz short fcmp_res_qnan - tbl_fcmp_op # NORM - QNAN
10232 1.2.4.2 wiz short fcmp_nrm_dnrm - tbl_fcmp_op # NORM - DENORM
10233 1.2.4.2 wiz short fcmp_res_snan - tbl_fcmp_op # NORM - SNAN
10234 1.2.4.2 wiz short tbl_fcmp_op - tbl_fcmp_op #
10235 1.2.4.2 wiz short tbl_fcmp_op - tbl_fcmp_op #
10236 1.2.4.2 wiz
10237 1.2.4.2 wiz short fcmp_norm - tbl_fcmp_op # ZERO - NORM
10238 1.2.4.2 wiz short fcmp_norm - tbl_fcmp_op # ZERO - ZERO
10239 1.2.4.2 wiz short fcmp_norm - tbl_fcmp_op # ZERO - INF
10240 1.2.4.2 wiz short fcmp_res_qnan - tbl_fcmp_op # ZERO - QNAN
10241 1.2.4.2 wiz short fcmp_dnrm_s - tbl_fcmp_op # ZERO - DENORM
10242 1.2.4.2 wiz short fcmp_res_snan - tbl_fcmp_op # ZERO - SNAN
10243 1.2.4.2 wiz short tbl_fcmp_op - tbl_fcmp_op #
10244 1.2.4.2 wiz short tbl_fcmp_op - tbl_fcmp_op #
10245 1.2.4.2 wiz
10246 1.2.4.2 wiz short fcmp_norm - tbl_fcmp_op # INF - NORM
10247 1.2.4.2 wiz short fcmp_norm - tbl_fcmp_op # INF - ZERO
10248 1.2.4.2 wiz short fcmp_norm - tbl_fcmp_op # INF - INF
10249 1.2.4.2 wiz short fcmp_res_qnan - tbl_fcmp_op # INF - QNAN
10250 1.2.4.2 wiz short fcmp_dnrm_s - tbl_fcmp_op # INF - DENORM
10251 1.2.4.2 wiz short fcmp_res_snan - tbl_fcmp_op # INF - SNAN
10252 1.2.4.2 wiz short tbl_fcmp_op - tbl_fcmp_op #
10253 1.2.4.2 wiz short tbl_fcmp_op - tbl_fcmp_op #
10254 1.2.4.2 wiz
10255 1.2.4.2 wiz short fcmp_res_qnan - tbl_fcmp_op # QNAN - NORM
10256 1.2.4.2 wiz short fcmp_res_qnan - tbl_fcmp_op # QNAN - ZERO
10257 1.2.4.2 wiz short fcmp_res_qnan - tbl_fcmp_op # QNAN - INF
10258 1.2.4.2 wiz short fcmp_res_qnan - tbl_fcmp_op # QNAN - QNAN
10259 1.2.4.2 wiz short fcmp_res_qnan - tbl_fcmp_op # QNAN - DENORM
10260 1.2.4.2 wiz short fcmp_res_snan - tbl_fcmp_op # QNAN - SNAN
10261 1.2.4.2 wiz short tbl_fcmp_op - tbl_fcmp_op #
10262 1.2.4.2 wiz short tbl_fcmp_op - tbl_fcmp_op #
10263 1.2.4.2 wiz
10264 1.2.4.2 wiz short fcmp_dnrm_nrm - tbl_fcmp_op # DENORM - NORM
10265 1.2.4.2 wiz short fcmp_dnrm_d - tbl_fcmp_op # DENORM - ZERO
10266 1.2.4.2 wiz short fcmp_dnrm_d - tbl_fcmp_op # DENORM - INF
10267 1.2.4.2 wiz short fcmp_res_qnan - tbl_fcmp_op # DENORM - QNAN
10268 1.2.4.2 wiz short fcmp_dnrm_sd - tbl_fcmp_op # DENORM - DENORM
10269 1.2.4.2 wiz short fcmp_res_snan - tbl_fcmp_op # DENORM - SNAN
10270 1.2.4.2 wiz short tbl_fcmp_op - tbl_fcmp_op #
10271 1.2.4.2 wiz short tbl_fcmp_op - tbl_fcmp_op #
10272 1.2.4.2 wiz
10273 1.2.4.2 wiz short fcmp_res_snan - tbl_fcmp_op # SNAN - NORM
10274 1.2.4.2 wiz short fcmp_res_snan - tbl_fcmp_op # SNAN - ZERO
10275 1.2.4.2 wiz short fcmp_res_snan - tbl_fcmp_op # SNAN - INF
10276 1.2.4.2 wiz short fcmp_res_snan - tbl_fcmp_op # SNAN - QNAN
10277 1.2.4.2 wiz short fcmp_res_snan - tbl_fcmp_op # SNAN - DENORM
10278 1.2.4.2 wiz short fcmp_res_snan - tbl_fcmp_op # SNAN - SNAN
10279 1.2.4.2 wiz short tbl_fcmp_op - tbl_fcmp_op #
10280 1.2.4.2 wiz short tbl_fcmp_op - tbl_fcmp_op #
10281 1.2.4.2 wiz
10282 1.2.4.2 wiz # unlike all other functions for QNAN and SNAN, fcmp does NOT set the
10283 1.2.4.2 wiz # 'N' bit for a negative QNAN or SNAN input so we must squelch it here.
10284 1.2.4.2 wiz fcmp_res_qnan:
10285 1.2.4.2 wiz bsr.l res_qnan
10286 1.2.4.2 wiz andi.b &0xf7,FPSR_CC(%a6)
10287 1.2.4.2 wiz rts
10288 1.2.4.2 wiz fcmp_res_snan:
10289 1.2.4.2 wiz bsr.l res_snan
10290 1.2.4.2 wiz andi.b &0xf7,FPSR_CC(%a6)
10291 1.2.4.2 wiz rts
10292 1.2.4.2 wiz
10293 1.2.4.2 wiz #
10294 1.2.4.2 wiz # DENORMs are a little more difficult.
10295 1.2.4.2 wiz # If you have a 2 DENORMs, then you can just force the j-bit to a one
10296 1.2.4.2 wiz # and use the fcmp_norm routine.
10297 1.2.4.2 wiz # If you have a DENORM and an INF or ZERO, just force the DENORM's j-bit to a one
10298 1.2.4.2 wiz # and use the fcmp_norm routine.
10299 1.2.4.2 wiz # If you have a DENORM and a NORM with opposite signs, then use fcmp_norm, also.
10300 1.2.4.2 wiz # But with a DENORM and a NORM of the same sign, the neg bit is set if the
10301 1.2.4.2 wiz # (1) signs are (+) and the DENORM is the dst or
10302 1.2.4.2 wiz # (2) signs are (-) and the DENORM is the src
10303 1.2.4.2 wiz #
10304 1.2.4.2 wiz
10305 1.2.4.2 wiz fcmp_dnrm_s:
10306 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
10307 1.2.4.2 wiz mov.l SRC_HI(%a0),%d0
10308 1.2.4.2 wiz bset &31,%d0 # DENORM src; make into small norm
10309 1.2.4.2 wiz mov.l %d0,FP_SCR0_HI(%a6)
10310 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
10311 1.2.4.2 wiz lea FP_SCR0(%a6),%a0
10312 1.2.4.2 wiz bra.w fcmp_norm
10313 1.2.4.2 wiz
10314 1.2.4.2 wiz fcmp_dnrm_d:
10315 1.2.4.2 wiz mov.l DST_EX(%a1),FP_SCR0_EX(%a6)
10316 1.2.4.2 wiz mov.l DST_HI(%a1),%d0
10317 1.2.4.2 wiz bset &31,%d0 # DENORM src; make into small norm
10318 1.2.4.2 wiz mov.l %d0,FP_SCR0_HI(%a6)
10319 1.2.4.2 wiz mov.l DST_LO(%a1),FP_SCR0_LO(%a6)
10320 1.2.4.2 wiz lea FP_SCR0(%a6),%a1
10321 1.2.4.2 wiz bra.w fcmp_norm
10322 1.2.4.2 wiz
10323 1.2.4.2 wiz fcmp_dnrm_sd:
10324 1.2.4.2 wiz mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
10325 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
10326 1.2.4.2 wiz mov.l DST_HI(%a1),%d0
10327 1.2.4.2 wiz bset &31,%d0 # DENORM dst; make into small norm
10328 1.2.4.2 wiz mov.l %d0,FP_SCR1_HI(%a6)
10329 1.2.4.2 wiz mov.l SRC_HI(%a0),%d0
10330 1.2.4.2 wiz bset &31,%d0 # DENORM dst; make into small norm
10331 1.2.4.2 wiz mov.l %d0,FP_SCR0_HI(%a6)
10332 1.2.4.2 wiz mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
10333 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
10334 1.2.4.2 wiz lea FP_SCR1(%a6),%a1
10335 1.2.4.2 wiz lea FP_SCR0(%a6),%a0
10336 1.2.4.2 wiz bra.w fcmp_norm
10337 1.2.4.2 wiz
10338 1.2.4.2 wiz fcmp_nrm_dnrm:
10339 1.2.4.2 wiz mov.b SRC_EX(%a0),%d0 # determine if like signs
10340 1.2.4.2 wiz mov.b DST_EX(%a1),%d1
10341 1.2.4.2 wiz eor.b %d0,%d1
10342 1.2.4.2 wiz bmi.w fcmp_dnrm_s
10343 1.2.4.2 wiz
10344 1.2.4.2 wiz # signs are the same, so must determine the answer ourselves.
10345 1.2.4.2 wiz tst.b %d0 # is src op negative?
10346 1.2.4.2 wiz bmi.b fcmp_nrm_dnrm_m # yes
10347 1.2.4.2 wiz rts
10348 1.2.4.2 wiz fcmp_nrm_dnrm_m:
10349 1.2.4.2 wiz mov.b &neg_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
10350 1.2.4.2 wiz rts
10351 1.2.4.2 wiz
10352 1.2.4.2 wiz fcmp_dnrm_nrm:
10353 1.2.4.2 wiz mov.b SRC_EX(%a0),%d0 # determine if like signs
10354 1.2.4.2 wiz mov.b DST_EX(%a1),%d1
10355 1.2.4.2 wiz eor.b %d0,%d1
10356 1.2.4.2 wiz bmi.w fcmp_dnrm_d
10357 1.2.4.2 wiz
10358 1.2.4.2 wiz # signs are the same, so must determine the answer ourselves.
10359 1.2.4.2 wiz tst.b %d0 # is src op negative?
10360 1.2.4.2 wiz bpl.b fcmp_dnrm_nrm_m # no
10361 1.2.4.2 wiz rts
10362 1.2.4.2 wiz fcmp_dnrm_nrm_m:
10363 1.2.4.2 wiz mov.b &neg_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
10364 1.2.4.2 wiz rts
10365 1.2.4.2 wiz
10366 1.2.4.2 wiz #########################################################################
10367 1.2.4.2 wiz # XDEF **************************************************************** #
10368 1.2.4.2 wiz # fsglmul(): emulates the fsglmul instruction #
10369 1.2.4.2 wiz # #
10370 1.2.4.2 wiz # XREF **************************************************************** #
10371 1.2.4.2 wiz # scale_to_zero_src() - scale src exponent to zero #
10372 1.2.4.2 wiz # scale_to_zero_dst() - scale dst exponent to zero #
10373 1.2.4.2 wiz # unf_res4() - return default underflow result for sglop #
10374 1.2.4.2 wiz # ovf_res() - return default overflow result #
10375 1.2.4.2 wiz # res_qnan() - return QNAN result #
10376 1.2.4.2 wiz # res_snan() - return SNAN result #
10377 1.2.4.2 wiz # #
10378 1.2.4.2 wiz # INPUT *************************************************************** #
10379 1.2.4.2 wiz # a0 = pointer to extended precision source operand #
10380 1.2.4.2 wiz # a1 = pointer to extended precision destination operand #
10381 1.2.4.2 wiz # d0 rnd prec,mode #
10382 1.2.4.2 wiz # #
10383 1.2.4.2 wiz # OUTPUT ************************************************************** #
10384 1.2.4.2 wiz # fp0 = result #
10385 1.2.4.2 wiz # fp1 = EXOP (if exception occurred) #
10386 1.2.4.2 wiz # #
10387 1.2.4.2 wiz # ALGORITHM *********************************************************** #
10388 1.2.4.2 wiz # Handle NANs, infinities, and zeroes as special cases. Divide #
10389 1.2.4.2 wiz # norms/denorms into ext/sgl/dbl precision. #
10390 1.2.4.2 wiz # For norms/denorms, scale the exponents such that a multiply #
10391 1.2.4.2 wiz # instruction won't cause an exception. Use the regular fsglmul to #
10392 1.2.4.2 wiz # compute a result. Check if the regular operands would have taken #
10393 1.2.4.2 wiz # an exception. If so, return the default overflow/underflow result #
10394 1.2.4.2 wiz # and return the EXOP if exceptions are enabled. Else, scale the #
10395 1.2.4.2 wiz # result operand to the proper exponent. #
10396 1.2.4.2 wiz # #
10397 1.2.4.2 wiz #########################################################################
10398 1.2.4.2 wiz
10399 1.2.4.2 wiz global fsglmul
10400 1.2.4.2 wiz fsglmul:
10401 1.2.4.2 wiz mov.l %d0,L_SCR3(%a6) # store rnd info
10402 1.2.4.2 wiz
10403 1.2.4.2 wiz clr.w %d1
10404 1.2.4.2 wiz mov.b DTAG(%a6),%d1
10405 1.2.4.2 wiz lsl.b &0x3,%d1
10406 1.2.4.2 wiz or.b STAG(%a6),%d1
10407 1.2.4.2 wiz
10408 1.2.4.2 wiz bne.w fsglmul_not_norm # optimize on non-norm input
10409 1.2.4.2 wiz
10410 1.2.4.2 wiz fsglmul_norm:
10411 1.2.4.2 wiz mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
10412 1.2.4.2 wiz mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
10413 1.2.4.2 wiz mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
10414 1.2.4.2 wiz
10415 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
10416 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
10417 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
10418 1.2.4.2 wiz
10419 1.2.4.2 wiz bsr.l scale_to_zero_src # scale exponent
10420 1.2.4.2 wiz mov.l %d0,-(%sp) # save scale factor 1
10421 1.2.4.2 wiz
10422 1.2.4.2 wiz bsr.l scale_to_zero_dst # scale dst exponent
10423 1.2.4.2 wiz
10424 1.2.4.2 wiz add.l (%sp)+,%d0 # SCALE_FACTOR = scale1 + scale2
10425 1.2.4.2 wiz
10426 1.2.4.2 wiz cmpi.l %d0,&0x3fff-0x7ffe # would result ovfl?
10427 1.2.4.2 wiz beq.w fsglmul_may_ovfl # result may rnd to overflow
10428 1.2.4.2 wiz blt.w fsglmul_ovfl # result will overflow
10429 1.2.4.2 wiz
10430 1.2.4.2 wiz cmpi.l %d0,&0x3fff+0x0001 # would result unfl?
10431 1.2.4.2 wiz beq.w fsglmul_may_unfl # result may rnd to no unfl
10432 1.2.4.2 wiz bgt.w fsglmul_unfl # result will underflow
10433 1.2.4.2 wiz
10434 1.2.4.2 wiz fsglmul_normal:
10435 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst op
10436 1.2.4.2 wiz
10437 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
10438 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
10439 1.2.4.2 wiz
10440 1.2.4.2 wiz fsglmul.x FP_SCR0(%a6),%fp0 # execute sgl multiply
10441 1.2.4.2 wiz
10442 1.2.4.2 wiz fmov.l %fpsr,%d1 # save status
10443 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
10444 1.2.4.2 wiz
10445 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
10446 1.2.4.2 wiz
10447 1.2.4.2 wiz fsglmul_normal_exit:
10448 1.2.4.2 wiz fmovm.x &0x80,FP_SCR0(%a6) # store out result
10449 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
10450 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # load {sgn,exp}
10451 1.2.4.2 wiz mov.l %d1,%d2 # make a copy
10452 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
10453 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
10454 1.2.4.2 wiz sub.l %d0,%d1 # add scale factor
10455 1.2.4.2 wiz or.w %d2,%d1 # concat old sign,new exp
10456 1.2.4.2 wiz mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
10457 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
10458 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
10459 1.2.4.2 wiz rts
10460 1.2.4.2 wiz
10461 1.2.4.2 wiz fsglmul_ovfl:
10462 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst op
10463 1.2.4.2 wiz
10464 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
10465 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
10466 1.2.4.2 wiz
10467 1.2.4.2 wiz fsglmul.x FP_SCR0(%a6),%fp0 # execute sgl multiply
10468 1.2.4.2 wiz
10469 1.2.4.2 wiz fmov.l %fpsr,%d1 # save status
10470 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
10471 1.2.4.2 wiz
10472 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
10473 1.2.4.2 wiz
10474 1.2.4.2 wiz fsglmul_ovfl_tst:
10475 1.2.4.2 wiz
10476 1.2.4.2 wiz # save setting this until now because this is where fsglmul_may_ovfl may jump in
10477 1.2.4.2 wiz or.l &ovfl_inx_mask, USER_FPSR(%a6) # set ovfl/aovfl/ainex
10478 1.2.4.2 wiz
10479 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d1
10480 1.2.4.2 wiz andi.b &0x13,%d1 # is OVFL or INEX enabled?
10481 1.2.4.2 wiz bne.b fsglmul_ovfl_ena # yes
10482 1.2.4.2 wiz
10483 1.2.4.2 wiz fsglmul_ovfl_dis:
10484 1.2.4.2 wiz btst &neg_bit,FPSR_CC(%a6) # is result negative?
10485 1.2.4.2 wiz sne %d1 # set sign param accordingly
10486 1.2.4.2 wiz mov.l L_SCR3(%a6),%d0 # pass prec:rnd
10487 1.2.4.2 wiz andi.b &0x30,%d0 # force prec = ext
10488 1.2.4.2 wiz bsr.l ovf_res # calculate default result
10489 1.2.4.2 wiz or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
10490 1.2.4.2 wiz fmovm.x (%a0),&0x80 # return default result in fp0
10491 1.2.4.2 wiz rts
10492 1.2.4.2 wiz
10493 1.2.4.2 wiz fsglmul_ovfl_ena:
10494 1.2.4.2 wiz fmovm.x &0x80,FP_SCR0(%a6) # move result to stack
10495 1.2.4.2 wiz
10496 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
10497 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
10498 1.2.4.2 wiz mov.l %d1,%d2 # make a copy
10499 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
10500 1.2.4.2 wiz sub.l %d0,%d1 # add scale factor
10501 1.2.4.2 wiz subi.l &0x6000,%d1 # subtract bias
10502 1.2.4.2 wiz andi.w &0x7fff,%d1
10503 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
10504 1.2.4.2 wiz or.w %d2,%d1 # concat old sign,new exp
10505 1.2.4.2 wiz mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
10506 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
10507 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
10508 1.2.4.2 wiz bra.b fsglmul_ovfl_dis
10509 1.2.4.2 wiz
10510 1.2.4.2 wiz fsglmul_may_ovfl:
10511 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst op
10512 1.2.4.2 wiz
10513 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
10514 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
10515 1.2.4.2 wiz
10516 1.2.4.2 wiz fsglmul.x FP_SCR0(%a6),%fp0 # execute sgl multiply
10517 1.2.4.2 wiz
10518 1.2.4.2 wiz fmov.l %fpsr,%d1 # save status
10519 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
10520 1.2.4.2 wiz
10521 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
10522 1.2.4.2 wiz
10523 1.2.4.2 wiz fabs.x %fp0,%fp1 # make a copy of result
10524 1.2.4.2 wiz fcmp.b %fp1,&0x2 # is |result| >= 2.b?
10525 1.2.4.2 wiz fbge.w fsglmul_ovfl_tst # yes; overflow has occurred
10526 1.2.4.2 wiz
10527 1.2.4.2 wiz # no, it didn't overflow; we have correct result
10528 1.2.4.2 wiz bra.w fsglmul_normal_exit
10529 1.2.4.2 wiz
10530 1.2.4.2 wiz fsglmul_unfl:
10531 1.2.4.2 wiz bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
10532 1.2.4.2 wiz
10533 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst op
10534 1.2.4.2 wiz
10535 1.2.4.2 wiz fmov.l &rz_mode*0x10,%fpcr # set FPCR
10536 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
10537 1.2.4.2 wiz
10538 1.2.4.2 wiz fsglmul.x FP_SCR0(%a6),%fp0 # execute sgl multiply
10539 1.2.4.2 wiz
10540 1.2.4.2 wiz fmov.l %fpsr,%d1 # save status
10541 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
10542 1.2.4.2 wiz
10543 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
10544 1.2.4.2 wiz
10545 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d1
10546 1.2.4.2 wiz andi.b &0x0b,%d1 # is UNFL or INEX enabled?
10547 1.2.4.2 wiz bne.b fsglmul_unfl_ena # yes
10548 1.2.4.2 wiz
10549 1.2.4.2 wiz fsglmul_unfl_dis:
10550 1.2.4.2 wiz fmovm.x &0x80,FP_SCR0(%a6) # store out result
10551 1.2.4.2 wiz
10552 1.2.4.2 wiz lea FP_SCR0(%a6),%a0 # pass: result addr
10553 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
10554 1.2.4.2 wiz bsr.l unf_res4 # calculate default result
10555 1.2.4.2 wiz or.b %d0,FPSR_CC(%a6) # 'Z' bit may have been set
10556 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
10557 1.2.4.2 wiz rts
10558 1.2.4.2 wiz
10559 1.2.4.2 wiz #
10560 1.2.4.2 wiz # UNFL is enabled.
10561 1.2.4.2 wiz #
10562 1.2.4.2 wiz fsglmul_unfl_ena:
10563 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x40 # load dst op
10564 1.2.4.2 wiz
10565 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
10566 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
10567 1.2.4.2 wiz
10568 1.2.4.2 wiz fsglmul.x FP_SCR0(%a6),%fp1 # execute sgl multiply
10569 1.2.4.2 wiz
10570 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
10571 1.2.4.2 wiz
10572 1.2.4.2 wiz fmovm.x &0x40,FP_SCR0(%a6) # save result to stack
10573 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
10574 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
10575 1.2.4.2 wiz mov.l %d1,%d2 # make a copy
10576 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
10577 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
10578 1.2.4.2 wiz sub.l %d0,%d1 # add scale factor
10579 1.2.4.2 wiz addi.l &0x6000,%d1 # add bias
10580 1.2.4.2 wiz andi.w &0x7fff,%d1
10581 1.2.4.2 wiz or.w %d2,%d1 # concat old sign,new exp
10582 1.2.4.2 wiz mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
10583 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
10584 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
10585 1.2.4.2 wiz bra.w fsglmul_unfl_dis
10586 1.2.4.2 wiz
10587 1.2.4.2 wiz fsglmul_may_unfl:
10588 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst op
10589 1.2.4.2 wiz
10590 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
10591 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
10592 1.2.4.2 wiz
10593 1.2.4.2 wiz fsglmul.x FP_SCR0(%a6),%fp0 # execute sgl multiply
10594 1.2.4.2 wiz
10595 1.2.4.2 wiz fmov.l %fpsr,%d1 # save status
10596 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
10597 1.2.4.2 wiz
10598 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
10599 1.2.4.2 wiz
10600 1.2.4.2 wiz fabs.x %fp0,%fp1 # make a copy of result
10601 1.2.4.2 wiz fcmp.b %fp1,&0x2 # is |result| > 2.b?
10602 1.2.4.2 wiz fbgt.w fsglmul_normal_exit # no; no underflow occurred
10603 1.2.4.2 wiz fblt.w fsglmul_unfl # yes; underflow occurred
10604 1.2.4.2 wiz
10605 1.2.4.2 wiz #
10606 1.2.4.2 wiz # we still don't know if underflow occurred. result is ~ equal to 2. but,
10607 1.2.4.2 wiz # we don't know if the result was an underflow that rounded up to a 2 or
10608 1.2.4.2 wiz # a normalized number that rounded down to a 2. so, redo the entire operation
10609 1.2.4.2 wiz # using RZ as the rounding mode to see what the pre-rounded result is.
10610 1.2.4.2 wiz # this case should be relatively rare.
10611 1.2.4.2 wiz #
10612 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x40 # load dst op into fp1
10613 1.2.4.2 wiz
10614 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1
10615 1.2.4.2 wiz andi.b &0xc0,%d1 # keep rnd prec
10616 1.2.4.2 wiz ori.b &rz_mode*0x10,%d1 # insert RZ
10617 1.2.4.2 wiz
10618 1.2.4.2 wiz fmov.l %d1,%fpcr # set FPCR
10619 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
10620 1.2.4.2 wiz
10621 1.2.4.2 wiz fsglmul.x FP_SCR0(%a6),%fp1 # execute sgl multiply
10622 1.2.4.2 wiz
10623 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
10624 1.2.4.2 wiz fabs.x %fp1 # make absolute value
10625 1.2.4.2 wiz fcmp.b %fp1,&0x2 # is |result| < 2.b?
10626 1.2.4.2 wiz fbge.w fsglmul_normal_exit # no; no underflow occurred
10627 1.2.4.2 wiz bra.w fsglmul_unfl # yes, underflow occurred
10628 1.2.4.2 wiz
10629 1.2.4.2 wiz ##############################################################################
10630 1.2.4.2 wiz
10631 1.2.4.2 wiz #
10632 1.2.4.2 wiz # Single Precision Multiply: inputs are not both normalized; what are they?
10633 1.2.4.2 wiz #
10634 1.2.4.2 wiz fsglmul_not_norm:
10635 1.2.4.2 wiz mov.w (tbl_fsglmul_op.b,%pc,%d1.w*2),%d1
10636 1.2.4.2 wiz jmp (tbl_fsglmul_op.b,%pc,%d1.w*1)
10637 1.2.4.2 wiz
10638 1.2.4.2 wiz swbeg &48
10639 1.2.4.2 wiz tbl_fsglmul_op:
10640 1.2.4.2 wiz short fsglmul_norm - tbl_fsglmul_op # NORM x NORM
10641 1.2.4.2 wiz short fsglmul_zero - tbl_fsglmul_op # NORM x ZERO
10642 1.2.4.2 wiz short fsglmul_inf_src - tbl_fsglmul_op # NORM x INF
10643 1.2.4.2 wiz short fsglmul_res_qnan - tbl_fsglmul_op # NORM x QNAN
10644 1.2.4.2 wiz short fsglmul_norm - tbl_fsglmul_op # NORM x DENORM
10645 1.2.4.2 wiz short fsglmul_res_snan - tbl_fsglmul_op # NORM x SNAN
10646 1.2.4.2 wiz short tbl_fsglmul_op - tbl_fsglmul_op #
10647 1.2.4.2 wiz short tbl_fsglmul_op - tbl_fsglmul_op #
10648 1.2.4.2 wiz
10649 1.2.4.2 wiz short fsglmul_zero - tbl_fsglmul_op # ZERO x NORM
10650 1.2.4.2 wiz short fsglmul_zero - tbl_fsglmul_op # ZERO x ZERO
10651 1.2.4.2 wiz short fsglmul_res_operr - tbl_fsglmul_op # ZERO x INF
10652 1.2.4.2 wiz short fsglmul_res_qnan - tbl_fsglmul_op # ZERO x QNAN
10653 1.2.4.2 wiz short fsglmul_zero - tbl_fsglmul_op # ZERO x DENORM
10654 1.2.4.2 wiz short fsglmul_res_snan - tbl_fsglmul_op # ZERO x SNAN
10655 1.2.4.2 wiz short tbl_fsglmul_op - tbl_fsglmul_op #
10656 1.2.4.2 wiz short tbl_fsglmul_op - tbl_fsglmul_op #
10657 1.2.4.2 wiz
10658 1.2.4.2 wiz short fsglmul_inf_dst - tbl_fsglmul_op # INF x NORM
10659 1.2.4.2 wiz short fsglmul_res_operr - tbl_fsglmul_op # INF x ZERO
10660 1.2.4.2 wiz short fsglmul_inf_dst - tbl_fsglmul_op # INF x INF
10661 1.2.4.2 wiz short fsglmul_res_qnan - tbl_fsglmul_op # INF x QNAN
10662 1.2.4.2 wiz short fsglmul_inf_dst - tbl_fsglmul_op # INF x DENORM
10663 1.2.4.2 wiz short fsglmul_res_snan - tbl_fsglmul_op # INF x SNAN
10664 1.2.4.2 wiz short tbl_fsglmul_op - tbl_fsglmul_op #
10665 1.2.4.2 wiz short tbl_fsglmul_op - tbl_fsglmul_op #
10666 1.2.4.2 wiz
10667 1.2.4.2 wiz short fsglmul_res_qnan - tbl_fsglmul_op # QNAN x NORM
10668 1.2.4.2 wiz short fsglmul_res_qnan - tbl_fsglmul_op # QNAN x ZERO
10669 1.2.4.2 wiz short fsglmul_res_qnan - tbl_fsglmul_op # QNAN x INF
10670 1.2.4.2 wiz short fsglmul_res_qnan - tbl_fsglmul_op # QNAN x QNAN
10671 1.2.4.2 wiz short fsglmul_res_qnan - tbl_fsglmul_op # QNAN x DENORM
10672 1.2.4.2 wiz short fsglmul_res_snan - tbl_fsglmul_op # QNAN x SNAN
10673 1.2.4.2 wiz short tbl_fsglmul_op - tbl_fsglmul_op #
10674 1.2.4.2 wiz short tbl_fsglmul_op - tbl_fsglmul_op #
10675 1.2.4.2 wiz
10676 1.2.4.2 wiz short fsglmul_norm - tbl_fsglmul_op # NORM x NORM
10677 1.2.4.2 wiz short fsglmul_zero - tbl_fsglmul_op # NORM x ZERO
10678 1.2.4.2 wiz short fsglmul_inf_src - tbl_fsglmul_op # NORM x INF
10679 1.2.4.2 wiz short fsglmul_res_qnan - tbl_fsglmul_op # NORM x QNAN
10680 1.2.4.2 wiz short fsglmul_norm - tbl_fsglmul_op # NORM x DENORM
10681 1.2.4.2 wiz short fsglmul_res_snan - tbl_fsglmul_op # NORM x SNAN
10682 1.2.4.2 wiz short tbl_fsglmul_op - tbl_fsglmul_op #
10683 1.2.4.2 wiz short tbl_fsglmul_op - tbl_fsglmul_op #
10684 1.2.4.2 wiz
10685 1.2.4.2 wiz short fsglmul_res_snan - tbl_fsglmul_op # SNAN x NORM
10686 1.2.4.2 wiz short fsglmul_res_snan - tbl_fsglmul_op # SNAN x ZERO
10687 1.2.4.2 wiz short fsglmul_res_snan - tbl_fsglmul_op # SNAN x INF
10688 1.2.4.2 wiz short fsglmul_res_snan - tbl_fsglmul_op # SNAN x QNAN
10689 1.2.4.2 wiz short fsglmul_res_snan - tbl_fsglmul_op # SNAN x DENORM
10690 1.2.4.2 wiz short fsglmul_res_snan - tbl_fsglmul_op # SNAN x SNAN
10691 1.2.4.2 wiz short tbl_fsglmul_op - tbl_fsglmul_op #
10692 1.2.4.2 wiz short tbl_fsglmul_op - tbl_fsglmul_op #
10693 1.2.4.2 wiz
10694 1.2.4.2 wiz fsglmul_res_operr:
10695 1.2.4.2 wiz bra.l res_operr
10696 1.2.4.2 wiz fsglmul_res_snan:
10697 1.2.4.2 wiz bra.l res_snan
10698 1.2.4.2 wiz fsglmul_res_qnan:
10699 1.2.4.2 wiz bra.l res_qnan
10700 1.2.4.2 wiz fsglmul_zero:
10701 1.2.4.2 wiz bra.l fmul_zero
10702 1.2.4.2 wiz fsglmul_inf_src:
10703 1.2.4.2 wiz bra.l fmul_inf_src
10704 1.2.4.2 wiz fsglmul_inf_dst:
10705 1.2.4.2 wiz bra.l fmul_inf_dst
10706 1.2.4.2 wiz
10707 1.2.4.2 wiz #########################################################################
10708 1.2.4.2 wiz # XDEF **************************************************************** #
10709 1.2.4.2 wiz # fsgldiv(): emulates the fsgldiv instruction #
10710 1.2.4.2 wiz # #
10711 1.2.4.2 wiz # XREF **************************************************************** #
10712 1.2.4.2 wiz # scale_to_zero_src() - scale src exponent to zero #
10713 1.2.4.2 wiz # scale_to_zero_dst() - scale dst exponent to zero #
10714 1.2.4.2 wiz # unf_res4() - return default underflow result for sglop #
10715 1.2.4.2 wiz # ovf_res() - return default overflow result #
10716 1.2.4.2 wiz # res_qnan() - return QNAN result #
10717 1.2.4.2 wiz # res_snan() - return SNAN result #
10718 1.2.4.2 wiz # #
10719 1.2.4.2 wiz # INPUT *************************************************************** #
10720 1.2.4.2 wiz # a0 = pointer to extended precision source operand #
10721 1.2.4.2 wiz # a1 = pointer to extended precision destination operand #
10722 1.2.4.2 wiz # d0 rnd prec,mode #
10723 1.2.4.2 wiz # #
10724 1.2.4.2 wiz # OUTPUT ************************************************************** #
10725 1.2.4.2 wiz # fp0 = result #
10726 1.2.4.2 wiz # fp1 = EXOP (if exception occurred) #
10727 1.2.4.2 wiz # #
10728 1.2.4.2 wiz # ALGORITHM *********************************************************** #
10729 1.2.4.2 wiz # Handle NANs, infinities, and zeroes as special cases. Divide #
10730 1.2.4.2 wiz # norms/denorms into ext/sgl/dbl precision. #
10731 1.2.4.2 wiz # For norms/denorms, scale the exponents such that a divide #
10732 1.2.4.2 wiz # instruction won't cause an exception. Use the regular fsgldiv to #
10733 1.2.4.2 wiz # compute a result. Check if the regular operands would have taken #
10734 1.2.4.2 wiz # an exception. If so, return the default overflow/underflow result #
10735 1.2.4.2 wiz # and return the EXOP if exceptions are enabled. Else, scale the #
10736 1.2.4.2 wiz # result operand to the proper exponent. #
10737 1.2.4.2 wiz # #
10738 1.2.4.2 wiz #########################################################################
10739 1.2.4.2 wiz
10740 1.2.4.2 wiz global fsgldiv
10741 1.2.4.2 wiz fsgldiv:
10742 1.2.4.2 wiz mov.l %d0,L_SCR3(%a6) # store rnd info
10743 1.2.4.2 wiz
10744 1.2.4.2 wiz clr.w %d1
10745 1.2.4.2 wiz mov.b DTAG(%a6),%d1
10746 1.2.4.2 wiz lsl.b &0x3,%d1
10747 1.2.4.2 wiz or.b STAG(%a6),%d1 # combine src tags
10748 1.2.4.2 wiz
10749 1.2.4.2 wiz bne.w fsgldiv_not_norm # optimize on non-norm input
10750 1.2.4.2 wiz
10751 1.2.4.2 wiz #
10752 1.2.4.2 wiz # DIVIDE: NORMs and DENORMs ONLY!
10753 1.2.4.2 wiz #
10754 1.2.4.2 wiz fsgldiv_norm:
10755 1.2.4.2 wiz mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
10756 1.2.4.2 wiz mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
10757 1.2.4.2 wiz mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
10758 1.2.4.2 wiz
10759 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
10760 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
10761 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
10762 1.2.4.2 wiz
10763 1.2.4.2 wiz bsr.l scale_to_zero_src # calculate scale factor 1
10764 1.2.4.2 wiz mov.l %d0,-(%sp) # save scale factor 1
10765 1.2.4.2 wiz
10766 1.2.4.2 wiz bsr.l scale_to_zero_dst # calculate scale factor 2
10767 1.2.4.2 wiz
10768 1.2.4.2 wiz neg.l (%sp) # S.F. = scale1 - scale2
10769 1.2.4.2 wiz add.l %d0,(%sp)
10770 1.2.4.2 wiz
10771 1.2.4.2 wiz mov.w 2+L_SCR3(%a6),%d1 # fetch precision,mode
10772 1.2.4.2 wiz lsr.b &0x6,%d1
10773 1.2.4.2 wiz mov.l (%sp)+,%d0
10774 1.2.4.2 wiz cmpi.l %d0,&0x3fff-0x7ffe
10775 1.2.4.2 wiz ble.w fsgldiv_may_ovfl
10776 1.2.4.2 wiz
10777 1.2.4.2 wiz cmpi.l %d0,&0x3fff-0x0000 # will result underflow?
10778 1.2.4.2 wiz beq.w fsgldiv_may_unfl # maybe
10779 1.2.4.2 wiz bgt.w fsgldiv_unfl # yes; go handle underflow
10780 1.2.4.2 wiz
10781 1.2.4.2 wiz fsgldiv_normal:
10782 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst op
10783 1.2.4.2 wiz
10784 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # save FPCR
10785 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
10786 1.2.4.2 wiz
10787 1.2.4.2 wiz fsgldiv.x FP_SCR0(%a6),%fp0 # perform sgl divide
10788 1.2.4.2 wiz
10789 1.2.4.2 wiz fmov.l %fpsr,%d1 # save FPSR
10790 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
10791 1.2.4.2 wiz
10792 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
10793 1.2.4.2 wiz
10794 1.2.4.2 wiz fsgldiv_normal_exit:
10795 1.2.4.2 wiz fmovm.x &0x80,FP_SCR0(%a6) # store result on stack
10796 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
10797 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # load {sgn,exp}
10798 1.2.4.2 wiz mov.l %d1,%d2 # make a copy
10799 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
10800 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
10801 1.2.4.2 wiz sub.l %d0,%d1 # add scale factor
10802 1.2.4.2 wiz or.w %d2,%d1 # concat old sign,new exp
10803 1.2.4.2 wiz mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
10804 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
10805 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
10806 1.2.4.2 wiz rts
10807 1.2.4.2 wiz
10808 1.2.4.2 wiz fsgldiv_may_ovfl:
10809 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst op
10810 1.2.4.2 wiz
10811 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
10812 1.2.4.2 wiz fmov.l &0x0,%fpsr # set FPSR
10813 1.2.4.2 wiz
10814 1.2.4.2 wiz fsgldiv.x FP_SCR0(%a6),%fp0 # execute divide
10815 1.2.4.2 wiz
10816 1.2.4.2 wiz fmov.l %fpsr,%d1
10817 1.2.4.2 wiz fmov.l &0x0,%fpcr
10818 1.2.4.2 wiz
10819 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX,N
10820 1.2.4.2 wiz
10821 1.2.4.2 wiz fmovm.x &0x01,-(%sp) # save result to stack
10822 1.2.4.2 wiz mov.w (%sp),%d1 # fetch new exponent
10823 1.2.4.2 wiz add.l &0xc,%sp # clear result
10824 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
10825 1.2.4.2 wiz sub.l %d0,%d1 # add scale factor
10826 1.2.4.2 wiz cmp.l %d1,&0x7fff # did divide overflow?
10827 1.2.4.2 wiz blt.b fsgldiv_normal_exit
10828 1.2.4.2 wiz
10829 1.2.4.2 wiz fsgldiv_ovfl_tst:
10830 1.2.4.2 wiz or.w &ovfl_inx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex
10831 1.2.4.2 wiz
10832 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d1
10833 1.2.4.2 wiz andi.b &0x13,%d1 # is OVFL or INEX enabled?
10834 1.2.4.2 wiz bne.b fsgldiv_ovfl_ena # yes
10835 1.2.4.2 wiz
10836 1.2.4.2 wiz fsgldiv_ovfl_dis:
10837 1.2.4.2 wiz btst &neg_bit,FPSR_CC(%a6) # is result negative
10838 1.2.4.2 wiz sne %d1 # set sign param accordingly
10839 1.2.4.2 wiz mov.l L_SCR3(%a6),%d0 # pass prec:rnd
10840 1.2.4.2 wiz andi.b &0x30,%d0 # kill precision
10841 1.2.4.2 wiz bsr.l ovf_res # calculate default result
10842 1.2.4.2 wiz or.b %d0,FPSR_CC(%a6) # set INF if applicable
10843 1.2.4.2 wiz fmovm.x (%a0),&0x80 # return default result in fp0
10844 1.2.4.2 wiz rts
10845 1.2.4.2 wiz
10846 1.2.4.2 wiz fsgldiv_ovfl_ena:
10847 1.2.4.2 wiz fmovm.x &0x80,FP_SCR0(%a6) # move result to stack
10848 1.2.4.2 wiz
10849 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
10850 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
10851 1.2.4.2 wiz mov.l %d1,%d2 # make a copy
10852 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
10853 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
10854 1.2.4.2 wiz sub.l %d0,%d1 # add scale factor
10855 1.2.4.2 wiz subi.l &0x6000,%d1 # subtract new bias
10856 1.2.4.2 wiz andi.w &0x7fff,%d1 # clear ms bit
10857 1.2.4.2 wiz or.w %d2,%d1 # concat old sign,new exp
10858 1.2.4.2 wiz mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
10859 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
10860 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
10861 1.2.4.2 wiz bra.b fsgldiv_ovfl_dis
10862 1.2.4.2 wiz
10863 1.2.4.2 wiz fsgldiv_unfl:
10864 1.2.4.2 wiz bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
10865 1.2.4.2 wiz
10866 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst op
10867 1.2.4.2 wiz
10868 1.2.4.2 wiz fmov.l &rz_mode*0x10,%fpcr # set FPCR
10869 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
10870 1.2.4.2 wiz
10871 1.2.4.2 wiz fsgldiv.x FP_SCR0(%a6),%fp0 # execute sgl divide
10872 1.2.4.2 wiz
10873 1.2.4.2 wiz fmov.l %fpsr,%d1 # save status
10874 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
10875 1.2.4.2 wiz
10876 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
10877 1.2.4.2 wiz
10878 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d1
10879 1.2.4.2 wiz andi.b &0x0b,%d1 # is UNFL or INEX enabled?
10880 1.2.4.2 wiz bne.b fsgldiv_unfl_ena # yes
10881 1.2.4.2 wiz
10882 1.2.4.2 wiz fsgldiv_unfl_dis:
10883 1.2.4.2 wiz fmovm.x &0x80,FP_SCR0(%a6) # store out result
10884 1.2.4.2 wiz
10885 1.2.4.2 wiz lea FP_SCR0(%a6),%a0 # pass: result addr
10886 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
10887 1.2.4.2 wiz bsr.l unf_res4 # calculate default result
10888 1.2.4.2 wiz or.b %d0,FPSR_CC(%a6) # 'Z' bit may have been set
10889 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
10890 1.2.4.2 wiz rts
10891 1.2.4.2 wiz
10892 1.2.4.2 wiz #
10893 1.2.4.2 wiz # UNFL is enabled.
10894 1.2.4.2 wiz #
10895 1.2.4.2 wiz fsgldiv_unfl_ena:
10896 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x40 # load dst op
10897 1.2.4.2 wiz
10898 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
10899 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
10900 1.2.4.2 wiz
10901 1.2.4.2 wiz fsgldiv.x FP_SCR0(%a6),%fp1 # execute sgl divide
10902 1.2.4.2 wiz
10903 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
10904 1.2.4.2 wiz
10905 1.2.4.2 wiz fmovm.x &0x40,FP_SCR0(%a6) # save result to stack
10906 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
10907 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
10908 1.2.4.2 wiz mov.l %d1,%d2 # make a copy
10909 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
10910 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
10911 1.2.4.2 wiz sub.l %d0,%d1 # add scale factor
10912 1.2.4.2 wiz addi.l &0x6000,%d1 # add bias
10913 1.2.4.2 wiz andi.w &0x7fff,%d1 # clear top bit
10914 1.2.4.2 wiz or.w %d2,%d1 # concat old sign, new exp
10915 1.2.4.2 wiz mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
10916 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
10917 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
10918 1.2.4.2 wiz bra.b fsgldiv_unfl_dis
10919 1.2.4.2 wiz
10920 1.2.4.2 wiz #
10921 1.2.4.2 wiz # the divide operation MAY underflow:
10922 1.2.4.2 wiz #
10923 1.2.4.2 wiz fsgldiv_may_unfl:
10924 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst op
10925 1.2.4.2 wiz
10926 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
10927 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
10928 1.2.4.2 wiz
10929 1.2.4.2 wiz fsgldiv.x FP_SCR0(%a6),%fp0 # execute sgl divide
10930 1.2.4.2 wiz
10931 1.2.4.2 wiz fmov.l %fpsr,%d1 # save status
10932 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
10933 1.2.4.2 wiz
10934 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
10935 1.2.4.2 wiz
10936 1.2.4.2 wiz fabs.x %fp0,%fp1 # make a copy of result
10937 1.2.4.2 wiz fcmp.b %fp1,&0x1 # is |result| > 1.b?
10938 1.2.4.2 wiz fbgt.w fsgldiv_normal_exit # no; no underflow occurred
10939 1.2.4.2 wiz fblt.w fsgldiv_unfl # yes; underflow occurred
10940 1.2.4.2 wiz
10941 1.2.4.2 wiz #
10942 1.2.4.2 wiz # we still don't know if underflow occurred. result is ~ equal to 1. but,
10943 1.2.4.2 wiz # we don't know if the result was an underflow that rounded up to a 1
10944 1.2.4.2 wiz # or a normalized number that rounded down to a 1. so, redo the entire
10945 1.2.4.2 wiz # operation using RZ as the rounding mode to see what the pre-rounded
10946 1.2.4.2 wiz # result is. this case should be relatively rare.
10947 1.2.4.2 wiz #
10948 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x40 # load dst op into %fp1
10949 1.2.4.2 wiz
10950 1.2.4.2 wiz clr.l %d1 # clear scratch register
10951 1.2.4.2 wiz ori.b &rz_mode*0x10,%d1 # force RZ rnd mode
10952 1.2.4.2 wiz
10953 1.2.4.2 wiz fmov.l %d1,%fpcr # set FPCR
10954 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
10955 1.2.4.2 wiz
10956 1.2.4.2 wiz fsgldiv.x FP_SCR0(%a6),%fp1 # execute sgl divide
10957 1.2.4.2 wiz
10958 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
10959 1.2.4.2 wiz fabs.x %fp1 # make absolute value
10960 1.2.4.2 wiz fcmp.b %fp1,&0x1 # is |result| < 1.b?
10961 1.2.4.2 wiz fbge.w fsgldiv_normal_exit # no; no underflow occurred
10962 1.2.4.2 wiz bra.w fsgldiv_unfl # yes; underflow occurred
10963 1.2.4.2 wiz
10964 1.2.4.2 wiz ############################################################################
10965 1.2.4.2 wiz
10966 1.2.4.2 wiz #
10967 1.2.4.2 wiz # Divide: inputs are not both normalized; what are they?
10968 1.2.4.2 wiz #
10969 1.2.4.2 wiz fsgldiv_not_norm:
10970 1.2.4.2 wiz mov.w (tbl_fsgldiv_op.b,%pc,%d1.w*2),%d1
10971 1.2.4.2 wiz jmp (tbl_fsgldiv_op.b,%pc,%d1.w*1)
10972 1.2.4.2 wiz
10973 1.2.4.2 wiz swbeg &48
10974 1.2.4.2 wiz tbl_fsgldiv_op:
10975 1.2.4.2 wiz short fsgldiv_norm - tbl_fsgldiv_op # NORM / NORM
10976 1.2.4.2 wiz short fsgldiv_inf_load - tbl_fsgldiv_op # NORM / ZERO
10977 1.2.4.2 wiz short fsgldiv_zero_load - tbl_fsgldiv_op # NORM / INF
10978 1.2.4.2 wiz short fsgldiv_res_qnan - tbl_fsgldiv_op # NORM / QNAN
10979 1.2.4.2 wiz short fsgldiv_norm - tbl_fsgldiv_op # NORM / DENORM
10980 1.2.4.2 wiz short fsgldiv_res_snan - tbl_fsgldiv_op # NORM / SNAN
10981 1.2.4.2 wiz short tbl_fsgldiv_op - tbl_fsgldiv_op #
10982 1.2.4.2 wiz short tbl_fsgldiv_op - tbl_fsgldiv_op #
10983 1.2.4.2 wiz
10984 1.2.4.2 wiz short fsgldiv_zero_load - tbl_fsgldiv_op # ZERO / NORM
10985 1.2.4.2 wiz short fsgldiv_res_operr - tbl_fsgldiv_op # ZERO / ZERO
10986 1.2.4.2 wiz short fsgldiv_zero_load - tbl_fsgldiv_op # ZERO / INF
10987 1.2.4.2 wiz short fsgldiv_res_qnan - tbl_fsgldiv_op # ZERO / QNAN
10988 1.2.4.2 wiz short fsgldiv_zero_load - tbl_fsgldiv_op # ZERO / DENORM
10989 1.2.4.2 wiz short fsgldiv_res_snan - tbl_fsgldiv_op # ZERO / SNAN
10990 1.2.4.2 wiz short tbl_fsgldiv_op - tbl_fsgldiv_op #
10991 1.2.4.2 wiz short tbl_fsgldiv_op - tbl_fsgldiv_op #
10992 1.2.4.2 wiz
10993 1.2.4.2 wiz short fsgldiv_inf_dst - tbl_fsgldiv_op # INF / NORM
10994 1.2.4.2 wiz short fsgldiv_inf_dst - tbl_fsgldiv_op # INF / ZERO
10995 1.2.4.2 wiz short fsgldiv_res_operr - tbl_fsgldiv_op # INF / INF
10996 1.2.4.2 wiz short fsgldiv_res_qnan - tbl_fsgldiv_op # INF / QNAN
10997 1.2.4.2 wiz short fsgldiv_inf_dst - tbl_fsgldiv_op # INF / DENORM
10998 1.2.4.2 wiz short fsgldiv_res_snan - tbl_fsgldiv_op # INF / SNAN
10999 1.2.4.2 wiz short tbl_fsgldiv_op - tbl_fsgldiv_op #
11000 1.2.4.2 wiz short tbl_fsgldiv_op - tbl_fsgldiv_op #
11001 1.2.4.2 wiz
11002 1.2.4.2 wiz short fsgldiv_res_qnan - tbl_fsgldiv_op # QNAN / NORM
11003 1.2.4.2 wiz short fsgldiv_res_qnan - tbl_fsgldiv_op # QNAN / ZERO
11004 1.2.4.2 wiz short fsgldiv_res_qnan - tbl_fsgldiv_op # QNAN / INF
11005 1.2.4.2 wiz short fsgldiv_res_qnan - tbl_fsgldiv_op # QNAN / QNAN
11006 1.2.4.2 wiz short fsgldiv_res_qnan - tbl_fsgldiv_op # QNAN / DENORM
11007 1.2.4.2 wiz short fsgldiv_res_snan - tbl_fsgldiv_op # QNAN / SNAN
11008 1.2.4.2 wiz short tbl_fsgldiv_op - tbl_fsgldiv_op #
11009 1.2.4.2 wiz short tbl_fsgldiv_op - tbl_fsgldiv_op #
11010 1.2.4.2 wiz
11011 1.2.4.2 wiz short fsgldiv_norm - tbl_fsgldiv_op # DENORM / NORM
11012 1.2.4.2 wiz short fsgldiv_inf_load - tbl_fsgldiv_op # DENORM / ZERO
11013 1.2.4.2 wiz short fsgldiv_zero_load - tbl_fsgldiv_op # DENORM / INF
11014 1.2.4.2 wiz short fsgldiv_res_qnan - tbl_fsgldiv_op # DENORM / QNAN
11015 1.2.4.2 wiz short fsgldiv_norm - tbl_fsgldiv_op # DENORM / DENORM
11016 1.2.4.2 wiz short fsgldiv_res_snan - tbl_fsgldiv_op # DENORM / SNAN
11017 1.2.4.2 wiz short tbl_fsgldiv_op - tbl_fsgldiv_op #
11018 1.2.4.2 wiz short tbl_fsgldiv_op - tbl_fsgldiv_op #
11019 1.2.4.2 wiz
11020 1.2.4.2 wiz short fsgldiv_res_snan - tbl_fsgldiv_op # SNAN / NORM
11021 1.2.4.2 wiz short fsgldiv_res_snan - tbl_fsgldiv_op # SNAN / ZERO
11022 1.2.4.2 wiz short fsgldiv_res_snan - tbl_fsgldiv_op # SNAN / INF
11023 1.2.4.2 wiz short fsgldiv_res_snan - tbl_fsgldiv_op # SNAN / QNAN
11024 1.2.4.2 wiz short fsgldiv_res_snan - tbl_fsgldiv_op # SNAN / DENORM
11025 1.2.4.2 wiz short fsgldiv_res_snan - tbl_fsgldiv_op # SNAN / SNAN
11026 1.2.4.2 wiz short tbl_fsgldiv_op - tbl_fsgldiv_op #
11027 1.2.4.2 wiz short tbl_fsgldiv_op - tbl_fsgldiv_op #
11028 1.2.4.2 wiz
11029 1.2.4.2 wiz fsgldiv_res_qnan:
11030 1.2.4.2 wiz bra.l res_qnan
11031 1.2.4.2 wiz fsgldiv_res_snan:
11032 1.2.4.2 wiz bra.l res_snan
11033 1.2.4.2 wiz fsgldiv_res_operr:
11034 1.2.4.2 wiz bra.l res_operr
11035 1.2.4.2 wiz fsgldiv_inf_load:
11036 1.2.4.2 wiz bra.l fdiv_inf_load
11037 1.2.4.2 wiz fsgldiv_zero_load:
11038 1.2.4.2 wiz bra.l fdiv_zero_load
11039 1.2.4.2 wiz fsgldiv_inf_dst:
11040 1.2.4.2 wiz bra.l fdiv_inf_dst
11041 1.2.4.2 wiz
11042 1.2.4.2 wiz #########################################################################
11043 1.2.4.2 wiz # XDEF **************************************************************** #
11044 1.2.4.2 wiz # fadd(): emulates the fadd instruction #
11045 1.2.4.2 wiz # fsadd(): emulates the fadd instruction #
11046 1.2.4.2 wiz # fdadd(): emulates the fdadd instruction #
11047 1.2.4.2 wiz # #
11048 1.2.4.2 wiz # XREF **************************************************************** #
11049 1.2.4.2 wiz # addsub_scaler2() - scale the operands so they won't take exc #
11050 1.2.4.2 wiz # ovf_res() - return default overflow result #
11051 1.2.4.2 wiz # unf_res() - return default underflow result #
11052 1.2.4.2 wiz # res_qnan() - set QNAN result #
11053 1.2.4.2 wiz # res_snan() - set SNAN result #
11054 1.2.4.2 wiz # res_operr() - set OPERR result #
11055 1.2.4.2 wiz # scale_to_zero_src() - set src operand exponent equal to zero #
11056 1.2.4.2 wiz # scale_to_zero_dst() - set dst operand exponent equal to zero #
11057 1.2.4.2 wiz # #
11058 1.2.4.2 wiz # INPUT *************************************************************** #
11059 1.2.4.2 wiz # a0 = pointer to extended precision source operand #
11060 1.2.4.2 wiz # a1 = pointer to extended precision destination operand #
11061 1.2.4.2 wiz # #
11062 1.2.4.2 wiz # OUTPUT ************************************************************** #
11063 1.2.4.2 wiz # fp0 = result #
11064 1.2.4.2 wiz # fp1 = EXOP (if exception occurred) #
11065 1.2.4.2 wiz # #
11066 1.2.4.2 wiz # ALGORITHM *********************************************************** #
11067 1.2.4.2 wiz # Handle NANs, infinities, and zeroes as special cases. Divide #
11068 1.2.4.2 wiz # norms into extended, single, and double precision. #
11069 1.2.4.2 wiz # Do addition after scaling exponents such that exception won't #
11070 1.2.4.2 wiz # occur. Then, check result exponent to see if exception would have #
11071 1.2.4.2 wiz # occurred. If so, return default result and maybe EXOP. Else, insert #
11072 1.2.4.2 wiz # the correct result exponent and return. Set FPSR bits as appropriate. #
11073 1.2.4.2 wiz # #
11074 1.2.4.2 wiz #########################################################################
11075 1.2.4.2 wiz
11076 1.2.4.2 wiz global fsadd
11077 1.2.4.2 wiz fsadd:
11078 1.2.4.2 wiz andi.b &0x30,%d0 # clear rnd prec
11079 1.2.4.2 wiz ori.b &s_mode*0x10,%d0 # insert sgl prec
11080 1.2.4.2 wiz bra.b fadd
11081 1.2.4.2 wiz
11082 1.2.4.2 wiz global fdadd
11083 1.2.4.2 wiz fdadd:
11084 1.2.4.2 wiz andi.b &0x30,%d0 # clear rnd prec
11085 1.2.4.2 wiz ori.b &d_mode*0x10,%d0 # insert dbl prec
11086 1.2.4.2 wiz
11087 1.2.4.2 wiz global fadd
11088 1.2.4.2 wiz fadd:
11089 1.2.4.2 wiz mov.l %d0,L_SCR3(%a6) # store rnd info
11090 1.2.4.2 wiz
11091 1.2.4.2 wiz clr.w %d1
11092 1.2.4.2 wiz mov.b DTAG(%a6),%d1
11093 1.2.4.2 wiz lsl.b &0x3,%d1
11094 1.2.4.2 wiz or.b STAG(%a6),%d1 # combine src tags
11095 1.2.4.2 wiz
11096 1.2.4.2 wiz bne.w fadd_not_norm # optimize on non-norm input
11097 1.2.4.2 wiz
11098 1.2.4.2 wiz #
11099 1.2.4.2 wiz # ADD: norms and denorms
11100 1.2.4.2 wiz #
11101 1.2.4.2 wiz fadd_norm:
11102 1.2.4.2 wiz bsr.l addsub_scaler2 # scale exponents
11103 1.2.4.2 wiz
11104 1.2.4.2 wiz fadd_zero_entry:
11105 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst op
11106 1.2.4.2 wiz
11107 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
11108 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
11109 1.2.4.2 wiz
11110 1.2.4.2 wiz fadd.x FP_SCR0(%a6),%fp0 # execute add
11111 1.2.4.2 wiz
11112 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
11113 1.2.4.2 wiz fmov.l %fpsr,%d1 # fetch INEX2,N,Z
11114 1.2.4.2 wiz
11115 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save exc and ccode bits
11116 1.2.4.2 wiz
11117 1.2.4.2 wiz fbeq.w fadd_zero_exit # if result is zero, end now
11118 1.2.4.2 wiz
11119 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
11120 1.2.4.2 wiz
11121 1.2.4.2 wiz fmovm.x &0x01,-(%sp) # save result to stack
11122 1.2.4.2 wiz
11123 1.2.4.2 wiz mov.w 2+L_SCR3(%a6),%d1
11124 1.2.4.2 wiz lsr.b &0x6,%d1
11125 1.2.4.2 wiz
11126 1.2.4.2 wiz mov.w (%sp),%d2 # fetch new sign, exp
11127 1.2.4.2 wiz andi.l &0x7fff,%d2 # strip sign
11128 1.2.4.2 wiz sub.l %d0,%d2 # add scale factor
11129 1.2.4.2 wiz
11130 1.2.4.2 wiz cmp.l %d2,(tbl_fadd_ovfl.b,%pc,%d1.w*4) # is it an overflow?
11131 1.2.4.2 wiz bge.b fadd_ovfl # yes
11132 1.2.4.2 wiz
11133 1.2.4.2 wiz cmp.l %d2,(tbl_fadd_unfl.b,%pc,%d1.w*4) # is it an underflow?
11134 1.2.4.2 wiz blt.w fadd_unfl # yes
11135 1.2.4.2 wiz beq.w fadd_may_unfl # maybe; go find out
11136 1.2.4.2 wiz
11137 1.2.4.2 wiz fadd_normal:
11138 1.2.4.2 wiz mov.w (%sp),%d1
11139 1.2.4.2 wiz andi.w &0x8000,%d1 # keep sign
11140 1.2.4.2 wiz or.w %d2,%d1 # concat sign,new exp
11141 1.2.4.2 wiz mov.w %d1,(%sp) # insert new exponent
11142 1.2.4.2 wiz
11143 1.2.4.2 wiz fmovm.x (%sp)+,&0x80 # return result in fp0
11144 1.2.4.2 wiz
11145 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
11146 1.2.4.2 wiz rts
11147 1.2.4.2 wiz
11148 1.2.4.2 wiz fadd_zero_exit:
11149 1.2.4.2 wiz # fmov.s &0x00000000,%fp0 # return zero in fp0
11150 1.2.4.2 wiz rts
11151 1.2.4.2 wiz
11152 1.2.4.2 wiz tbl_fadd_ovfl:
11153 1.2.4.2 wiz long 0x7fff # ext ovfl
11154 1.2.4.2 wiz long 0x407f # sgl ovfl
11155 1.2.4.2 wiz long 0x43ff # dbl ovfl
11156 1.2.4.2 wiz
11157 1.2.4.2 wiz tbl_fadd_unfl:
11158 1.2.4.2 wiz long 0x0000 # ext unfl
11159 1.2.4.2 wiz long 0x3f81 # sgl unfl
11160 1.2.4.2 wiz long 0x3c01 # dbl unfl
11161 1.2.4.2 wiz
11162 1.2.4.2 wiz fadd_ovfl:
11163 1.2.4.2 wiz or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
11164 1.2.4.2 wiz
11165 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d1
11166 1.2.4.2 wiz andi.b &0x13,%d1 # is OVFL or INEX enabled?
11167 1.2.4.2 wiz bne.b fadd_ovfl_ena # yes
11168 1.2.4.2 wiz
11169 1.2.4.2 wiz add.l &0xc,%sp
11170 1.2.4.2 wiz fadd_ovfl_dis:
11171 1.2.4.2 wiz btst &neg_bit,FPSR_CC(%a6) # is result negative?
11172 1.2.4.2 wiz sne %d1 # set sign param accordingly
11173 1.2.4.2 wiz mov.l L_SCR3(%a6),%d0 # pass prec:rnd
11174 1.2.4.2 wiz bsr.l ovf_res # calculate default result
11175 1.2.4.2 wiz or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
11176 1.2.4.2 wiz fmovm.x (%a0),&0x80 # return default result in fp0
11177 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
11178 1.2.4.2 wiz rts
11179 1.2.4.2 wiz
11180 1.2.4.2 wiz fadd_ovfl_ena:
11181 1.2.4.2 wiz mov.b L_SCR3(%a6),%d1
11182 1.2.4.2 wiz andi.b &0xc0,%d1 # is precision extended?
11183 1.2.4.2 wiz bne.b fadd_ovfl_ena_sd # no; prec = sgl or dbl
11184 1.2.4.2 wiz
11185 1.2.4.2 wiz fadd_ovfl_ena_cont:
11186 1.2.4.2 wiz mov.w (%sp),%d1
11187 1.2.4.2 wiz andi.w &0x8000,%d1 # keep sign
11188 1.2.4.2 wiz subi.l &0x6000,%d2 # add extra bias
11189 1.2.4.2 wiz andi.w &0x7fff,%d2
11190 1.2.4.2 wiz or.w %d2,%d1 # concat sign,new exp
11191 1.2.4.2 wiz mov.w %d1,(%sp) # insert new exponent
11192 1.2.4.2 wiz
11193 1.2.4.2 wiz fmovm.x (%sp)+,&0x40 # return EXOP in fp1
11194 1.2.4.2 wiz bra.b fadd_ovfl_dis
11195 1.2.4.2 wiz
11196 1.2.4.2 wiz fadd_ovfl_ena_sd:
11197 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst op
11198 1.2.4.2 wiz
11199 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1
11200 1.2.4.2 wiz andi.b &0x30,%d1 # keep rnd mode
11201 1.2.4.2 wiz fmov.l %d1,%fpcr # set FPCR
11202 1.2.4.2 wiz
11203 1.2.4.2 wiz fadd.x FP_SCR0(%a6),%fp0 # execute add
11204 1.2.4.2 wiz
11205 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
11206 1.2.4.2 wiz
11207 1.2.4.2 wiz add.l &0xc,%sp
11208 1.2.4.2 wiz fmovm.x &0x01,-(%sp)
11209 1.2.4.2 wiz bra.b fadd_ovfl_ena_cont
11210 1.2.4.2 wiz
11211 1.2.4.2 wiz fadd_unfl:
11212 1.2.4.2 wiz bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
11213 1.2.4.2 wiz
11214 1.2.4.2 wiz add.l &0xc,%sp
11215 1.2.4.2 wiz
11216 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst op
11217 1.2.4.2 wiz
11218 1.2.4.2 wiz fmov.l &rz_mode*0x10,%fpcr # set FPCR
11219 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
11220 1.2.4.2 wiz
11221 1.2.4.2 wiz fadd.x FP_SCR0(%a6),%fp0 # execute add
11222 1.2.4.2 wiz
11223 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
11224 1.2.4.2 wiz fmov.l %fpsr,%d1 # save status
11225 1.2.4.2 wiz
11226 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX,N
11227 1.2.4.2 wiz
11228 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d1
11229 1.2.4.2 wiz andi.b &0x0b,%d1 # is UNFL or INEX enabled?
11230 1.2.4.2 wiz bne.b fadd_unfl_ena # yes
11231 1.2.4.2 wiz
11232 1.2.4.2 wiz fadd_unfl_dis:
11233 1.2.4.2 wiz fmovm.x &0x80,FP_SCR0(%a6) # store out result
11234 1.2.4.2 wiz
11235 1.2.4.2 wiz lea FP_SCR0(%a6),%a0 # pass: result addr
11236 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
11237 1.2.4.2 wiz bsr.l unf_res # calculate default result
11238 1.2.4.2 wiz or.b %d0,FPSR_CC(%a6) # 'Z' bit may have been set
11239 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
11240 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
11241 1.2.4.2 wiz rts
11242 1.2.4.2 wiz
11243 1.2.4.2 wiz fadd_unfl_ena:
11244 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x40 # load dst op
11245 1.2.4.2 wiz
11246 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1
11247 1.2.4.2 wiz andi.b &0xc0,%d1 # is precision extended?
11248 1.2.4.2 wiz bne.b fadd_unfl_ena_sd # no; sgl or dbl
11249 1.2.4.2 wiz
11250 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
11251 1.2.4.2 wiz
11252 1.2.4.2 wiz fadd_unfl_ena_cont:
11253 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
11254 1.2.4.2 wiz
11255 1.2.4.2 wiz fadd.x FP_SCR0(%a6),%fp1 # execute multiply
11256 1.2.4.2 wiz
11257 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
11258 1.2.4.2 wiz
11259 1.2.4.2 wiz fmovm.x &0x40,FP_SCR0(%a6) # save result to stack
11260 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
11261 1.2.4.2 wiz mov.l %d1,%d2 # make a copy
11262 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
11263 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
11264 1.2.4.2 wiz sub.l %d0,%d1 # add scale factor
11265 1.2.4.2 wiz addi.l &0x6000,%d1 # add new bias
11266 1.2.4.2 wiz andi.w &0x7fff,%d1 # clear top bit
11267 1.2.4.2 wiz or.w %d2,%d1 # concat sign,new exp
11268 1.2.4.2 wiz mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
11269 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
11270 1.2.4.2 wiz bra.w fadd_unfl_dis
11271 1.2.4.2 wiz
11272 1.2.4.2 wiz fadd_unfl_ena_sd:
11273 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1
11274 1.2.4.2 wiz andi.b &0x30,%d1 # use only rnd mode
11275 1.2.4.2 wiz fmov.l %d1,%fpcr # set FPCR
11276 1.2.4.2 wiz
11277 1.2.4.2 wiz bra.b fadd_unfl_ena_cont
11278 1.2.4.2 wiz
11279 1.2.4.2 wiz #
11280 1.2.4.2 wiz # result is equal to the smallest normalized number in the selected precision
11281 1.2.4.2 wiz # if the precision is extended, this result could not have come from an
11282 1.2.4.2 wiz # underflow that rounded up.
11283 1.2.4.2 wiz #
11284 1.2.4.2 wiz fadd_may_unfl:
11285 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1
11286 1.2.4.2 wiz andi.b &0xc0,%d1
11287 1.2.4.2 wiz beq.w fadd_normal # yes; no underflow occurred
11288 1.2.4.2 wiz
11289 1.2.4.2 wiz mov.l 0x4(%sp),%d1 # extract hi(man)
11290 1.2.4.2 wiz cmpi.l %d1,&0x80000000 # is hi(man) = 0x80000000?
11291 1.2.4.2 wiz bne.w fadd_normal # no; no underflow occurred
11292 1.2.4.2 wiz
11293 1.2.4.2 wiz tst.l 0x8(%sp) # is lo(man) = 0x0?
11294 1.2.4.2 wiz bne.w fadd_normal # no; no underflow occurred
11295 1.2.4.2 wiz
11296 1.2.4.2 wiz btst &inex2_bit,FPSR_EXCEPT(%a6) # is INEX2 set?
11297 1.2.4.2 wiz beq.w fadd_normal # no; no underflow occurred
11298 1.2.4.2 wiz
11299 1.2.4.2 wiz #
11300 1.2.4.2 wiz # ok, so now the result has a exponent equal to the smallest normalized
11301 1.2.4.2 wiz # exponent for the selected precision. also, the mantissa is equal to
11302 1.2.4.2 wiz # 0x8000000000000000 and this mantissa is the result of rounding non-zero
11303 1.2.4.2 wiz # g,r,s.
11304 1.2.4.2 wiz # now, we must determine whether the pre-rounded result was an underflow
11305 1.2.4.2 wiz # rounded "up" or a normalized number rounded "down".
11306 1.2.4.2 wiz # so, we do this be re-executing the add using RZ as the rounding mode and
11307 1.2.4.2 wiz # seeing if the new result is smaller or equal to the current result.
11308 1.2.4.2 wiz #
11309 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x40 # load dst op into fp1
11310 1.2.4.2 wiz
11311 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1
11312 1.2.4.2 wiz andi.b &0xc0,%d1 # keep rnd prec
11313 1.2.4.2 wiz ori.b &rz_mode*0x10,%d1 # insert rnd mode
11314 1.2.4.2 wiz fmov.l %d1,%fpcr # set FPCR
11315 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
11316 1.2.4.2 wiz
11317 1.2.4.2 wiz fadd.x FP_SCR0(%a6),%fp1 # execute add
11318 1.2.4.2 wiz
11319 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
11320 1.2.4.2 wiz
11321 1.2.4.2 wiz fabs.x %fp0 # compare absolute values
11322 1.2.4.2 wiz fabs.x %fp1
11323 1.2.4.2 wiz fcmp.x %fp0,%fp1 # is first result > second?
11324 1.2.4.2 wiz
11325 1.2.4.2 wiz fbgt.w fadd_unfl # yes; it's an underflow
11326 1.2.4.2 wiz bra.w fadd_normal # no; it's not an underflow
11327 1.2.4.2 wiz
11328 1.2.4.2 wiz ##########################################################################
11329 1.2.4.2 wiz
11330 1.2.4.2 wiz #
11331 1.2.4.2 wiz # Add: inputs are not both normalized; what are they?
11332 1.2.4.2 wiz #
11333 1.2.4.2 wiz fadd_not_norm:
11334 1.2.4.2 wiz mov.w (tbl_fadd_op.b,%pc,%d1.w*2),%d1
11335 1.2.4.2 wiz jmp (tbl_fadd_op.b,%pc,%d1.w*1)
11336 1.2.4.2 wiz
11337 1.2.4.2 wiz swbeg &48
11338 1.2.4.2 wiz tbl_fadd_op:
11339 1.2.4.2 wiz short fadd_norm - tbl_fadd_op # NORM + NORM
11340 1.2.4.2 wiz short fadd_zero_src - tbl_fadd_op # NORM + ZERO
11341 1.2.4.2 wiz short fadd_inf_src - tbl_fadd_op # NORM + INF
11342 1.2.4.2 wiz short fadd_res_qnan - tbl_fadd_op # NORM + QNAN
11343 1.2.4.2 wiz short fadd_norm - tbl_fadd_op # NORM + DENORM
11344 1.2.4.2 wiz short fadd_res_snan - tbl_fadd_op # NORM + SNAN
11345 1.2.4.2 wiz short tbl_fadd_op - tbl_fadd_op #
11346 1.2.4.2 wiz short tbl_fadd_op - tbl_fadd_op #
11347 1.2.4.2 wiz
11348 1.2.4.2 wiz short fadd_zero_dst - tbl_fadd_op # ZERO + NORM
11349 1.2.4.2 wiz short fadd_zero_2 - tbl_fadd_op # ZERO + ZERO
11350 1.2.4.2 wiz short fadd_inf_src - tbl_fadd_op # ZERO + INF
11351 1.2.4.2 wiz short fadd_res_qnan - tbl_fadd_op # NORM + QNAN
11352 1.2.4.2 wiz short fadd_zero_dst - tbl_fadd_op # ZERO + DENORM
11353 1.2.4.2 wiz short fadd_res_snan - tbl_fadd_op # NORM + SNAN
11354 1.2.4.2 wiz short tbl_fadd_op - tbl_fadd_op #
11355 1.2.4.2 wiz short tbl_fadd_op - tbl_fadd_op #
11356 1.2.4.2 wiz
11357 1.2.4.2 wiz short fadd_inf_dst - tbl_fadd_op # INF + NORM
11358 1.2.4.2 wiz short fadd_inf_dst - tbl_fadd_op # INF + ZERO
11359 1.2.4.2 wiz short fadd_inf_2 - tbl_fadd_op # INF + INF
11360 1.2.4.2 wiz short fadd_res_qnan - tbl_fadd_op # NORM + QNAN
11361 1.2.4.2 wiz short fadd_inf_dst - tbl_fadd_op # INF + DENORM
11362 1.2.4.2 wiz short fadd_res_snan - tbl_fadd_op # NORM + SNAN
11363 1.2.4.2 wiz short tbl_fadd_op - tbl_fadd_op #
11364 1.2.4.2 wiz short tbl_fadd_op - tbl_fadd_op #
11365 1.2.4.2 wiz
11366 1.2.4.2 wiz short fadd_res_qnan - tbl_fadd_op # QNAN + NORM
11367 1.2.4.2 wiz short fadd_res_qnan - tbl_fadd_op # QNAN + ZERO
11368 1.2.4.2 wiz short fadd_res_qnan - tbl_fadd_op # QNAN + INF
11369 1.2.4.2 wiz short fadd_res_qnan - tbl_fadd_op # QNAN + QNAN
11370 1.2.4.2 wiz short fadd_res_qnan - tbl_fadd_op # QNAN + DENORM
11371 1.2.4.2 wiz short fadd_res_snan - tbl_fadd_op # QNAN + SNAN
11372 1.2.4.2 wiz short tbl_fadd_op - tbl_fadd_op #
11373 1.2.4.2 wiz short tbl_fadd_op - tbl_fadd_op #
11374 1.2.4.2 wiz
11375 1.2.4.2 wiz short fadd_norm - tbl_fadd_op # DENORM + NORM
11376 1.2.4.2 wiz short fadd_zero_src - tbl_fadd_op # DENORM + ZERO
11377 1.2.4.2 wiz short fadd_inf_src - tbl_fadd_op # DENORM + INF
11378 1.2.4.2 wiz short fadd_res_qnan - tbl_fadd_op # NORM + QNAN
11379 1.2.4.2 wiz short fadd_norm - tbl_fadd_op # DENORM + DENORM
11380 1.2.4.2 wiz short fadd_res_snan - tbl_fadd_op # NORM + SNAN
11381 1.2.4.2 wiz short tbl_fadd_op - tbl_fadd_op #
11382 1.2.4.2 wiz short tbl_fadd_op - tbl_fadd_op #
11383 1.2.4.2 wiz
11384 1.2.4.2 wiz short fadd_res_snan - tbl_fadd_op # SNAN + NORM
11385 1.2.4.2 wiz short fadd_res_snan - tbl_fadd_op # SNAN + ZERO
11386 1.2.4.2 wiz short fadd_res_snan - tbl_fadd_op # SNAN + INF
11387 1.2.4.2 wiz short fadd_res_snan - tbl_fadd_op # SNAN + QNAN
11388 1.2.4.2 wiz short fadd_res_snan - tbl_fadd_op # SNAN + DENORM
11389 1.2.4.2 wiz short fadd_res_snan - tbl_fadd_op # SNAN + SNAN
11390 1.2.4.2 wiz short tbl_fadd_op - tbl_fadd_op #
11391 1.2.4.2 wiz short tbl_fadd_op - tbl_fadd_op #
11392 1.2.4.2 wiz
11393 1.2.4.2 wiz fadd_res_qnan:
11394 1.2.4.2 wiz bra.l res_qnan
11395 1.2.4.2 wiz fadd_res_snan:
11396 1.2.4.2 wiz bra.l res_snan
11397 1.2.4.2 wiz
11398 1.2.4.2 wiz #
11399 1.2.4.2 wiz # both operands are ZEROes
11400 1.2.4.2 wiz #
11401 1.2.4.2 wiz fadd_zero_2:
11402 1.2.4.2 wiz mov.b SRC_EX(%a0),%d0 # are the signs opposite
11403 1.2.4.2 wiz mov.b DST_EX(%a1),%d1
11404 1.2.4.2 wiz eor.b %d0,%d1
11405 1.2.4.2 wiz bmi.w fadd_zero_2_chk_rm # weed out (-ZERO)+(+ZERO)
11406 1.2.4.2 wiz
11407 1.2.4.2 wiz # the signs are the same. so determine whether they are positive or negative
11408 1.2.4.2 wiz # and return the appropriately signed zero.
11409 1.2.4.2 wiz tst.b %d0 # are ZEROes positive or negative?
11410 1.2.4.2 wiz bmi.b fadd_zero_rm # negative
11411 1.2.4.2 wiz fmov.s &0x00000000,%fp0 # return +ZERO
11412 1.2.4.2 wiz mov.b &z_bmask,FPSR_CC(%a6) # set Z
11413 1.2.4.2 wiz rts
11414 1.2.4.2 wiz
11415 1.2.4.2 wiz #
11416 1.2.4.2 wiz # the ZEROes have opposite signs:
11417 1.2.4.2 wiz # - therefore, we return +ZERO if the rounding modes are RN,RZ, or RP.
11418 1.2.4.2 wiz # - -ZERO is returned in the case of RM.
11419 1.2.4.2 wiz #
11420 1.2.4.2 wiz fadd_zero_2_chk_rm:
11421 1.2.4.2 wiz mov.b 3+L_SCR3(%a6),%d1
11422 1.2.4.2 wiz andi.b &0x30,%d1 # extract rnd mode
11423 1.2.4.2 wiz cmpi.b %d1,&rm_mode*0x10 # is rnd mode == RM?
11424 1.2.4.2 wiz beq.b fadd_zero_rm # yes
11425 1.2.4.2 wiz fmov.s &0x00000000,%fp0 # return +ZERO
11426 1.2.4.2 wiz mov.b &z_bmask,FPSR_CC(%a6) # set Z
11427 1.2.4.2 wiz rts
11428 1.2.4.2 wiz
11429 1.2.4.2 wiz fadd_zero_rm:
11430 1.2.4.2 wiz fmov.s &0x80000000,%fp0 # return -ZERO
11431 1.2.4.2 wiz mov.b &neg_bmask+z_bmask,FPSR_CC(%a6) # set NEG/Z
11432 1.2.4.2 wiz rts
11433 1.2.4.2 wiz
11434 1.2.4.2 wiz #
11435 1.2.4.2 wiz # one operand is a ZERO and the other is a DENORM or NORM. scale
11436 1.2.4.2 wiz # the DENORM or NORM and jump to the regular fadd routine.
11437 1.2.4.2 wiz #
11438 1.2.4.2 wiz fadd_zero_dst:
11439 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
11440 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
11441 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
11442 1.2.4.2 wiz bsr.l scale_to_zero_src # scale the operand
11443 1.2.4.2 wiz clr.w FP_SCR1_EX(%a6)
11444 1.2.4.2 wiz clr.l FP_SCR1_HI(%a6)
11445 1.2.4.2 wiz clr.l FP_SCR1_LO(%a6)
11446 1.2.4.2 wiz bra.w fadd_zero_entry # go execute fadd
11447 1.2.4.2 wiz
11448 1.2.4.2 wiz fadd_zero_src:
11449 1.2.4.2 wiz mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
11450 1.2.4.2 wiz mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
11451 1.2.4.2 wiz mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
11452 1.2.4.2 wiz bsr.l scale_to_zero_dst # scale the operand
11453 1.2.4.2 wiz clr.w FP_SCR0_EX(%a6)
11454 1.2.4.2 wiz clr.l FP_SCR0_HI(%a6)
11455 1.2.4.2 wiz clr.l FP_SCR0_LO(%a6)
11456 1.2.4.2 wiz bra.w fadd_zero_entry # go execute fadd
11457 1.2.4.2 wiz
11458 1.2.4.2 wiz #
11459 1.2.4.2 wiz # both operands are INFs. an OPERR will result if the INFs have
11460 1.2.4.2 wiz # different signs. else, an INF of the same sign is returned
11461 1.2.4.2 wiz #
11462 1.2.4.2 wiz fadd_inf_2:
11463 1.2.4.2 wiz mov.b SRC_EX(%a0),%d0 # exclusive or the signs
11464 1.2.4.2 wiz mov.b DST_EX(%a1),%d1
11465 1.2.4.2 wiz eor.b %d1,%d0
11466 1.2.4.2 wiz bmi.l res_operr # weed out (-INF)+(+INF)
11467 1.2.4.2 wiz
11468 1.2.4.2 wiz # ok, so it's not an OPERR. but, we do have to remember to return the
11469 1.2.4.2 wiz # src INF since that's where the 881/882 gets the j-bit from...
11470 1.2.4.2 wiz
11471 1.2.4.2 wiz #
11472 1.2.4.2 wiz # operands are INF and one of {ZERO, INF, DENORM, NORM}
11473 1.2.4.2 wiz #
11474 1.2.4.2 wiz fadd_inf_src:
11475 1.2.4.2 wiz fmovm.x SRC(%a0),&0x80 # return src INF
11476 1.2.4.2 wiz tst.b SRC_EX(%a0) # is INF positive?
11477 1.2.4.2 wiz bpl.b fadd_inf_done # yes; we're done
11478 1.2.4.2 wiz mov.b &neg_bmask+inf_bmask,FPSR_CC(%a6) # set INF/NEG
11479 1.2.4.2 wiz rts
11480 1.2.4.2 wiz
11481 1.2.4.2 wiz #
11482 1.2.4.2 wiz # operands are INF and one of {ZERO, INF, DENORM, NORM}
11483 1.2.4.2 wiz #
11484 1.2.4.2 wiz fadd_inf_dst:
11485 1.2.4.2 wiz fmovm.x DST(%a1),&0x80 # return dst INF
11486 1.2.4.2 wiz tst.b DST_EX(%a1) # is INF positive?
11487 1.2.4.2 wiz bpl.b fadd_inf_done # yes; we're done
11488 1.2.4.2 wiz mov.b &neg_bmask+inf_bmask,FPSR_CC(%a6) # set INF/NEG
11489 1.2.4.2 wiz rts
11490 1.2.4.2 wiz
11491 1.2.4.2 wiz fadd_inf_done:
11492 1.2.4.2 wiz mov.b &inf_bmask,FPSR_CC(%a6) # set INF
11493 1.2.4.2 wiz rts
11494 1.2.4.2 wiz
11495 1.2.4.2 wiz #########################################################################
11496 1.2.4.2 wiz # XDEF **************************************************************** #
11497 1.2.4.2 wiz # fsub(): emulates the fsub instruction #
11498 1.2.4.2 wiz # fssub(): emulates the fssub instruction #
11499 1.2.4.2 wiz # fdsub(): emulates the fdsub instruction #
11500 1.2.4.2 wiz # #
11501 1.2.4.2 wiz # XREF **************************************************************** #
11502 1.2.4.2 wiz # addsub_scaler2() - scale the operands so they won't take exc #
11503 1.2.4.2 wiz # ovf_res() - return default overflow result #
11504 1.2.4.2 wiz # unf_res() - return default underflow result #
11505 1.2.4.2 wiz # res_qnan() - set QNAN result #
11506 1.2.4.2 wiz # res_snan() - set SNAN result #
11507 1.2.4.2 wiz # res_operr() - set OPERR result #
11508 1.2.4.2 wiz # scale_to_zero_src() - set src operand exponent equal to zero #
11509 1.2.4.2 wiz # scale_to_zero_dst() - set dst operand exponent equal to zero #
11510 1.2.4.2 wiz # #
11511 1.2.4.2 wiz # INPUT *************************************************************** #
11512 1.2.4.2 wiz # a0 = pointer to extended precision source operand #
11513 1.2.4.2 wiz # a1 = pointer to extended precision destination operand #
11514 1.2.4.2 wiz # #
11515 1.2.4.2 wiz # OUTPUT ************************************************************** #
11516 1.2.4.2 wiz # fp0 = result #
11517 1.2.4.2 wiz # fp1 = EXOP (if exception occurred) #
11518 1.2.4.2 wiz # #
11519 1.2.4.2 wiz # ALGORITHM *********************************************************** #
11520 1.2.4.2 wiz # Handle NANs, infinities, and zeroes as special cases. Divide #
11521 1.2.4.2 wiz # norms into extended, single, and double precision. #
11522 1.2.4.2 wiz # Do subtraction after scaling exponents such that exception won't#
11523 1.2.4.2 wiz # occur. Then, check result exponent to see if exception would have #
11524 1.2.4.2 wiz # occurred. If so, return default result and maybe EXOP. Else, insert #
11525 1.2.4.2 wiz # the correct result exponent and return. Set FPSR bits as appropriate. #
11526 1.2.4.2 wiz # #
11527 1.2.4.2 wiz #########################################################################
11528 1.2.4.2 wiz
11529 1.2.4.2 wiz global fssub
11530 1.2.4.2 wiz fssub:
11531 1.2.4.2 wiz andi.b &0x30,%d0 # clear rnd prec
11532 1.2.4.2 wiz ori.b &s_mode*0x10,%d0 # insert sgl prec
11533 1.2.4.2 wiz bra.b fsub
11534 1.2.4.2 wiz
11535 1.2.4.2 wiz global fdsub
11536 1.2.4.2 wiz fdsub:
11537 1.2.4.2 wiz andi.b &0x30,%d0 # clear rnd prec
11538 1.2.4.2 wiz ori.b &d_mode*0x10,%d0 # insert dbl prec
11539 1.2.4.2 wiz
11540 1.2.4.2 wiz global fsub
11541 1.2.4.2 wiz fsub:
11542 1.2.4.2 wiz mov.l %d0,L_SCR3(%a6) # store rnd info
11543 1.2.4.2 wiz
11544 1.2.4.2 wiz clr.w %d1
11545 1.2.4.2 wiz mov.b DTAG(%a6),%d1
11546 1.2.4.2 wiz lsl.b &0x3,%d1
11547 1.2.4.2 wiz or.b STAG(%a6),%d1 # combine src tags
11548 1.2.4.2 wiz
11549 1.2.4.2 wiz bne.w fsub_not_norm # optimize on non-norm input
11550 1.2.4.2 wiz
11551 1.2.4.2 wiz #
11552 1.2.4.2 wiz # SUB: norms and denorms
11553 1.2.4.2 wiz #
11554 1.2.4.2 wiz fsub_norm:
11555 1.2.4.2 wiz bsr.l addsub_scaler2 # scale exponents
11556 1.2.4.2 wiz
11557 1.2.4.2 wiz fsub_zero_entry:
11558 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst op
11559 1.2.4.2 wiz
11560 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
11561 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
11562 1.2.4.2 wiz
11563 1.2.4.2 wiz fsub.x FP_SCR0(%a6),%fp0 # execute subtract
11564 1.2.4.2 wiz
11565 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
11566 1.2.4.2 wiz fmov.l %fpsr,%d1 # fetch INEX2, N, Z
11567 1.2.4.2 wiz
11568 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save exc and ccode bits
11569 1.2.4.2 wiz
11570 1.2.4.2 wiz fbeq.w fsub_zero_exit # if result zero, end now
11571 1.2.4.2 wiz
11572 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
11573 1.2.4.2 wiz
11574 1.2.4.2 wiz fmovm.x &0x01,-(%sp) # save result to stack
11575 1.2.4.2 wiz
11576 1.2.4.2 wiz mov.w 2+L_SCR3(%a6),%d1
11577 1.2.4.2 wiz lsr.b &0x6,%d1
11578 1.2.4.2 wiz
11579 1.2.4.2 wiz mov.w (%sp),%d2 # fetch new exponent
11580 1.2.4.2 wiz andi.l &0x7fff,%d2 # strip sign
11581 1.2.4.2 wiz sub.l %d0,%d2 # add scale factor
11582 1.2.4.2 wiz
11583 1.2.4.2 wiz cmp.l %d2,(tbl_fsub_ovfl.b,%pc,%d1.w*4) # is it an overflow?
11584 1.2.4.2 wiz bge.b fsub_ovfl # yes
11585 1.2.4.2 wiz
11586 1.2.4.2 wiz cmp.l %d2,(tbl_fsub_unfl.b,%pc,%d1.w*4) # is it an underflow?
11587 1.2.4.2 wiz blt.w fsub_unfl # yes
11588 1.2.4.2 wiz beq.w fsub_may_unfl # maybe; go find out
11589 1.2.4.2 wiz
11590 1.2.4.2 wiz fsub_normal:
11591 1.2.4.2 wiz mov.w (%sp),%d1
11592 1.2.4.2 wiz andi.w &0x8000,%d1 # keep sign
11593 1.2.4.2 wiz or.w %d2,%d1 # insert new exponent
11594 1.2.4.2 wiz mov.w %d1,(%sp) # insert new exponent
11595 1.2.4.2 wiz
11596 1.2.4.2 wiz fmovm.x (%sp)+,&0x80 # return result in fp0
11597 1.2.4.2 wiz
11598 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
11599 1.2.4.2 wiz rts
11600 1.2.4.2 wiz
11601 1.2.4.2 wiz fsub_zero_exit:
11602 1.2.4.2 wiz # fmov.s &0x00000000,%fp0 # return zero in fp0
11603 1.2.4.2 wiz rts
11604 1.2.4.2 wiz
11605 1.2.4.2 wiz tbl_fsub_ovfl:
11606 1.2.4.2 wiz long 0x7fff # ext ovfl
11607 1.2.4.2 wiz long 0x407f # sgl ovfl
11608 1.2.4.2 wiz long 0x43ff # dbl ovfl
11609 1.2.4.2 wiz
11610 1.2.4.2 wiz tbl_fsub_unfl:
11611 1.2.4.2 wiz long 0x0000 # ext unfl
11612 1.2.4.2 wiz long 0x3f81 # sgl unfl
11613 1.2.4.2 wiz long 0x3c01 # dbl unfl
11614 1.2.4.2 wiz
11615 1.2.4.2 wiz fsub_ovfl:
11616 1.2.4.2 wiz or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
11617 1.2.4.2 wiz
11618 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d1
11619 1.2.4.2 wiz andi.b &0x13,%d1 # is OVFL or INEX enabled?
11620 1.2.4.2 wiz bne.b fsub_ovfl_ena # yes
11621 1.2.4.2 wiz
11622 1.2.4.2 wiz add.l &0xc,%sp
11623 1.2.4.2 wiz fsub_ovfl_dis:
11624 1.2.4.2 wiz btst &neg_bit,FPSR_CC(%a6) # is result negative?
11625 1.2.4.2 wiz sne %d1 # set sign param accordingly
11626 1.2.4.2 wiz mov.l L_SCR3(%a6),%d0 # pass prec:rnd
11627 1.2.4.2 wiz bsr.l ovf_res # calculate default result
11628 1.2.4.2 wiz or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
11629 1.2.4.2 wiz fmovm.x (%a0),&0x80 # return default result in fp0
11630 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
11631 1.2.4.2 wiz rts
11632 1.2.4.2 wiz
11633 1.2.4.2 wiz fsub_ovfl_ena:
11634 1.2.4.2 wiz mov.b L_SCR3(%a6),%d1
11635 1.2.4.2 wiz andi.b &0xc0,%d1 # is precision extended?
11636 1.2.4.2 wiz bne.b fsub_ovfl_ena_sd # no
11637 1.2.4.2 wiz
11638 1.2.4.2 wiz fsub_ovfl_ena_cont:
11639 1.2.4.2 wiz mov.w (%sp),%d1 # fetch {sgn,exp}
11640 1.2.4.2 wiz andi.w &0x8000,%d1 # keep sign
11641 1.2.4.2 wiz subi.l &0x6000,%d2 # subtract new bias
11642 1.2.4.2 wiz andi.w &0x7fff,%d2 # clear top bit
11643 1.2.4.2 wiz or.w %d2,%d1 # concat sign,exp
11644 1.2.4.2 wiz mov.w %d1,(%sp) # insert new exponent
11645 1.2.4.2 wiz
11646 1.2.4.2 wiz fmovm.x (%sp)+,&0x40 # return EXOP in fp1
11647 1.2.4.2 wiz bra.b fsub_ovfl_dis
11648 1.2.4.2 wiz
11649 1.2.4.2 wiz fsub_ovfl_ena_sd:
11650 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst op
11651 1.2.4.2 wiz
11652 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1
11653 1.2.4.2 wiz andi.b &0x30,%d1 # clear rnd prec
11654 1.2.4.2 wiz fmov.l %d1,%fpcr # set FPCR
11655 1.2.4.2 wiz
11656 1.2.4.2 wiz fsub.x FP_SCR0(%a6),%fp0 # execute subtract
11657 1.2.4.2 wiz
11658 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
11659 1.2.4.2 wiz
11660 1.2.4.2 wiz add.l &0xc,%sp
11661 1.2.4.2 wiz fmovm.x &0x01,-(%sp)
11662 1.2.4.2 wiz bra.b fsub_ovfl_ena_cont
11663 1.2.4.2 wiz
11664 1.2.4.2 wiz fsub_unfl:
11665 1.2.4.2 wiz bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
11666 1.2.4.2 wiz
11667 1.2.4.2 wiz add.l &0xc,%sp
11668 1.2.4.2 wiz
11669 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x80 # load dst op
11670 1.2.4.2 wiz
11671 1.2.4.2 wiz fmov.l &rz_mode*0x10,%fpcr # set FPCR
11672 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
11673 1.2.4.2 wiz
11674 1.2.4.2 wiz fsub.x FP_SCR0(%a6),%fp0 # execute subtract
11675 1.2.4.2 wiz
11676 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
11677 1.2.4.2 wiz fmov.l %fpsr,%d1 # save status
11678 1.2.4.2 wiz
11679 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6)
11680 1.2.4.2 wiz
11681 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d1
11682 1.2.4.2 wiz andi.b &0x0b,%d1 # is UNFL or INEX enabled?
11683 1.2.4.2 wiz bne.b fsub_unfl_ena # yes
11684 1.2.4.2 wiz
11685 1.2.4.2 wiz fsub_unfl_dis:
11686 1.2.4.2 wiz fmovm.x &0x80,FP_SCR0(%a6) # store out result
11687 1.2.4.2 wiz
11688 1.2.4.2 wiz lea FP_SCR0(%a6),%a0 # pass: result addr
11689 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
11690 1.2.4.2 wiz bsr.l unf_res # calculate default result
11691 1.2.4.2 wiz or.b %d0,FPSR_CC(%a6) # 'Z' may have been set
11692 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
11693 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
11694 1.2.4.2 wiz rts
11695 1.2.4.2 wiz
11696 1.2.4.2 wiz fsub_unfl_ena:
11697 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x40
11698 1.2.4.2 wiz
11699 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1
11700 1.2.4.2 wiz andi.b &0xc0,%d1 # is precision extended?
11701 1.2.4.2 wiz bne.b fsub_unfl_ena_sd # no
11702 1.2.4.2 wiz
11703 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
11704 1.2.4.2 wiz
11705 1.2.4.2 wiz fsub_unfl_ena_cont:
11706 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
11707 1.2.4.2 wiz
11708 1.2.4.2 wiz fsub.x FP_SCR0(%a6),%fp1 # execute subtract
11709 1.2.4.2 wiz
11710 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
11711 1.2.4.2 wiz
11712 1.2.4.2 wiz fmovm.x &0x40,FP_SCR0(%a6) # store result to stack
11713 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
11714 1.2.4.2 wiz mov.l %d1,%d2 # make a copy
11715 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
11716 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
11717 1.2.4.2 wiz sub.l %d0,%d1 # add scale factor
11718 1.2.4.2 wiz addi.l &0x6000,%d1 # subtract new bias
11719 1.2.4.2 wiz andi.w &0x7fff,%d1 # clear top bit
11720 1.2.4.2 wiz or.w %d2,%d1 # concat sgn,exp
11721 1.2.4.2 wiz mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
11722 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
11723 1.2.4.2 wiz bra.w fsub_unfl_dis
11724 1.2.4.2 wiz
11725 1.2.4.2 wiz fsub_unfl_ena_sd:
11726 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1
11727 1.2.4.2 wiz andi.b &0x30,%d1 # clear rnd prec
11728 1.2.4.2 wiz fmov.l %d1,%fpcr # set FPCR
11729 1.2.4.2 wiz
11730 1.2.4.2 wiz bra.b fsub_unfl_ena_cont
11731 1.2.4.2 wiz
11732 1.2.4.2 wiz #
11733 1.2.4.2 wiz # result is equal to the smallest normalized number in the selected precision
11734 1.2.4.2 wiz # if the precision is extended, this result could not have come from an
11735 1.2.4.2 wiz # underflow that rounded up.
11736 1.2.4.2 wiz #
11737 1.2.4.2 wiz fsub_may_unfl:
11738 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1
11739 1.2.4.2 wiz andi.b &0xc0,%d1 # fetch rnd prec
11740 1.2.4.2 wiz beq.w fsub_normal # yes; no underflow occurred
11741 1.2.4.2 wiz
11742 1.2.4.2 wiz mov.l 0x4(%sp),%d1
11743 1.2.4.2 wiz cmpi.l %d1,&0x80000000 # is hi(man) = 0x80000000?
11744 1.2.4.2 wiz bne.w fsub_normal # no; no underflow occurred
11745 1.2.4.2 wiz
11746 1.2.4.2 wiz tst.l 0x8(%sp) # is lo(man) = 0x0?
11747 1.2.4.2 wiz bne.w fsub_normal # no; no underflow occurred
11748 1.2.4.2 wiz
11749 1.2.4.2 wiz btst &inex2_bit,FPSR_EXCEPT(%a6) # is INEX2 set?
11750 1.2.4.2 wiz beq.w fsub_normal # no; no underflow occurred
11751 1.2.4.2 wiz
11752 1.2.4.2 wiz #
11753 1.2.4.2 wiz # ok, so now the result has a exponent equal to the smallest normalized
11754 1.2.4.2 wiz # exponent for the selected precision. also, the mantissa is equal to
11755 1.2.4.2 wiz # 0x8000000000000000 and this mantissa is the result of rounding non-zero
11756 1.2.4.2 wiz # g,r,s.
11757 1.2.4.2 wiz # now, we must determine whether the pre-rounded result was an underflow
11758 1.2.4.2 wiz # rounded "up" or a normalized number rounded "down".
11759 1.2.4.2 wiz # so, we do this be re-executing the add using RZ as the rounding mode and
11760 1.2.4.2 wiz # seeing if the new result is smaller or equal to the current result.
11761 1.2.4.2 wiz #
11762 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x40 # load dst op into fp1
11763 1.2.4.2 wiz
11764 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1
11765 1.2.4.2 wiz andi.b &0xc0,%d1 # keep rnd prec
11766 1.2.4.2 wiz ori.b &rz_mode*0x10,%d1 # insert rnd mode
11767 1.2.4.2 wiz fmov.l %d1,%fpcr # set FPCR
11768 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
11769 1.2.4.2 wiz
11770 1.2.4.2 wiz fsub.x FP_SCR0(%a6),%fp1 # execute subtract
11771 1.2.4.2 wiz
11772 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
11773 1.2.4.2 wiz
11774 1.2.4.2 wiz fabs.x %fp0 # compare absolute values
11775 1.2.4.2 wiz fabs.x %fp1
11776 1.2.4.2 wiz fcmp.x %fp0,%fp1 # is first result > second?
11777 1.2.4.2 wiz
11778 1.2.4.2 wiz fbgt.w fsub_unfl # yes; it's an underflow
11779 1.2.4.2 wiz bra.w fsub_normal # no; it's not an underflow
11780 1.2.4.2 wiz
11781 1.2.4.2 wiz ##########################################################################
11782 1.2.4.2 wiz
11783 1.2.4.2 wiz #
11784 1.2.4.2 wiz # Sub: inputs are not both normalized; what are they?
11785 1.2.4.2 wiz #
11786 1.2.4.2 wiz fsub_not_norm:
11787 1.2.4.2 wiz mov.w (tbl_fsub_op.b,%pc,%d1.w*2),%d1
11788 1.2.4.2 wiz jmp (tbl_fsub_op.b,%pc,%d1.w*1)
11789 1.2.4.2 wiz
11790 1.2.4.2 wiz swbeg &48
11791 1.2.4.2 wiz tbl_fsub_op:
11792 1.2.4.2 wiz short fsub_norm - tbl_fsub_op # NORM - NORM
11793 1.2.4.2 wiz short fsub_zero_src - tbl_fsub_op # NORM - ZERO
11794 1.2.4.2 wiz short fsub_inf_src - tbl_fsub_op # NORM - INF
11795 1.2.4.2 wiz short fsub_res_qnan - tbl_fsub_op # NORM - QNAN
11796 1.2.4.2 wiz short fsub_norm - tbl_fsub_op # NORM - DENORM
11797 1.2.4.2 wiz short fsub_res_snan - tbl_fsub_op # NORM - SNAN
11798 1.2.4.2 wiz short tbl_fsub_op - tbl_fsub_op #
11799 1.2.4.2 wiz short tbl_fsub_op - tbl_fsub_op #
11800 1.2.4.2 wiz
11801 1.2.4.2 wiz short fsub_zero_dst - tbl_fsub_op # ZERO - NORM
11802 1.2.4.2 wiz short fsub_zero_2 - tbl_fsub_op # ZERO - ZERO
11803 1.2.4.2 wiz short fsub_inf_src - tbl_fsub_op # ZERO - INF
11804 1.2.4.2 wiz short fsub_res_qnan - tbl_fsub_op # NORM - QNAN
11805 1.2.4.2 wiz short fsub_zero_dst - tbl_fsub_op # ZERO - DENORM
11806 1.2.4.2 wiz short fsub_res_snan - tbl_fsub_op # NORM - SNAN
11807 1.2.4.2 wiz short tbl_fsub_op - tbl_fsub_op #
11808 1.2.4.2 wiz short tbl_fsub_op - tbl_fsub_op #
11809 1.2.4.2 wiz
11810 1.2.4.2 wiz short fsub_inf_dst - tbl_fsub_op # INF - NORM
11811 1.2.4.2 wiz short fsub_inf_dst - tbl_fsub_op # INF - ZERO
11812 1.2.4.2 wiz short fsub_inf_2 - tbl_fsub_op # INF - INF
11813 1.2.4.2 wiz short fsub_res_qnan - tbl_fsub_op # NORM - QNAN
11814 1.2.4.2 wiz short fsub_inf_dst - tbl_fsub_op # INF - DENORM
11815 1.2.4.2 wiz short fsub_res_snan - tbl_fsub_op # NORM - SNAN
11816 1.2.4.2 wiz short tbl_fsub_op - tbl_fsub_op #
11817 1.2.4.2 wiz short tbl_fsub_op - tbl_fsub_op #
11818 1.2.4.2 wiz
11819 1.2.4.2 wiz short fsub_res_qnan - tbl_fsub_op # QNAN - NORM
11820 1.2.4.2 wiz short fsub_res_qnan - tbl_fsub_op # QNAN - ZERO
11821 1.2.4.2 wiz short fsub_res_qnan - tbl_fsub_op # QNAN - INF
11822 1.2.4.2 wiz short fsub_res_qnan - tbl_fsub_op # QNAN - QNAN
11823 1.2.4.2 wiz short fsub_res_qnan - tbl_fsub_op # QNAN - DENORM
11824 1.2.4.2 wiz short fsub_res_snan - tbl_fsub_op # QNAN - SNAN
11825 1.2.4.2 wiz short tbl_fsub_op - tbl_fsub_op #
11826 1.2.4.2 wiz short tbl_fsub_op - tbl_fsub_op #
11827 1.2.4.2 wiz
11828 1.2.4.2 wiz short fsub_norm - tbl_fsub_op # DENORM - NORM
11829 1.2.4.2 wiz short fsub_zero_src - tbl_fsub_op # DENORM - ZERO
11830 1.2.4.2 wiz short fsub_inf_src - tbl_fsub_op # DENORM - INF
11831 1.2.4.2 wiz short fsub_res_qnan - tbl_fsub_op # NORM - QNAN
11832 1.2.4.2 wiz short fsub_norm - tbl_fsub_op # DENORM - DENORM
11833 1.2.4.2 wiz short fsub_res_snan - tbl_fsub_op # NORM - SNAN
11834 1.2.4.2 wiz short tbl_fsub_op - tbl_fsub_op #
11835 1.2.4.2 wiz short tbl_fsub_op - tbl_fsub_op #
11836 1.2.4.2 wiz
11837 1.2.4.2 wiz short fsub_res_snan - tbl_fsub_op # SNAN - NORM
11838 1.2.4.2 wiz short fsub_res_snan - tbl_fsub_op # SNAN - ZERO
11839 1.2.4.2 wiz short fsub_res_snan - tbl_fsub_op # SNAN - INF
11840 1.2.4.2 wiz short fsub_res_snan - tbl_fsub_op # SNAN - QNAN
11841 1.2.4.2 wiz short fsub_res_snan - tbl_fsub_op # SNAN - DENORM
11842 1.2.4.2 wiz short fsub_res_snan - tbl_fsub_op # SNAN - SNAN
11843 1.2.4.2 wiz short tbl_fsub_op - tbl_fsub_op #
11844 1.2.4.2 wiz short tbl_fsub_op - tbl_fsub_op #
11845 1.2.4.2 wiz
11846 1.2.4.2 wiz fsub_res_qnan:
11847 1.2.4.2 wiz bra.l res_qnan
11848 1.2.4.2 wiz fsub_res_snan:
11849 1.2.4.2 wiz bra.l res_snan
11850 1.2.4.2 wiz
11851 1.2.4.2 wiz #
11852 1.2.4.2 wiz # both operands are ZEROes
11853 1.2.4.2 wiz #
11854 1.2.4.2 wiz fsub_zero_2:
11855 1.2.4.2 wiz mov.b SRC_EX(%a0),%d0
11856 1.2.4.2 wiz mov.b DST_EX(%a1),%d1
11857 1.2.4.2 wiz eor.b %d1,%d0
11858 1.2.4.2 wiz bpl.b fsub_zero_2_chk_rm
11859 1.2.4.2 wiz
11860 1.2.4.2 wiz # the signs are opposite, so, return a ZERO w/ the sign of the dst ZERO
11861 1.2.4.2 wiz tst.b %d0 # is dst negative?
11862 1.2.4.2 wiz bmi.b fsub_zero_2_rm # yes
11863 1.2.4.2 wiz fmov.s &0x00000000,%fp0 # no; return +ZERO
11864 1.2.4.2 wiz mov.b &z_bmask,FPSR_CC(%a6) # set Z
11865 1.2.4.2 wiz rts
11866 1.2.4.2 wiz
11867 1.2.4.2 wiz #
11868 1.2.4.2 wiz # the ZEROes have the same signs:
11869 1.2.4.2 wiz # - therefore, we return +ZERO if the rounding mode is RN,RZ, or RP
11870 1.2.4.2 wiz # - -ZERO is returned in the case of RM.
11871 1.2.4.2 wiz #
11872 1.2.4.2 wiz fsub_zero_2_chk_rm:
11873 1.2.4.2 wiz mov.b 3+L_SCR3(%a6),%d1
11874 1.2.4.2 wiz andi.b &0x30,%d1 # extract rnd mode
11875 1.2.4.2 wiz cmpi.b %d1,&rm_mode*0x10 # is rnd mode = RM?
11876 1.2.4.2 wiz beq.b fsub_zero_2_rm # yes
11877 1.2.4.2 wiz fmov.s &0x00000000,%fp0 # no; return +ZERO
11878 1.2.4.2 wiz mov.b &z_bmask,FPSR_CC(%a6) # set Z
11879 1.2.4.2 wiz rts
11880 1.2.4.2 wiz
11881 1.2.4.2 wiz fsub_zero_2_rm:
11882 1.2.4.2 wiz fmov.s &0x80000000,%fp0 # return -ZERO
11883 1.2.4.2 wiz mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set Z/NEG
11884 1.2.4.2 wiz rts
11885 1.2.4.2 wiz
11886 1.2.4.2 wiz #
11887 1.2.4.2 wiz # one operand is a ZERO and the other is a DENORM or a NORM.
11888 1.2.4.2 wiz # scale the DENORM or NORM and jump to the regular fsub routine.
11889 1.2.4.2 wiz #
11890 1.2.4.2 wiz fsub_zero_dst:
11891 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
11892 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
11893 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
11894 1.2.4.2 wiz bsr.l scale_to_zero_src # scale the operand
11895 1.2.4.2 wiz clr.w FP_SCR1_EX(%a6)
11896 1.2.4.2 wiz clr.l FP_SCR1_HI(%a6)
11897 1.2.4.2 wiz clr.l FP_SCR1_LO(%a6)
11898 1.2.4.2 wiz bra.w fsub_zero_entry # go execute fsub
11899 1.2.4.2 wiz
11900 1.2.4.2 wiz fsub_zero_src:
11901 1.2.4.2 wiz mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
11902 1.2.4.2 wiz mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
11903 1.2.4.2 wiz mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
11904 1.2.4.2 wiz bsr.l scale_to_zero_dst # scale the operand
11905 1.2.4.2 wiz clr.w FP_SCR0_EX(%a6)
11906 1.2.4.2 wiz clr.l FP_SCR0_HI(%a6)
11907 1.2.4.2 wiz clr.l FP_SCR0_LO(%a6)
11908 1.2.4.2 wiz bra.w fsub_zero_entry # go execute fsub
11909 1.2.4.2 wiz
11910 1.2.4.2 wiz #
11911 1.2.4.2 wiz # both operands are INFs. an OPERR will result if the INFs have the
11912 1.2.4.2 wiz # same signs. else,
11913 1.2.4.2 wiz #
11914 1.2.4.2 wiz fsub_inf_2:
11915 1.2.4.2 wiz mov.b SRC_EX(%a0),%d0 # exclusive or the signs
11916 1.2.4.2 wiz mov.b DST_EX(%a1),%d1
11917 1.2.4.2 wiz eor.b %d1,%d0
11918 1.2.4.2 wiz bpl.l res_operr # weed out (-INF)+(+INF)
11919 1.2.4.2 wiz
11920 1.2.4.2 wiz # ok, so it's not an OPERR. but we do have to remember to return
11921 1.2.4.2 wiz # the src INF since that's where the 881/882 gets the j-bit.
11922 1.2.4.2 wiz
11923 1.2.4.2 wiz fsub_inf_src:
11924 1.2.4.2 wiz fmovm.x SRC(%a0),&0x80 # return src INF
11925 1.2.4.2 wiz fneg.x %fp0 # invert sign
11926 1.2.4.2 wiz fbge.w fsub_inf_done # sign is now positive
11927 1.2.4.2 wiz mov.b &neg_bmask+inf_bmask,FPSR_CC(%a6) # set INF/NEG
11928 1.2.4.2 wiz rts
11929 1.2.4.2 wiz
11930 1.2.4.2 wiz fsub_inf_dst:
11931 1.2.4.2 wiz fmovm.x DST(%a1),&0x80 # return dst INF
11932 1.2.4.2 wiz tst.b DST_EX(%a1) # is INF negative?
11933 1.2.4.2 wiz bpl.b fsub_inf_done # no
11934 1.2.4.2 wiz mov.b &neg_bmask+inf_bmask,FPSR_CC(%a6) # set INF/NEG
11935 1.2.4.2 wiz rts
11936 1.2.4.2 wiz
11937 1.2.4.2 wiz fsub_inf_done:
11938 1.2.4.2 wiz mov.b &inf_bmask,FPSR_CC(%a6) # set INF
11939 1.2.4.2 wiz rts
11940 1.2.4.2 wiz
11941 1.2.4.2 wiz #########################################################################
11942 1.2.4.2 wiz # XDEF **************************************************************** #
11943 1.2.4.2 wiz # fsqrt(): emulates the fsqrt instruction #
11944 1.2.4.2 wiz # fssqrt(): emulates the fssqrt instruction #
11945 1.2.4.2 wiz # fdsqrt(): emulates the fdsqrt instruction #
11946 1.2.4.2 wiz # #
11947 1.2.4.2 wiz # XREF **************************************************************** #
11948 1.2.4.2 wiz # scale_sqrt() - scale the source operand #
11949 1.2.4.2 wiz # unf_res() - return default underflow result #
11950 1.2.4.2 wiz # ovf_res() - return default overflow result #
11951 1.2.4.2 wiz # res_qnan_1op() - return QNAN result #
11952 1.2.4.2 wiz # res_snan_1op() - return SNAN result #
11953 1.2.4.2 wiz # #
11954 1.2.4.2 wiz # INPUT *************************************************************** #
11955 1.2.4.2 wiz # a0 = pointer to extended precision source operand #
11956 1.2.4.2 wiz # d0 rnd prec,mode #
11957 1.2.4.2 wiz # #
11958 1.2.4.2 wiz # OUTPUT ************************************************************** #
11959 1.2.4.2 wiz # fp0 = result #
11960 1.2.4.2 wiz # fp1 = EXOP (if exception occurred) #
11961 1.2.4.2 wiz # #
11962 1.2.4.2 wiz # ALGORITHM *********************************************************** #
11963 1.2.4.2 wiz # Handle NANs, infinities, and zeroes as special cases. Divide #
11964 1.2.4.2 wiz # norms/denorms into ext/sgl/dbl precision. #
11965 1.2.4.2 wiz # For norms/denorms, scale the exponents such that a sqrt #
11966 1.2.4.2 wiz # instruction won't cause an exception. Use the regular fsqrt to #
11967 1.2.4.2 wiz # compute a result. Check if the regular operands would have taken #
11968 1.2.4.2 wiz # an exception. If so, return the default overflow/underflow result #
11969 1.2.4.2 wiz # and return the EXOP if exceptions are enabled. Else, scale the #
11970 1.2.4.2 wiz # result operand to the proper exponent. #
11971 1.2.4.2 wiz # #
11972 1.2.4.2 wiz #########################################################################
11973 1.2.4.2 wiz
11974 1.2.4.2 wiz global fssqrt
11975 1.2.4.2 wiz fssqrt:
11976 1.2.4.2 wiz andi.b &0x30,%d0 # clear rnd prec
11977 1.2.4.2 wiz ori.b &s_mode*0x10,%d0 # insert sgl precision
11978 1.2.4.2 wiz bra.b fsqrt
11979 1.2.4.2 wiz
11980 1.2.4.2 wiz global fdsqrt
11981 1.2.4.2 wiz fdsqrt:
11982 1.2.4.2 wiz andi.b &0x30,%d0 # clear rnd prec
11983 1.2.4.2 wiz ori.b &d_mode*0x10,%d0 # insert dbl precision
11984 1.2.4.2 wiz
11985 1.2.4.2 wiz global fsqrt
11986 1.2.4.2 wiz fsqrt:
11987 1.2.4.2 wiz mov.l %d0,L_SCR3(%a6) # store rnd info
11988 1.2.4.2 wiz clr.w %d1
11989 1.2.4.2 wiz mov.b STAG(%a6),%d1
11990 1.2.4.2 wiz bne.w fsqrt_not_norm # optimize on non-norm input
11991 1.2.4.2 wiz
11992 1.2.4.2 wiz #
11993 1.2.4.2 wiz # SQUARE ROOT: norms and denorms ONLY!
11994 1.2.4.2 wiz #
11995 1.2.4.2 wiz fsqrt_norm:
11996 1.2.4.2 wiz tst.b SRC_EX(%a0) # is operand negative?
11997 1.2.4.2 wiz bmi.l res_operr # yes
11998 1.2.4.2 wiz
11999 1.2.4.2 wiz andi.b &0xc0,%d0 # is precision extended?
12000 1.2.4.2 wiz bne.b fsqrt_not_ext # no; go handle sgl or dbl
12001 1.2.4.2 wiz
12002 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
12003 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
12004 1.2.4.2 wiz
12005 1.2.4.2 wiz fsqrt.x (%a0),%fp0 # execute square root
12006 1.2.4.2 wiz
12007 1.2.4.2 wiz fmov.l %fpsr,%d1
12008 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # set N,INEX
12009 1.2.4.2 wiz
12010 1.2.4.2 wiz rts
12011 1.2.4.2 wiz
12012 1.2.4.2 wiz fsqrt_denorm:
12013 1.2.4.2 wiz tst.b SRC_EX(%a0) # is operand negative?
12014 1.2.4.2 wiz bmi.l res_operr # yes
12015 1.2.4.2 wiz
12016 1.2.4.2 wiz andi.b &0xc0,%d0 # is precision extended?
12017 1.2.4.2 wiz bne.b fsqrt_not_ext # no; go handle sgl or dbl
12018 1.2.4.2 wiz
12019 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
12020 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
12021 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
12022 1.2.4.2 wiz
12023 1.2.4.2 wiz bsr.l scale_sqrt # calculate scale factor
12024 1.2.4.2 wiz
12025 1.2.4.2 wiz bra.w fsqrt_sd_normal
12026 1.2.4.2 wiz
12027 1.2.4.2 wiz #
12028 1.2.4.2 wiz # operand is either single or double
12029 1.2.4.2 wiz #
12030 1.2.4.2 wiz fsqrt_not_ext:
12031 1.2.4.2 wiz cmpi.b %d0,&s_mode*0x10 # separate sgl/dbl prec
12032 1.2.4.2 wiz bne.w fsqrt_dbl
12033 1.2.4.2 wiz
12034 1.2.4.2 wiz #
12035 1.2.4.2 wiz # operand is to be rounded to single precision
12036 1.2.4.2 wiz #
12037 1.2.4.2 wiz fsqrt_sgl:
12038 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
12039 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
12040 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
12041 1.2.4.2 wiz
12042 1.2.4.2 wiz bsr.l scale_sqrt # calculate scale factor
12043 1.2.4.2 wiz
12044 1.2.4.2 wiz cmpi.l %d0,&0x3fff-0x3f81 # will move in underflow?
12045 1.2.4.2 wiz beq.w fsqrt_sd_may_unfl
12046 1.2.4.2 wiz bgt.w fsqrt_sd_unfl # yes; go handle underflow
12047 1.2.4.2 wiz cmpi.l %d0,&0x3fff-0x407f # will move in overflow?
12048 1.2.4.2 wiz beq.w fsqrt_sd_may_ovfl # maybe; go check
12049 1.2.4.2 wiz blt.w fsqrt_sd_ovfl # yes; go handle overflow
12050 1.2.4.2 wiz
12051 1.2.4.2 wiz #
12052 1.2.4.2 wiz # operand will NOT overflow or underflow when moved in to the fp reg file
12053 1.2.4.2 wiz #
12054 1.2.4.2 wiz fsqrt_sd_normal:
12055 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
12056 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
12057 1.2.4.2 wiz
12058 1.2.4.2 wiz fsqrt.x FP_SCR0(%a6),%fp0 # perform absolute
12059 1.2.4.2 wiz
12060 1.2.4.2 wiz fmov.l %fpsr,%d1 # save FPSR
12061 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
12062 1.2.4.2 wiz
12063 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
12064 1.2.4.2 wiz
12065 1.2.4.2 wiz fsqrt_sd_normal_exit:
12066 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
12067 1.2.4.2 wiz fmovm.x &0x80,FP_SCR0(%a6) # store out result
12068 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # load sgn,exp
12069 1.2.4.2 wiz mov.l %d1,%d2 # make a copy
12070 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
12071 1.2.4.2 wiz sub.l %d0,%d1 # add scale factor
12072 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
12073 1.2.4.2 wiz or.w %d1,%d2 # concat old sign,new exp
12074 1.2.4.2 wiz mov.w %d2,FP_SCR0_EX(%a6) # insert new exponent
12075 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
12076 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
12077 1.2.4.2 wiz rts
12078 1.2.4.2 wiz
12079 1.2.4.2 wiz #
12080 1.2.4.2 wiz # operand is to be rounded to double precision
12081 1.2.4.2 wiz #
12082 1.2.4.2 wiz fsqrt_dbl:
12083 1.2.4.2 wiz mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
12084 1.2.4.2 wiz mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
12085 1.2.4.2 wiz mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
12086 1.2.4.2 wiz
12087 1.2.4.2 wiz bsr.l scale_sqrt # calculate scale factor
12088 1.2.4.2 wiz
12089 1.2.4.2 wiz cmpi.l %d0,&0x3fff-0x3c01 # will move in underflow?
12090 1.2.4.2 wiz beq.w fsqrt_sd_may_unfl
12091 1.2.4.2 wiz bgt.b fsqrt_sd_unfl # yes; go handle underflow
12092 1.2.4.2 wiz cmpi.l %d0,&0x3fff-0x43ff # will move in overflow?
12093 1.2.4.2 wiz beq.w fsqrt_sd_may_ovfl # maybe; go check
12094 1.2.4.2 wiz blt.w fsqrt_sd_ovfl # yes; go handle overflow
12095 1.2.4.2 wiz bra.w fsqrt_sd_normal # no; ho handle normalized op
12096 1.2.4.2 wiz
12097 1.2.4.2 wiz # we're on the line here and the distinguising characteristic is whether
12098 1.2.4.2 wiz # the exponent is 3fff or 3ffe. if it's 3ffe, then it's a safe number
12099 1.2.4.2 wiz # elsewise fall through to underflow.
12100 1.2.4.2 wiz fsqrt_sd_may_unfl:
12101 1.2.4.2 wiz btst &0x0,1+FP_SCR0_EX(%a6) # is exponent 0x3fff?
12102 1.2.4.2 wiz bne.w fsqrt_sd_normal # yes, so no underflow
12103 1.2.4.2 wiz
12104 1.2.4.2 wiz #
12105 1.2.4.2 wiz # operand WILL underflow when moved in to the fp register file
12106 1.2.4.2 wiz #
12107 1.2.4.2 wiz fsqrt_sd_unfl:
12108 1.2.4.2 wiz bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
12109 1.2.4.2 wiz
12110 1.2.4.2 wiz fmov.l &rz_mode*0x10,%fpcr # set FPCR
12111 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
12112 1.2.4.2 wiz
12113 1.2.4.2 wiz fsqrt.x FP_SCR0(%a6),%fp0 # execute square root
12114 1.2.4.2 wiz
12115 1.2.4.2 wiz fmov.l %fpsr,%d1 # save status
12116 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
12117 1.2.4.2 wiz
12118 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
12119 1.2.4.2 wiz
12120 1.2.4.2 wiz # if underflow or inexact is enabled, go calculate EXOP first.
12121 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d1
12122 1.2.4.2 wiz andi.b &0x0b,%d1 # is UNFL or INEX enabled?
12123 1.2.4.2 wiz bne.b fsqrt_sd_unfl_ena # yes
12124 1.2.4.2 wiz
12125 1.2.4.2 wiz fsqrt_sd_unfl_dis:
12126 1.2.4.2 wiz fmovm.x &0x80,FP_SCR0(%a6) # store out result
12127 1.2.4.2 wiz
12128 1.2.4.2 wiz lea FP_SCR0(%a6),%a0 # pass: result addr
12129 1.2.4.2 wiz mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
12130 1.2.4.2 wiz bsr.l unf_res # calculate default result
12131 1.2.4.2 wiz or.b %d0,FPSR_CC(%a6) # set possible 'Z' ccode
12132 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
12133 1.2.4.2 wiz rts
12134 1.2.4.2 wiz
12135 1.2.4.2 wiz #
12136 1.2.4.2 wiz # operand will underflow AND underflow is enabled.
12137 1.2.4.2 wiz # therefore, we must return the result rounded to extended precision.
12138 1.2.4.2 wiz #
12139 1.2.4.2 wiz fsqrt_sd_unfl_ena:
12140 1.2.4.2 wiz mov.l FP_SCR0_HI(%a6),FP_SCR1_HI(%a6)
12141 1.2.4.2 wiz mov.l FP_SCR0_LO(%a6),FP_SCR1_LO(%a6)
12142 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # load current exponent
12143 1.2.4.2 wiz
12144 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
12145 1.2.4.2 wiz mov.l %d1,%d2 # make a copy
12146 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
12147 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
12148 1.2.4.2 wiz sub.l %d0,%d1 # subtract scale factor
12149 1.2.4.2 wiz addi.l &0x6000,%d1 # add new bias
12150 1.2.4.2 wiz andi.w &0x7fff,%d1
12151 1.2.4.2 wiz or.w %d2,%d1 # concat new sign,new exp
12152 1.2.4.2 wiz mov.w %d1,FP_SCR1_EX(%a6) # insert new exp
12153 1.2.4.2 wiz fmovm.x FP_SCR1(%a6),&0x40 # return EXOP in fp1
12154 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
12155 1.2.4.2 wiz bra.b fsqrt_sd_unfl_dis
12156 1.2.4.2 wiz
12157 1.2.4.2 wiz #
12158 1.2.4.2 wiz # operand WILL overflow.
12159 1.2.4.2 wiz #
12160 1.2.4.2 wiz fsqrt_sd_ovfl:
12161 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
12162 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
12163 1.2.4.2 wiz
12164 1.2.4.2 wiz fsqrt.x FP_SCR0(%a6),%fp0 # perform square root
12165 1.2.4.2 wiz
12166 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
12167 1.2.4.2 wiz fmov.l %fpsr,%d1 # save FPSR
12168 1.2.4.2 wiz
12169 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
12170 1.2.4.2 wiz
12171 1.2.4.2 wiz fsqrt_sd_ovfl_tst:
12172 1.2.4.2 wiz or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
12173 1.2.4.2 wiz
12174 1.2.4.2 wiz mov.b FPCR_ENABLE(%a6),%d1
12175 1.2.4.2 wiz andi.b &0x13,%d1 # is OVFL or INEX enabled?
12176 1.2.4.2 wiz bne.b fsqrt_sd_ovfl_ena # yes
12177 1.2.4.2 wiz
12178 1.2.4.2 wiz #
12179 1.2.4.2 wiz # OVFL is not enabled; therefore, we must create the default result by
12180 1.2.4.2 wiz # calling ovf_res().
12181 1.2.4.2 wiz #
12182 1.2.4.2 wiz fsqrt_sd_ovfl_dis:
12183 1.2.4.2 wiz btst &neg_bit,FPSR_CC(%a6) # is result negative?
12184 1.2.4.2 wiz sne %d1 # set sign param accordingly
12185 1.2.4.2 wiz mov.l L_SCR3(%a6),%d0 # pass: prec,mode
12186 1.2.4.2 wiz bsr.l ovf_res # calculate default result
12187 1.2.4.2 wiz or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
12188 1.2.4.2 wiz fmovm.x (%a0),&0x80 # return default result in fp0
12189 1.2.4.2 wiz rts
12190 1.2.4.2 wiz
12191 1.2.4.2 wiz #
12192 1.2.4.2 wiz # OVFL is enabled.
12193 1.2.4.2 wiz # the INEX2 bit has already been updated by the round to the correct precision.
12194 1.2.4.2 wiz # now, round to extended(and don't alter the FPSR).
12195 1.2.4.2 wiz #
12196 1.2.4.2 wiz fsqrt_sd_ovfl_ena:
12197 1.2.4.2 wiz mov.l %d2,-(%sp) # save d2
12198 1.2.4.2 wiz mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
12199 1.2.4.2 wiz mov.l %d1,%d2 # make a copy
12200 1.2.4.2 wiz andi.l &0x7fff,%d1 # strip sign
12201 1.2.4.2 wiz andi.w &0x8000,%d2 # keep old sign
12202 1.2.4.2 wiz sub.l %d0,%d1 # add scale factor
12203 1.2.4.2 wiz subi.l &0x6000,%d1 # subtract bias
12204 1.2.4.2 wiz andi.w &0x7fff,%d1
12205 1.2.4.2 wiz or.w %d2,%d1 # concat sign,exp
12206 1.2.4.2 wiz mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
12207 1.2.4.2 wiz fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
12208 1.2.4.2 wiz mov.l (%sp)+,%d2 # restore d2
12209 1.2.4.2 wiz bra.b fsqrt_sd_ovfl_dis
12210 1.2.4.2 wiz
12211 1.2.4.2 wiz #
12212 1.2.4.2 wiz # the move in MAY underflow. so...
12213 1.2.4.2 wiz #
12214 1.2.4.2 wiz fsqrt_sd_may_ovfl:
12215 1.2.4.2 wiz btst &0x0,1+FP_SCR0_EX(%a6) # is exponent 0x3fff?
12216 1.2.4.2 wiz bne.w fsqrt_sd_ovfl # yes, so overflow
12217 1.2.4.2 wiz
12218 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear FPSR
12219 1.2.4.2 wiz fmov.l L_SCR3(%a6),%fpcr # set FPCR
12220 1.2.4.2 wiz
12221 1.2.4.2 wiz fsqrt.x FP_SCR0(%a6),%fp0 # perform absolute
12222 1.2.4.2 wiz
12223 1.2.4.2 wiz fmov.l %fpsr,%d1 # save status
12224 1.2.4.2 wiz fmov.l &0x0,%fpcr # clear FPCR
12225 1.2.4.2 wiz
12226 1.2.4.2 wiz or.l %d1,USER_FPSR(%a6) # save INEX2,N
12227 1.2.4.2 wiz
12228 1.2.4.2 wiz fmov.x %fp0,%fp1 # make a copy of result
12229 1.2.4.2 wiz fcmp.b %fp1,&0x1 # is |result| >= 1.b?
12230 1.2.4.2 wiz fbge.w fsqrt_sd_ovfl_tst # yes; overflow has occurred
12231 1.2.4.2 wiz
12232 1.2.4.2 wiz # no, it didn't overflow; we have correct result
12233 1.2.4.2 wiz bra.w fsqrt_sd_normal_exit
12234 1.2.4.2 wiz
12235 1.2.4.2 wiz ##########################################################################
12236 1.2.4.2 wiz
12237 1.2.4.2 wiz #
12238 1.2.4.2 wiz # input is not normalized; what is it?
12239 1.2.4.2 wiz #
12240 1.2.4.2 wiz fsqrt_not_norm:
12241 1.2.4.2 wiz cmpi.b %d1,&DENORM # weed out DENORM
12242 1.2.4.2 wiz beq.w fsqrt_denorm
12243 1.2.4.2 wiz cmpi.b %d1,&ZERO # weed out ZERO
12244 1.2.4.2 wiz beq.b fsqrt_zero
12245 1.2.4.2 wiz cmpi.b %d1,&INF # weed out INF
12246 1.2.4.2 wiz beq.b fsqrt_inf
12247 1.2.4.2 wiz cmpi.b %d1,&SNAN # weed out SNAN
12248 1.2.4.2 wiz beq.l res_snan_1op
12249 1.2.4.2 wiz bra.l res_qnan_1op
12250 1.2.4.2 wiz
12251 1.2.4.2 wiz #
12252 1.2.4.2 wiz # fsqrt(+0) = +0
12253 1.2.4.2 wiz # fsqrt(-0) = -0
12254 1.2.4.2 wiz # fsqrt(+INF) = +INF
12255 1.2.4.2 wiz # fsqrt(-INF) = OPERR
12256 1.2.4.2 wiz #
12257 1.2.4.2 wiz fsqrt_zero:
12258 1.2.4.2 wiz tst.b SRC_EX(%a0) # is ZERO positive or negative?
12259 1.2.4.2 wiz bmi.b fsqrt_zero_m # negative
12260 1.2.4.2 wiz fsqrt_zero_p:
12261 1.2.4.2 wiz fmov.s &0x00000000,%fp0 # return +ZERO
12262 1.2.4.2 wiz mov.b &z_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
12263 1.2.4.2 wiz rts
12264 1.2.4.2 wiz fsqrt_zero_m:
12265 1.2.4.2 wiz fmov.s &0x80000000,%fp0 # return -ZERO
12266 1.2.4.2 wiz mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set 'Z','N' ccode bits
12267 1.2.4.2 wiz rts
12268 1.2.4.2 wiz
12269 1.2.4.2 wiz fsqrt_inf:
12270 1.2.4.2 wiz tst.b SRC_EX(%a0) # is INF positive or negative?
12271 1.2.4.2 wiz bmi.l res_operr # negative
12272 1.2.4.2 wiz fsqrt_inf_p:
12273 1.2.4.2 wiz fmovm.x SRC(%a0),&0x80 # return +INF in fp0
12274 1.2.4.2 wiz mov.b &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
12275 1.2.4.2 wiz rts
12276 1.2.4.2 wiz
12277 1.2.4.2 wiz #########################################################################
12278 1.2.4.2 wiz # XDEF **************************************************************** #
12279 1.2.4.2 wiz # fetch_dreg(): fetch register according to index in d1 #
12280 1.2.4.2 wiz # #
12281 1.2.4.2 wiz # XREF **************************************************************** #
12282 1.2.4.2 wiz # None #
12283 1.2.4.2 wiz # #
12284 1.2.4.2 wiz # INPUT *************************************************************** #
12285 1.2.4.2 wiz # d1 = index of register to fetch from #
12286 1.2.4.2 wiz # #
12287 1.2.4.2 wiz # OUTPUT ************************************************************** #
12288 1.2.4.2 wiz # d0 = value of register fetched #
12289 1.2.4.2 wiz # #
12290 1.2.4.2 wiz # ALGORITHM *********************************************************** #
12291 1.2.4.2 wiz # According to the index value in d1 which can range from zero #
12292 1.2.4.2 wiz # to fifteen, load the corresponding register file value (where #
12293 1.2.4.2 wiz # address register indexes start at 8). D0/D1/A0/A1/A6/A7 are on the #
12294 1.2.4.2 wiz # stack. The rest should still be in their original places. #
12295 1.2.4.2 wiz # #
12296 1.2.4.2 wiz #########################################################################
12297 1.2.4.2 wiz
12298 1.2.4.2 wiz # this routine leaves d1 intact for subsequent store_dreg calls.
12299 1.2.4.2 wiz global fetch_dreg
12300 1.2.4.2 wiz fetch_dreg:
12301 1.2.4.2 wiz mov.w (tbl_fdreg.b,%pc,%d1.w*2),%d0
12302 1.2.4.2 wiz jmp (tbl_fdreg.b,%pc,%d0.w*1)
12303 1.2.4.2 wiz
12304 1.2.4.2 wiz tbl_fdreg:
12305 1.2.4.2 wiz short fdreg0 - tbl_fdreg
12306 1.2.4.2 wiz short fdreg1 - tbl_fdreg
12307 1.2.4.2 wiz short fdreg2 - tbl_fdreg
12308 1.2.4.2 wiz short fdreg3 - tbl_fdreg
12309 1.2.4.2 wiz short fdreg4 - tbl_fdreg
12310 1.2.4.2 wiz short fdreg5 - tbl_fdreg
12311 1.2.4.2 wiz short fdreg6 - tbl_fdreg
12312 1.2.4.2 wiz short fdreg7 - tbl_fdreg
12313 1.2.4.2 wiz short fdreg8 - tbl_fdreg
12314 1.2.4.2 wiz short fdreg9 - tbl_fdreg
12315 1.2.4.2 wiz short fdrega - tbl_fdreg
12316 1.2.4.2 wiz short fdregb - tbl_fdreg
12317 1.2.4.2 wiz short fdregc - tbl_fdreg
12318 1.2.4.2 wiz short fdregd - tbl_fdreg
12319 1.2.4.2 wiz short fdrege - tbl_fdreg
12320 1.2.4.2 wiz short fdregf - tbl_fdreg
12321 1.2.4.2 wiz
12322 1.2.4.2 wiz fdreg0:
12323 1.2.4.2 wiz mov.l EXC_DREGS+0x0(%a6),%d0
12324 1.2.4.2 wiz rts
12325 1.2.4.2 wiz fdreg1:
12326 1.2.4.2 wiz mov.l EXC_DREGS+0x4(%a6),%d0
12327 1.2.4.2 wiz rts
12328 1.2.4.2 wiz fdreg2:
12329 1.2.4.2 wiz mov.l %d2,%d0
12330 1.2.4.2 wiz rts
12331 1.2.4.2 wiz fdreg3:
12332 1.2.4.2 wiz mov.l %d3,%d0
12333 1.2.4.2 wiz rts
12334 1.2.4.2 wiz fdreg4:
12335 1.2.4.2 wiz mov.l %d4,%d0
12336 1.2.4.2 wiz rts
12337 1.2.4.2 wiz fdreg5:
12338 1.2.4.2 wiz mov.l %d5,%d0
12339 1.2.4.2 wiz rts
12340 1.2.4.2 wiz fdreg6:
12341 1.2.4.2 wiz mov.l %d6,%d0
12342 1.2.4.2 wiz rts
12343 1.2.4.2 wiz fdreg7:
12344 1.2.4.2 wiz mov.l %d7,%d0
12345 1.2.4.2 wiz rts
12346 1.2.4.2 wiz fdreg8:
12347 1.2.4.2 wiz mov.l EXC_DREGS+0x8(%a6),%d0
12348 1.2.4.2 wiz rts
12349 1.2.4.2 wiz fdreg9:
12350 1.2.4.2 wiz mov.l EXC_DREGS+0xc(%a6),%d0
12351 1.2.4.2 wiz rts
12352 1.2.4.2 wiz fdrega:
12353 1.2.4.2 wiz mov.l %a2,%d0
12354 1.2.4.2 wiz rts
12355 1.2.4.2 wiz fdregb:
12356 1.2.4.2 wiz mov.l %a3,%d0
12357 1.2.4.2 wiz rts
12358 1.2.4.2 wiz fdregc:
12359 1.2.4.2 wiz mov.l %a4,%d0
12360 1.2.4.2 wiz rts
12361 1.2.4.2 wiz fdregd:
12362 1.2.4.2 wiz mov.l %a5,%d0
12363 1.2.4.2 wiz rts
12364 1.2.4.2 wiz fdrege:
12365 1.2.4.2 wiz mov.l (%a6),%d0
12366 1.2.4.2 wiz rts
12367 1.2.4.2 wiz fdregf:
12368 1.2.4.2 wiz mov.l EXC_A7(%a6),%d0
12369 1.2.4.2 wiz rts
12370 1.2.4.2 wiz
12371 1.2.4.2 wiz #########################################################################
12372 1.2.4.2 wiz # XDEF **************************************************************** #
12373 1.2.4.2 wiz # store_dreg_l(): store longword to data register specified by d1 #
12374 1.2.4.2 wiz # #
12375 1.2.4.2 wiz # XREF **************************************************************** #
12376 1.2.4.2 wiz # None #
12377 1.2.4.2 wiz # #
12378 1.2.4.2 wiz # INPUT *************************************************************** #
12379 1.2.4.2 wiz # d0 = longowrd value to store #
12380 1.2.4.2 wiz # d1 = index of register to fetch from #
12381 1.2.4.2 wiz # #
12382 1.2.4.2 wiz # OUTPUT ************************************************************** #
12383 1.2.4.2 wiz # (data register is updated) #
12384 1.2.4.2 wiz # #
12385 1.2.4.2 wiz # ALGORITHM *********************************************************** #
12386 1.2.4.2 wiz # According to the index value in d1, store the longword value #
12387 1.2.4.2 wiz # in d0 to the corresponding data register. D0/D1 are on the stack #
12388 1.2.4.2 wiz # while the rest are in their initial places. #
12389 1.2.4.2 wiz # #
12390 1.2.4.2 wiz #########################################################################
12391 1.2.4.2 wiz
12392 1.2.4.2 wiz global store_dreg_l
12393 1.2.4.2 wiz store_dreg_l:
12394 1.2.4.2 wiz mov.w (tbl_sdregl.b,%pc,%d1.w*2),%d1
12395 1.2.4.2 wiz jmp (tbl_sdregl.b,%pc,%d1.w*1)
12396 1.2.4.2 wiz
12397 1.2.4.2 wiz tbl_sdregl:
12398 1.2.4.2 wiz short sdregl0 - tbl_sdregl
12399 1.2.4.2 wiz short sdregl1 - tbl_sdregl
12400 1.2.4.2 wiz short sdregl2 - tbl_sdregl
12401 1.2.4.2 wiz short sdregl3 - tbl_sdregl
12402 1.2.4.2 wiz short sdregl4 - tbl_sdregl
12403 1.2.4.2 wiz short sdregl5 - tbl_sdregl
12404 1.2.4.2 wiz short sdregl6 - tbl_sdregl
12405 1.2.4.2 wiz short sdregl7 - tbl_sdregl
12406 1.2.4.2 wiz
12407 1.2.4.2 wiz sdregl0:
12408 1.2.4.2 wiz mov.l %d0,EXC_DREGS+0x0(%a6)
12409 1.2.4.2 wiz rts
12410 1.2.4.2 wiz sdregl1:
12411 1.2.4.2 wiz mov.l %d0,EXC_DREGS+0x4(%a6)
12412 1.2.4.2 wiz rts
12413 1.2.4.2 wiz sdregl2:
12414 1.2.4.2 wiz mov.l %d0,%d2
12415 1.2.4.2 wiz rts
12416 1.2.4.2 wiz sdregl3:
12417 1.2.4.2 wiz mov.l %d0,%d3
12418 1.2.4.2 wiz rts
12419 1.2.4.2 wiz sdregl4:
12420 1.2.4.2 wiz mov.l %d0,%d4
12421 1.2.4.2 wiz rts
12422 1.2.4.2 wiz sdregl5:
12423 1.2.4.2 wiz mov.l %d0,%d5
12424 1.2.4.2 wiz rts
12425 1.2.4.2 wiz sdregl6:
12426 1.2.4.2 wiz mov.l %d0,%d6
12427 1.2.4.2 wiz rts
12428 1.2.4.2 wiz sdregl7:
12429 1.2.4.2 wiz mov.l %d0,%d7
12430 1.2.4.2 wiz rts
12431 1.2.4.2 wiz
12432 1.2.4.2 wiz #########################################################################
12433 1.2.4.2 wiz # XDEF **************************************************************** #
12434 1.2.4.2 wiz # store_dreg_w(): store word to data register specified by d1 #
12435 1.2.4.2 wiz # #
12436 1.2.4.2 wiz # XREF **************************************************************** #
12437 1.2.4.2 wiz # None #
12438 1.2.4.2 wiz # #
12439 1.2.4.2 wiz # INPUT *************************************************************** #
12440 1.2.4.2 wiz # d0 = word value to store #
12441 1.2.4.2 wiz # d1 = index of register to fetch from #
12442 1.2.4.2 wiz # #
12443 1.2.4.2 wiz # OUTPUT ************************************************************** #
12444 1.2.4.2 wiz # (data register is updated) #
12445 1.2.4.2 wiz # #
12446 1.2.4.2 wiz # ALGORITHM *********************************************************** #
12447 1.2.4.2 wiz # According to the index value in d1, store the word value #
12448 1.2.4.2 wiz # in d0 to the corresponding data register. D0/D1 are on the stack #
12449 1.2.4.2 wiz # while the rest are in their initial places. #
12450 1.2.4.2 wiz # #
12451 1.2.4.2 wiz #########################################################################
12452 1.2.4.2 wiz
12453 1.2.4.2 wiz global store_dreg_w
12454 1.2.4.2 wiz store_dreg_w:
12455 1.2.4.2 wiz mov.w (tbl_sdregw.b,%pc,%d1.w*2),%d1
12456 1.2.4.2 wiz jmp (tbl_sdregw.b,%pc,%d1.w*1)
12457 1.2.4.2 wiz
12458 1.2.4.2 wiz tbl_sdregw:
12459 1.2.4.2 wiz short sdregw0 - tbl_sdregw
12460 1.2.4.2 wiz short sdregw1 - tbl_sdregw
12461 1.2.4.2 wiz short sdregw2 - tbl_sdregw
12462 1.2.4.2 wiz short sdregw3 - tbl_sdregw
12463 1.2.4.2 wiz short sdregw4 - tbl_sdregw
12464 1.2.4.2 wiz short sdregw5 - tbl_sdregw
12465 1.2.4.2 wiz short sdregw6 - tbl_sdregw
12466 1.2.4.2 wiz short sdregw7 - tbl_sdregw
12467 1.2.4.2 wiz
12468 1.2.4.2 wiz sdregw0:
12469 1.2.4.2 wiz mov.w %d0,2+EXC_DREGS+0x0(%a6)
12470 1.2.4.2 wiz rts
12471 1.2.4.2 wiz sdregw1:
12472 1.2.4.2 wiz mov.w %d0,2+EXC_DREGS+0x4(%a6)
12473 1.2.4.2 wiz rts
12474 1.2.4.2 wiz sdregw2:
12475 1.2.4.2 wiz mov.w %d0,%d2
12476 1.2.4.2 wiz rts
12477 1.2.4.2 wiz sdregw3:
12478 1.2.4.2 wiz mov.w %d0,%d3
12479 1.2.4.2 wiz rts
12480 1.2.4.2 wiz sdregw4:
12481 1.2.4.2 wiz mov.w %d0,%d4
12482 1.2.4.2 wiz rts
12483 1.2.4.2 wiz sdregw5:
12484 1.2.4.2 wiz mov.w %d0,%d5
12485 1.2.4.2 wiz rts
12486 1.2.4.2 wiz sdregw6:
12487 1.2.4.2 wiz mov.w %d0,%d6
12488 1.2.4.2 wiz rts
12489 1.2.4.2 wiz sdregw7:
12490 1.2.4.2 wiz mov.w %d0,%d7
12491 1.2.4.2 wiz rts
12492 1.2.4.2 wiz
12493 1.2.4.2 wiz #########################################################################
12494 1.2.4.2 wiz # XDEF **************************************************************** #
12495 1.2.4.2 wiz # store_dreg_b(): store byte to data register specified by d1 #
12496 1.2.4.2 wiz # #
12497 1.2.4.2 wiz # XREF **************************************************************** #
12498 1.2.4.2 wiz # None #
12499 1.2.4.2 wiz # #
12500 1.2.4.2 wiz # INPUT *************************************************************** #
12501 1.2.4.2 wiz # d0 = byte value to store #
12502 1.2.4.2 wiz # d1 = index of register to fetch from #
12503 1.2.4.2 wiz # #
12504 1.2.4.2 wiz # OUTPUT ************************************************************** #
12505 1.2.4.2 wiz # (data register is updated) #
12506 1.2.4.2 wiz # #
12507 1.2.4.2 wiz # ALGORITHM *********************************************************** #
12508 1.2.4.2 wiz # According to the index value in d1, store the byte value #
12509 1.2.4.2 wiz # in d0 to the corresponding data register. D0/D1 are on the stack #
12510 1.2.4.2 wiz # while the rest are in their initial places. #
12511 1.2.4.2 wiz # #
12512 1.2.4.2 wiz #########################################################################
12513 1.2.4.2 wiz
12514 1.2.4.2 wiz global store_dreg_b
12515 1.2.4.2 wiz store_dreg_b:
12516 1.2.4.2 wiz mov.w (tbl_sdregb.b,%pc,%d1.w*2),%d1
12517 1.2.4.2 wiz jmp (tbl_sdregb.b,%pc,%d1.w*1)
12518 1.2.4.2 wiz
12519 1.2.4.2 wiz tbl_sdregb:
12520 1.2.4.2 wiz short sdregb0 - tbl_sdregb
12521 1.2.4.2 wiz short sdregb1 - tbl_sdregb
12522 1.2.4.2 wiz short sdregb2 - tbl_sdregb
12523 1.2.4.2 wiz short sdregb3 - tbl_sdregb
12524 1.2.4.2 wiz short sdregb4 - tbl_sdregb
12525 1.2.4.2 wiz short sdregb5 - tbl_sdregb
12526 1.2.4.2 wiz short sdregb6 - tbl_sdregb
12527 1.2.4.2 wiz short sdregb7 - tbl_sdregb
12528 1.2.4.2 wiz
12529 1.2.4.2 wiz sdregb0:
12530 1.2.4.2 wiz mov.b %d0,3+EXC_DREGS+0x0(%a6)
12531 1.2.4.2 wiz rts
12532 1.2.4.2 wiz sdregb1:
12533 1.2.4.2 wiz mov.b %d0,3+EXC_DREGS+0x4(%a6)
12534 1.2.4.2 wiz rts
12535 1.2.4.2 wiz sdregb2:
12536 1.2.4.2 wiz mov.b %d0,%d2
12537 1.2.4.2 wiz rts
12538 1.2.4.2 wiz sdregb3:
12539 1.2.4.2 wiz mov.b %d0,%d3
12540 1.2.4.2 wiz rts
12541 1.2.4.2 wiz sdregb4:
12542 1.2.4.2 wiz mov.b %d0,%d4
12543 1.2.4.2 wiz rts
12544 1.2.4.2 wiz sdregb5:
12545 1.2.4.2 wiz mov.b %d0,%d5
12546 1.2.4.2 wiz rts
12547 1.2.4.2 wiz sdregb6:
12548 1.2.4.2 wiz mov.b %d0,%d6
12549 1.2.4.2 wiz rts
12550 1.2.4.2 wiz sdregb7:
12551 1.2.4.2 wiz mov.b %d0,%d7
12552 1.2.4.2 wiz rts
12553 1.2.4.2 wiz
12554 1.2.4.2 wiz #########################################################################
12555 1.2.4.2 wiz # XDEF **************************************************************** #
12556 1.2.4.2 wiz # inc_areg(): increment an address register by the value in d0 #
12557 1.2.4.2 wiz # #
12558 1.2.4.2 wiz # XREF **************************************************************** #
12559 1.2.4.2 wiz # None #
12560 1.2.4.2 wiz # #
12561 1.2.4.2 wiz # INPUT *************************************************************** #
12562 1.2.4.2 wiz # d0 = amount to increment by #
12563 1.2.4.2 wiz # d1 = index of address register to increment #
12564 1.2.4.2 wiz # #
12565 1.2.4.2 wiz # OUTPUT ************************************************************** #
12566 1.2.4.2 wiz # (address register is updated) #
12567 1.2.4.2 wiz # #
12568 1.2.4.2 wiz # ALGORITHM *********************************************************** #
12569 1.2.4.2 wiz # Typically used for an instruction w/ a post-increment <ea>, #
12570 1.2.4.2 wiz # this routine adds the increment value in d0 to the address register #
12571 1.2.4.2 wiz # specified by d1. A0/A1/A6/A7 reside on the stack. The rest reside #
12572 1.2.4.2 wiz # in their original places. #
12573 1.2.4.2 wiz # For a7, if the increment amount is one, then we have to #
12574 1.2.4.2 wiz # increment by two. For any a7 update, set the mia7_flag so that if #
12575 1.2.4.2 wiz # an access error exception occurs later in emulation, this address #
12576 1.2.4.2 wiz # register update can be undone. #
12577 1.2.4.2 wiz # #
12578 1.2.4.2 wiz #########################################################################
12579 1.2.4.2 wiz
12580 1.2.4.2 wiz global inc_areg
12581 1.2.4.2 wiz inc_areg:
12582 1.2.4.2 wiz mov.w (tbl_iareg.b,%pc,%d1.w*2),%d1
12583 1.2.4.2 wiz jmp (tbl_iareg.b,%pc,%d1.w*1)
12584 1.2.4.2 wiz
12585 1.2.4.2 wiz tbl_iareg:
12586 1.2.4.2 wiz short iareg0 - tbl_iareg
12587 1.2.4.2 wiz short iareg1 - tbl_iareg
12588 1.2.4.2 wiz short iareg2 - tbl_iareg
12589 1.2.4.2 wiz short iareg3 - tbl_iareg
12590 1.2.4.2 wiz short iareg4 - tbl_iareg
12591 1.2.4.2 wiz short iareg5 - tbl_iareg
12592 1.2.4.2 wiz short iareg6 - tbl_iareg
12593 1.2.4.2 wiz short iareg7 - tbl_iareg
12594 1.2.4.2 wiz
12595 1.2.4.2 wiz iareg0: add.l %d0,EXC_DREGS+0x8(%a6)
12596 1.2.4.2 wiz rts
12597 1.2.4.2 wiz iareg1: add.l %d0,EXC_DREGS+0xc(%a6)
12598 1.2.4.2 wiz rts
12599 1.2.4.2 wiz iareg2: add.l %d0,%a2
12600 1.2.4.2 wiz rts
12601 1.2.4.2 wiz iareg3: add.l %d0,%a3
12602 1.2.4.2 wiz rts
12603 1.2.4.2 wiz iareg4: add.l %d0,%a4
12604 1.2.4.2 wiz rts
12605 1.2.4.2 wiz iareg5: add.l %d0,%a5
12606 1.2.4.2 wiz rts
12607 1.2.4.2 wiz iareg6: add.l %d0,(%a6)
12608 1.2.4.2 wiz rts
12609 1.2.4.2 wiz iareg7: mov.b &mia7_flg,SPCOND_FLG(%a6)
12610 1.2.4.2 wiz cmpi.b %d0,&0x1
12611 1.2.4.2 wiz beq.b iareg7b
12612 1.2.4.2 wiz add.l %d0,EXC_A7(%a6)
12613 1.2.4.2 wiz rts
12614 1.2.4.2 wiz iareg7b:
12615 1.2.4.2 wiz addq.l &0x2,EXC_A7(%a6)
12616 1.2.4.2 wiz rts
12617 1.2.4.2 wiz
12618 1.2.4.2 wiz #########################################################################
12619 1.2.4.2 wiz # XDEF **************************************************************** #
12620 1.2.4.2 wiz # dec_areg(): decrement an address register by the value in d0 #
12621 1.2.4.2 wiz # #
12622 1.2.4.2 wiz # XREF **************************************************************** #
12623 1.2.4.2 wiz # None #
12624 1.2.4.2 wiz # #
12625 1.2.4.2 wiz # INPUT *************************************************************** #
12626 1.2.4.2 wiz # d0 = amount to decrement by #
12627 1.2.4.2 wiz # d1 = index of address register to decrement #
12628 1.2.4.2 wiz # #
12629 1.2.4.2 wiz # OUTPUT ************************************************************** #
12630 1.2.4.2 wiz # (address register is updated) #
12631 1.2.4.2 wiz # #
12632 1.2.4.2 wiz # ALGORITHM *********************************************************** #
12633 1.2.4.2 wiz # Typically used for an instruction w/ a pre-decrement <ea>, #
12634 1.2.4.2 wiz # this routine adds the decrement value in d0 to the address register #
12635 1.2.4.2 wiz # specified by d1. A0/A1/A6/A7 reside on the stack. The rest reside #
12636 1.2.4.2 wiz # in their original places. #
12637 1.2.4.2 wiz # For a7, if the decrement amount is one, then we have to #
12638 1.2.4.2 wiz # decrement by two. For any a7 update, set the mda7_flag so that if #
12639 1.2.4.2 wiz # an access error exception occurs later in emulation, this address #
12640 1.2.4.2 wiz # register update can be undone. #
12641 1.2.4.2 wiz # #
12642 1.2.4.2 wiz #########################################################################
12643 1.2.4.2 wiz
12644 1.2.4.2 wiz global dec_areg
12645 1.2.4.2 wiz dec_areg:
12646 1.2.4.2 wiz mov.w (tbl_dareg.b,%pc,%d1.w*2),%d1
12647 1.2.4.2 wiz jmp (tbl_dareg.b,%pc,%d1.w*1)
12648 1.2.4.2 wiz
12649 1.2.4.2 wiz tbl_dareg:
12650 1.2.4.2 wiz short dareg0 - tbl_dareg
12651 1.2.4.2 wiz short dareg1 - tbl_dareg
12652 1.2.4.2 wiz short dareg2 - tbl_dareg
12653 1.2.4.2 wiz short dareg3 - tbl_dareg
12654 1.2.4.2 wiz short dareg4 - tbl_dareg
12655 1.2.4.2 wiz short dareg5 - tbl_dareg
12656 1.2.4.2 wiz short dareg6 - tbl_dareg
12657 1.2.4.2 wiz short dareg7 - tbl_dareg
12658 1.2.4.2 wiz
12659 1.2.4.2 wiz dareg0: sub.l %d0,EXC_DREGS+0x8(%a6)
12660 1.2.4.2 wiz rts
12661 1.2.4.2 wiz dareg1: sub.l %d0,EXC_DREGS+0xc(%a6)
12662 1.2.4.2 wiz rts
12663 1.2.4.2 wiz dareg2: sub.l %d0,%a2
12664 1.2.4.2 wiz rts
12665 1.2.4.2 wiz dareg3: sub.l %d0,%a3
12666 1.2.4.2 wiz rts
12667 1.2.4.2 wiz dareg4: sub.l %d0,%a4
12668 1.2.4.2 wiz rts
12669 1.2.4.2 wiz dareg5: sub.l %d0,%a5
12670 1.2.4.2 wiz rts
12671 1.2.4.2 wiz dareg6: sub.l %d0,(%a6)
12672 1.2.4.2 wiz rts
12673 1.2.4.2 wiz dareg7: mov.b &mda7_flg,SPCOND_FLG(%a6)
12674 1.2.4.2 wiz cmpi.b %d0,&0x1
12675 1.2.4.2 wiz beq.b dareg7b
12676 1.2.4.2 wiz sub.l %d0,EXC_A7(%a6)
12677 1.2.4.2 wiz rts
12678 1.2.4.2 wiz dareg7b:
12679 1.2.4.2 wiz subq.l &0x2,EXC_A7(%a6)
12680 1.2.4.2 wiz rts
12681 1.2.4.2 wiz
12682 1.2.4.2 wiz ##############################################################################
12683 1.2.4.2 wiz
12684 1.2.4.2 wiz #########################################################################
12685 1.2.4.2 wiz # XDEF **************************************************************** #
12686 1.2.4.2 wiz # load_fpn1(): load FP register value into FP_SRC(a6). #
12687 1.2.4.2 wiz # #
12688 1.2.4.2 wiz # XREF **************************************************************** #
12689 1.2.4.2 wiz # None #
12690 1.2.4.2 wiz # #
12691 1.2.4.2 wiz # INPUT *************************************************************** #
12692 1.2.4.2 wiz # d0 = index of FP register to load #
12693 1.2.4.2 wiz # #
12694 1.2.4.2 wiz # OUTPUT ************************************************************** #
12695 1.2.4.2 wiz # FP_SRC(a6) = value loaded from FP register file #
12696 1.2.4.2 wiz # #
12697 1.2.4.2 wiz # ALGORITHM *********************************************************** #
12698 1.2.4.2 wiz # Using the index in d0, load FP_SRC(a6) with a number from the #
12699 1.2.4.2 wiz # FP register file. #
12700 1.2.4.2 wiz # #
12701 1.2.4.2 wiz #########################################################################
12702 1.2.4.2 wiz
12703 1.2.4.2 wiz global load_fpn1
12704 1.2.4.2 wiz load_fpn1:
12705 1.2.4.2 wiz mov.w (tbl_load_fpn1.b,%pc,%d0.w*2), %d0
12706 1.2.4.2 wiz jmp (tbl_load_fpn1.b,%pc,%d0.w*1)
12707 1.2.4.2 wiz
12708 1.2.4.2 wiz tbl_load_fpn1:
12709 1.2.4.2 wiz short load_fpn1_0 - tbl_load_fpn1
12710 1.2.4.2 wiz short load_fpn1_1 - tbl_load_fpn1
12711 1.2.4.2 wiz short load_fpn1_2 - tbl_load_fpn1
12712 1.2.4.2 wiz short load_fpn1_3 - tbl_load_fpn1
12713 1.2.4.2 wiz short load_fpn1_4 - tbl_load_fpn1
12714 1.2.4.2 wiz short load_fpn1_5 - tbl_load_fpn1
12715 1.2.4.2 wiz short load_fpn1_6 - tbl_load_fpn1
12716 1.2.4.2 wiz short load_fpn1_7 - tbl_load_fpn1
12717 1.2.4.2 wiz
12718 1.2.4.2 wiz load_fpn1_0:
12719 1.2.4.2 wiz mov.l 0+EXC_FP0(%a6), 0+FP_SRC(%a6)
12720 1.2.4.2 wiz mov.l 4+EXC_FP0(%a6), 4+FP_SRC(%a6)
12721 1.2.4.2 wiz mov.l 8+EXC_FP0(%a6), 8+FP_SRC(%a6)
12722 1.2.4.2 wiz lea FP_SRC(%a6), %a0
12723 1.2.4.2 wiz rts
12724 1.2.4.2 wiz load_fpn1_1:
12725 1.2.4.2 wiz mov.l 0+EXC_FP1(%a6), 0+FP_SRC(%a6)
12726 1.2.4.2 wiz mov.l 4+EXC_FP1(%a6), 4+FP_SRC(%a6)
12727 1.2.4.2 wiz mov.l 8+EXC_FP1(%a6), 8+FP_SRC(%a6)
12728 1.2.4.2 wiz lea FP_SRC(%a6), %a0
12729 1.2.4.2 wiz rts
12730 1.2.4.2 wiz load_fpn1_2:
12731 1.2.4.2 wiz fmovm.x &0x20, FP_SRC(%a6)
12732 1.2.4.2 wiz lea FP_SRC(%a6), %a0
12733 1.2.4.2 wiz rts
12734 1.2.4.2 wiz load_fpn1_3:
12735 1.2.4.2 wiz fmovm.x &0x10, FP_SRC(%a6)
12736 1.2.4.2 wiz lea FP_SRC(%a6), %a0
12737 1.2.4.2 wiz rts
12738 1.2.4.2 wiz load_fpn1_4:
12739 1.2.4.2 wiz fmovm.x &0x08, FP_SRC(%a6)
12740 1.2.4.2 wiz lea FP_SRC(%a6), %a0
12741 1.2.4.2 wiz rts
12742 1.2.4.2 wiz load_fpn1_5:
12743 1.2.4.2 wiz fmovm.x &0x04, FP_SRC(%a6)
12744 1.2.4.2 wiz lea FP_SRC(%a6), %a0
12745 1.2.4.2 wiz rts
12746 1.2.4.2 wiz load_fpn1_6:
12747 1.2.4.2 wiz fmovm.x &0x02, FP_SRC(%a6)
12748 1.2.4.2 wiz lea FP_SRC(%a6), %a0
12749 1.2.4.2 wiz rts
12750 1.2.4.2 wiz load_fpn1_7:
12751 1.2.4.2 wiz fmovm.x &0x01, FP_SRC(%a6)
12752 1.2.4.2 wiz lea FP_SRC(%a6), %a0
12753 1.2.4.2 wiz rts
12754 1.2.4.2 wiz
12755 1.2.4.2 wiz #############################################################################
12756 1.2.4.2 wiz
12757 1.2.4.2 wiz #########################################################################
12758 1.2.4.2 wiz # XDEF **************************************************************** #
12759 1.2.4.2 wiz # load_fpn2(): load FP register value into FP_DST(a6). #
12760 1.2.4.2 wiz # #
12761 1.2.4.2 wiz # XREF **************************************************************** #
12762 1.2.4.2 wiz # None #
12763 1.2.4.2 wiz # #
12764 1.2.4.2 wiz # INPUT *************************************************************** #
12765 1.2.4.2 wiz # d0 = index of FP register to load #
12766 1.2.4.2 wiz # #
12767 1.2.4.2 wiz # OUTPUT ************************************************************** #
12768 1.2.4.2 wiz # FP_DST(a6) = value loaded from FP register file #
12769 1.2.4.2 wiz # #
12770 1.2.4.2 wiz # ALGORITHM *********************************************************** #
12771 1.2.4.2 wiz # Using the index in d0, load FP_DST(a6) with a number from the #
12772 1.2.4.2 wiz # FP register file. #
12773 1.2.4.2 wiz # #
12774 1.2.4.2 wiz #########################################################################
12775 1.2.4.2 wiz
12776 1.2.4.2 wiz global load_fpn2
12777 1.2.4.2 wiz load_fpn2:
12778 1.2.4.2 wiz mov.w (tbl_load_fpn2.b,%pc,%d0.w*2), %d0
12779 1.2.4.2 wiz jmp (tbl_load_fpn2.b,%pc,%d0.w*1)
12780 1.2.4.2 wiz
12781 1.2.4.2 wiz tbl_load_fpn2:
12782 1.2.4.2 wiz short load_fpn2_0 - tbl_load_fpn2
12783 1.2.4.2 wiz short load_fpn2_1 - tbl_load_fpn2
12784 1.2.4.2 wiz short load_fpn2_2 - tbl_load_fpn2
12785 1.2.4.2 wiz short load_fpn2_3 - tbl_load_fpn2
12786 1.2.4.2 wiz short load_fpn2_4 - tbl_load_fpn2
12787 1.2.4.2 wiz short load_fpn2_5 - tbl_load_fpn2
12788 1.2.4.2 wiz short load_fpn2_6 - tbl_load_fpn2
12789 1.2.4.2 wiz short load_fpn2_7 - tbl_load_fpn2
12790 1.2.4.2 wiz
12791 1.2.4.2 wiz load_fpn2_0:
12792 1.2.4.2 wiz mov.l 0+EXC_FP0(%a6), 0+FP_DST(%a6)
12793 1.2.4.2 wiz mov.l 4+EXC_FP0(%a6), 4+FP_DST(%a6)
12794 1.2.4.2 wiz mov.l 8+EXC_FP0(%a6), 8+FP_DST(%a6)
12795 1.2.4.2 wiz lea FP_DST(%a6), %a0
12796 1.2.4.2 wiz rts
12797 1.2.4.2 wiz load_fpn2_1:
12798 1.2.4.2 wiz mov.l 0+EXC_FP1(%a6), 0+FP_DST(%a6)
12799 1.2.4.2 wiz mov.l 4+EXC_FP1(%a6), 4+FP_DST(%a6)
12800 1.2.4.2 wiz mov.l 8+EXC_FP1(%a6), 8+FP_DST(%a6)
12801 1.2.4.2 wiz lea FP_DST(%a6), %a0
12802 1.2.4.2 wiz rts
12803 1.2.4.2 wiz load_fpn2_2:
12804 1.2.4.2 wiz fmovm.x &0x20, FP_DST(%a6)
12805 1.2.4.2 wiz lea FP_DST(%a6), %a0
12806 1.2.4.2 wiz rts
12807 1.2.4.2 wiz load_fpn2_3:
12808 1.2.4.2 wiz fmovm.x &0x10, FP_DST(%a6)
12809 1.2.4.2 wiz lea FP_DST(%a6), %a0
12810 1.2.4.2 wiz rts
12811 1.2.4.2 wiz load_fpn2_4:
12812 1.2.4.2 wiz fmovm.x &0x08, FP_DST(%a6)
12813 1.2.4.2 wiz lea FP_DST(%a6), %a0
12814 1.2.4.2 wiz rts
12815 1.2.4.2 wiz load_fpn2_5:
12816 1.2.4.2 wiz fmovm.x &0x04, FP_DST(%a6)
12817 1.2.4.2 wiz lea FP_DST(%a6), %a0
12818 1.2.4.2 wiz rts
12819 1.2.4.2 wiz load_fpn2_6:
12820 1.2.4.2 wiz fmovm.x &0x02, FP_DST(%a6)
12821 1.2.4.2 wiz lea FP_DST(%a6), %a0
12822 1.2.4.2 wiz rts
12823 1.2.4.2 wiz load_fpn2_7:
12824 1.2.4.2 wiz fmovm.x &0x01, FP_DST(%a6)
12825 1.2.4.2 wiz lea FP_DST(%a6), %a0
12826 1.2.4.2 wiz rts
12827 1.2.4.2 wiz
12828 1.2.4.2 wiz #############################################################################
12829 1.2.4.2 wiz
12830 1.2.4.2 wiz #########################################################################
12831 1.2.4.2 wiz # XDEF **************************************************************** #
12832 1.2.4.2 wiz # store_fpreg(): store an fp value to the fpreg designated d0. #
12833 1.2.4.2 wiz # #
12834 1.2.4.2 wiz # XREF **************************************************************** #
12835 1.2.4.2 wiz # None #
12836 1.2.4.2 wiz # #
12837 1.2.4.2 wiz # INPUT *************************************************************** #
12838 1.2.4.2 wiz # fp0 = extended precision value to store #
12839 1.2.4.2 wiz # d0 = index of floating-point register #
12840 1.2.4.2 wiz # #
12841 1.2.4.2 wiz # OUTPUT ************************************************************** #
12842 1.2.4.2 wiz # None #
12843 1.2.4.2 wiz # #
12844 1.2.4.2 wiz # ALGORITHM *********************************************************** #
12845 1.2.4.2 wiz # Store the value in fp0 to the FP register designated by the #
12846 1.2.4.2 wiz # value in d0. The FP number can be DENORM or SNAN so we have to be #
12847 1.2.4.2 wiz # careful that we don't take an exception here. #
12848 1.2.4.2 wiz # #
12849 1.2.4.2 wiz #########################################################################
12850 1.2.4.2 wiz
12851 1.2.4.2 wiz global store_fpreg
12852 1.2.4.2 wiz store_fpreg:
12853 1.2.4.2 wiz mov.w (tbl_store_fpreg.b,%pc,%d0.w*2), %d0
12854 1.2.4.2 wiz jmp (tbl_store_fpreg.b,%pc,%d0.w*1)
12855 1.2.4.2 wiz
12856 1.2.4.2 wiz tbl_store_fpreg:
12857 1.2.4.2 wiz short store_fpreg_0 - tbl_store_fpreg
12858 1.2.4.2 wiz short store_fpreg_1 - tbl_store_fpreg
12859 1.2.4.2 wiz short store_fpreg_2 - tbl_store_fpreg
12860 1.2.4.2 wiz short store_fpreg_3 - tbl_store_fpreg
12861 1.2.4.2 wiz short store_fpreg_4 - tbl_store_fpreg
12862 1.2.4.2 wiz short store_fpreg_5 - tbl_store_fpreg
12863 1.2.4.2 wiz short store_fpreg_6 - tbl_store_fpreg
12864 1.2.4.2 wiz short store_fpreg_7 - tbl_store_fpreg
12865 1.2.4.2 wiz
12866 1.2.4.2 wiz store_fpreg_0:
12867 1.2.4.2 wiz fmovm.x &0x80, EXC_FP0(%a6)
12868 1.2.4.2 wiz rts
12869 1.2.4.2 wiz store_fpreg_1:
12870 1.2.4.2 wiz fmovm.x &0x80, EXC_FP1(%a6)
12871 1.2.4.2 wiz rts
12872 1.2.4.2 wiz store_fpreg_2:
12873 1.2.4.2 wiz fmovm.x &0x01, -(%sp)
12874 1.2.4.2 wiz fmovm.x (%sp)+, &0x20
12875 1.2.4.2 wiz rts
12876 1.2.4.2 wiz store_fpreg_3:
12877 1.2.4.2 wiz fmovm.x &0x01, -(%sp)
12878 1.2.4.2 wiz fmovm.x (%sp)+, &0x10
12879 1.2.4.2 wiz rts
12880 1.2.4.2 wiz store_fpreg_4:
12881 1.2.4.2 wiz fmovm.x &0x01, -(%sp)
12882 1.2.4.2 wiz fmovm.x (%sp)+, &0x08
12883 1.2.4.2 wiz rts
12884 1.2.4.2 wiz store_fpreg_5:
12885 1.2.4.2 wiz fmovm.x &0x01, -(%sp)
12886 1.2.4.2 wiz fmovm.x (%sp)+, &0x04
12887 1.2.4.2 wiz rts
12888 1.2.4.2 wiz store_fpreg_6:
12889 1.2.4.2 wiz fmovm.x &0x01, -(%sp)
12890 1.2.4.2 wiz fmovm.x (%sp)+, &0x02
12891 1.2.4.2 wiz rts
12892 1.2.4.2 wiz store_fpreg_7:
12893 1.2.4.2 wiz fmovm.x &0x01, -(%sp)
12894 1.2.4.2 wiz fmovm.x (%sp)+, &0x01
12895 1.2.4.2 wiz rts
12896 1.2.4.2 wiz
12897 1.2.4.2 wiz #########################################################################
12898 1.2.4.2 wiz # XDEF **************************************************************** #
12899 1.2.4.2 wiz # get_packed(): fetch a packed operand from memory and then #
12900 1.2.4.2 wiz # convert it to a floating-point binary number. #
12901 1.2.4.2 wiz # #
12902 1.2.4.2 wiz # XREF **************************************************************** #
12903 1.2.4.2 wiz # _dcalc_ea() - calculate the correct <ea> #
12904 1.2.4.2 wiz # _mem_read() - fetch the packed operand from memory #
12905 1.2.4.2 wiz # facc_in_x() - the fetch failed so jump to special exit code #
12906 1.2.4.2 wiz # decbin() - convert packed to binary extended precision #
12907 1.2.4.2 wiz # #
12908 1.2.4.2 wiz # INPUT *************************************************************** #
12909 1.2.4.2 wiz # None #
12910 1.2.4.2 wiz # #
12911 1.2.4.2 wiz # OUTPUT ************************************************************** #
12912 1.2.4.2 wiz # If no failure on _mem_read(): #
12913 1.2.4.2 wiz # FP_SRC(a6) = packed operand now as a binary FP number #
12914 1.2.4.2 wiz # #
12915 1.2.4.2 wiz # ALGORITHM *********************************************************** #
12916 1.2.4.2 wiz # Get the correct <ea> whihc is the value on the exception stack #
12917 1.2.4.2 wiz # frame w/ maybe a correction factor if the <ea> is -(an) or (an)+. #
12918 1.2.4.2 wiz # Then, fetch the operand from memory. If the fetch fails, exit #
12919 1.2.4.2 wiz # through facc_in_x(). #
12920 1.2.4.2 wiz # If the packed operand is a ZERO,NAN, or INF, convert it to #
12921 1.2.4.2 wiz # its binary representation here. Else, call decbin() which will #
12922 1.2.4.2 wiz # convert the packed value to an extended precision binary value. #
12923 1.2.4.2 wiz # #
12924 1.2.4.2 wiz #########################################################################
12925 1.2.4.2 wiz
12926 1.2.4.2 wiz # the stacked <ea> for packed is correct except for -(An).
12927 1.2.4.2 wiz # the base reg must be updated for both -(An) and (An)+.
12928 1.2.4.2 wiz global get_packed
12929 1.2.4.2 wiz get_packed:
12930 1.2.4.2 wiz mov.l &0xc,%d0 # packed is 12 bytes
12931 1.2.4.2 wiz bsr.l _dcalc_ea # fetch <ea>; correct An
12932 1.2.4.2 wiz
12933 1.2.4.2 wiz lea FP_SRC(%a6),%a1 # pass: ptr to super dst
12934 1.2.4.2 wiz mov.l &0xc,%d0 # pass: 12 bytes
12935 1.2.4.2 wiz bsr.l _dmem_read # read packed operand
12936 1.2.4.2 wiz
12937 1.2.4.2 wiz tst.l %d1 # did dfetch fail?
12938 1.2.4.2 wiz bne.l facc_in_x # yes
12939 1.2.4.2 wiz
12940 1.2.4.2 wiz # The packed operand is an INF or a NAN if the exponent field is all ones.
12941 1.2.4.2 wiz bfextu FP_SRC(%a6){&1:&15},%d0 # get exp
12942 1.2.4.2 wiz cmpi.w %d0,&0x7fff # INF or NAN?
12943 1.2.4.2 wiz bne.b gp_try_zero # no
12944 1.2.4.2 wiz rts # operand is an INF or NAN
12945 1.2.4.2 wiz
12946 1.2.4.2 wiz # The packed operand is a zero if the mantissa is all zero, else it's
12947 1.2.4.2 wiz # a normal packed op.
12948 1.2.4.2 wiz gp_try_zero:
12949 1.2.4.2 wiz mov.b 3+FP_SRC(%a6),%d0 # get byte 4
12950 1.2.4.2 wiz andi.b &0x0f,%d0 # clear all but last nybble
12951 1.2.4.2 wiz bne.b gp_not_spec # not a zero
12952 1.2.4.2 wiz tst.l FP_SRC_HI(%a6) # is lw 2 zero?
12953 1.2.4.2 wiz bne.b gp_not_spec # not a zero
12954 1.2.4.2 wiz tst.l FP_SRC_LO(%a6) # is lw 3 zero?
12955 1.2.4.2 wiz bne.b gp_not_spec # not a zero
12956 1.2.4.2 wiz rts # operand is a ZERO
12957 1.2.4.2 wiz gp_not_spec:
12958 1.2.4.2 wiz lea FP_SRC(%a6),%a0 # pass: ptr to packed op
12959 1.2.4.2 wiz bsr.l decbin # convert to extended
12960 1.2.4.2 wiz fmovm.x &0x80,FP_SRC(%a6) # make this the srcop
12961 1.2.4.2 wiz rts
12962 1.2.4.2 wiz
12963 1.2.4.2 wiz #########################################################################
12964 1.2.4.2 wiz # decbin(): Converts normalized packed bcd value pointed to by register #
12965 1.2.4.2 wiz # a0 to extended-precision value in fp0. #
12966 1.2.4.2 wiz # #
12967 1.2.4.2 wiz # INPUT *************************************************************** #
12968 1.2.4.2 wiz # a0 = pointer to normalized packed bcd value #
12969 1.2.4.2 wiz # #
12970 1.2.4.2 wiz # OUTPUT ************************************************************** #
12971 1.2.4.2 wiz # fp0 = exact fp representation of the packed bcd value. #
12972 1.2.4.2 wiz # #
12973 1.2.4.2 wiz # ALGORITHM *********************************************************** #
12974 1.2.4.2 wiz # Expected is a normal bcd (i.e. non-exceptional; all inf, zero, #
12975 1.2.4.2 wiz # and NaN operands are dispatched without entering this routine) #
12976 1.2.4.2 wiz # value in 68881/882 format at location (a0). #
12977 1.2.4.2 wiz # #
12978 1.2.4.2 wiz # A1. Convert the bcd exponent to binary by successive adds and #
12979 1.2.4.2 wiz # muls. Set the sign according to SE. Subtract 16 to compensate #
12980 1.2.4.2 wiz # for the mantissa which is to be interpreted as 17 integer #
12981 1.2.4.2 wiz # digits, rather than 1 integer and 16 fraction digits. #
12982 1.2.4.2 wiz # Note: this operation can never overflow. #
12983 1.2.4.2 wiz # #
12984 1.2.4.2 wiz # A2. Convert the bcd mantissa to binary by successive #
12985 1.2.4.2 wiz # adds and muls in FP0. Set the sign according to SM. #
12986 1.2.4.2 wiz # The mantissa digits will be converted with the decimal point #
12987 1.2.4.2 wiz # assumed following the least-significant digit. #
12988 1.2.4.2 wiz # Note: this operation can never overflow. #
12989 1.2.4.2 wiz # #
12990 1.2.4.2 wiz # A3. Count the number of leading/trailing zeros in the #
12991 1.2.4.2 wiz # bcd string. If SE is positive, count the leading zeros; #
12992 1.2.4.2 wiz # if negative, count the trailing zeros. Set the adjusted #
12993 1.2.4.2 wiz # exponent equal to the exponent from A1 and the zero count #
12994 1.2.4.2 wiz # added if SM = 1 and subtracted if SM = 0. Scale the #
12995 1.2.4.2 wiz # mantissa the equivalent of forcing in the bcd value: #
12996 1.2.4.2 wiz # #
12997 1.2.4.2 wiz # SM = 0 a non-zero digit in the integer position #
12998 1.2.4.2 wiz # SM = 1 a non-zero digit in Mant0, lsd of the fraction #
12999 1.2.4.2 wiz # #
13000 1.2.4.2 wiz # this will insure that any value, regardless of its #
13001 1.2.4.2 wiz # representation (ex. 0.1E2, 1E1, 10E0, 100E-1), is converted #
13002 1.2.4.2 wiz # consistently. #
13003 1.2.4.2 wiz # #
13004 1.2.4.2 wiz # A4. Calculate the factor 10^exp in FP1 using a table of #
13005 1.2.4.2 wiz # 10^(2^n) values. To reduce the error in forming factors #
13006 1.2.4.2 wiz # greater than 10^27, a directed rounding scheme is used with #
13007 1.2.4.2 wiz # tables rounded to RN, RM, and RP, according to the table #
13008 1.2.4.2 wiz # in the comments of the pwrten section. #
13009 1.2.4.2 wiz # #
13010 1.2.4.2 wiz # A5. Form the final binary number by scaling the mantissa by #
13011 1.2.4.2 wiz # the exponent factor. This is done by multiplying the #
13012 1.2.4.2 wiz # mantissa in FP0 by the factor in FP1 if the adjusted #
13013 1.2.4.2 wiz # exponent sign is positive, and dividing FP0 by FP1 if #
13014 1.2.4.2 wiz # it is negative. #
13015 1.2.4.2 wiz # #
13016 1.2.4.2 wiz # Clean up and return. Check if the final mul or div was inexact. #
13017 1.2.4.2 wiz # If so, set INEX1 in USER_FPSR. #
13018 1.2.4.2 wiz # #
13019 1.2.4.2 wiz #########################################################################
13020 1.2.4.2 wiz
13021 1.2.4.2 wiz #
13022 1.2.4.2 wiz # PTENRN, PTENRM, and PTENRP are arrays of powers of 10 rounded
13023 1.2.4.2 wiz # to nearest, minus, and plus, respectively. The tables include
13024 1.2.4.2 wiz # 10**{1,2,4,8,16,32,64,128,256,512,1024,2048,4096}. No rounding
13025 1.2.4.2 wiz # is required until the power is greater than 27, however, all
13026 1.2.4.2 wiz # tables include the first 5 for ease of indexing.
13027 1.2.4.2 wiz #
13028 1.2.4.2 wiz RTABLE:
13029 1.2.4.2 wiz byte 0,0,0,0
13030 1.2.4.2 wiz byte 2,3,2,3
13031 1.2.4.2 wiz byte 2,3,3,2
13032 1.2.4.2 wiz byte 3,2,2,3
13033 1.2.4.2 wiz
13034 1.2.4.2 wiz set FNIBS,7
13035 1.2.4.2 wiz set FSTRT,0
13036 1.2.4.2 wiz
13037 1.2.4.2 wiz set ESTRT,4
13038 1.2.4.2 wiz set EDIGITS,2
13039 1.2.4.2 wiz
13040 1.2.4.2 wiz global decbin
13041 1.2.4.2 wiz decbin:
13042 1.2.4.2 wiz mov.l 0x0(%a0),FP_SCR0_EX(%a6) # make a copy of input
13043 1.2.4.2 wiz mov.l 0x4(%a0),FP_SCR0_HI(%a6) # so we don't alter it
13044 1.2.4.2 wiz mov.l 0x8(%a0),FP_SCR0_LO(%a6)
13045 1.2.4.2 wiz
13046 1.2.4.2 wiz lea FP_SCR0(%a6),%a0
13047 1.2.4.2 wiz
13048 1.2.4.2 wiz movm.l &0x3c00,-(%sp) # save d2-d5
13049 1.2.4.2 wiz fmovm.x &0x1,-(%sp) # save fp1
13050 1.2.4.2 wiz #
13051 1.2.4.2 wiz # Calculate exponent:
13052 1.2.4.2 wiz # 1. Copy bcd value in memory for use as a working copy.
13053 1.2.4.2 wiz # 2. Calculate absolute value of exponent in d1 by mul and add.
13054 1.2.4.2 wiz # 3. Correct for exponent sign.
13055 1.2.4.2 wiz # 4. Subtract 16 to compensate for interpreting the mant as all integer digits.
13056 1.2.4.2 wiz # (i.e., all digits assumed left of the decimal point.)
13057 1.2.4.2 wiz #
13058 1.2.4.2 wiz # Register usage:
13059 1.2.4.2 wiz #
13060 1.2.4.2 wiz # calc_e:
13061 1.2.4.2 wiz # (*) d0: temp digit storage
13062 1.2.4.2 wiz # (*) d1: accumulator for binary exponent
13063 1.2.4.2 wiz # (*) d2: digit count
13064 1.2.4.2 wiz # (*) d3: offset pointer
13065 1.2.4.2 wiz # ( ) d4: first word of bcd
13066 1.2.4.2 wiz # ( ) a0: pointer to working bcd value
13067 1.2.4.2 wiz # ( ) a6: pointer to original bcd value
13068 1.2.4.2 wiz # (*) FP_SCR1: working copy of original bcd value
13069 1.2.4.2 wiz # (*) L_SCR1: copy of original exponent word
13070 1.2.4.2 wiz #
13071 1.2.4.2 wiz calc_e:
13072 1.2.4.2 wiz mov.l &EDIGITS,%d2 # # of nibbles (digits) in fraction part
13073 1.2.4.2 wiz mov.l &ESTRT,%d3 # counter to pick up digits
13074 1.2.4.2 wiz mov.l (%a0),%d4 # get first word of bcd
13075 1.2.4.2 wiz clr.l %d1 # zero d1 for accumulator
13076 1.2.4.2 wiz e_gd:
13077 1.2.4.2 wiz mulu.l &0xa,%d1 # mul partial product by one digit place
13078 1.2.4.2 wiz bfextu %d4{%d3:&4},%d0 # get the digit and zero extend into d0
13079 1.2.4.2 wiz add.l %d0,%d1 # d1 = d1 + d0
13080 1.2.4.2 wiz addq.b &4,%d3 # advance d3 to the next digit
13081 1.2.4.2 wiz dbf.w %d2,e_gd # if we have used all 3 digits, exit loop
13082 1.2.4.2 wiz btst &30,%d4 # get SE
13083 1.2.4.2 wiz beq.b e_pos # don't negate if pos
13084 1.2.4.2 wiz neg.l %d1 # negate before subtracting
13085 1.2.4.2 wiz e_pos:
13086 1.2.4.2 wiz sub.l &16,%d1 # sub to compensate for shift of mant
13087 1.2.4.2 wiz bge.b e_save # if still pos, do not neg
13088 1.2.4.2 wiz neg.l %d1 # now negative, make pos and set SE
13089 1.2.4.2 wiz or.l &0x40000000,%d4 # set SE in d4,
13090 1.2.4.2 wiz or.l &0x40000000,(%a0) # and in working bcd
13091 1.2.4.2 wiz e_save:
13092 1.2.4.2 wiz mov.l %d1,-(%sp) # save exp on stack
13093 1.2.4.2 wiz #
13094 1.2.4.2 wiz #
13095 1.2.4.2 wiz # Calculate mantissa:
13096 1.2.4.2 wiz # 1. Calculate absolute value of mantissa in fp0 by mul and add.
13097 1.2.4.2 wiz # 2. Correct for mantissa sign.
13098 1.2.4.2 wiz # (i.e., all digits assumed left of the decimal point.)
13099 1.2.4.2 wiz #
13100 1.2.4.2 wiz # Register usage:
13101 1.2.4.2 wiz #
13102 1.2.4.2 wiz # calc_m:
13103 1.2.4.2 wiz # (*) d0: temp digit storage
13104 1.2.4.2 wiz # (*) d1: lword counter
13105 1.2.4.2 wiz # (*) d2: digit count
13106 1.2.4.2 wiz # (*) d3: offset pointer
13107 1.2.4.2 wiz # ( ) d4: words 2 and 3 of bcd
13108 1.2.4.2 wiz # ( ) a0: pointer to working bcd value
13109 1.2.4.2 wiz # ( ) a6: pointer to original bcd value
13110 1.2.4.2 wiz # (*) fp0: mantissa accumulator
13111 1.2.4.2 wiz # ( ) FP_SCR1: working copy of original bcd value
13112 1.2.4.2 wiz # ( ) L_SCR1: copy of original exponent word
13113 1.2.4.2 wiz #
13114 1.2.4.2 wiz calc_m:
13115 1.2.4.2 wiz mov.l &1,%d1 # word counter, init to 1
13116 1.2.4.2 wiz fmov.s &0x00000000,%fp0 # accumulator
13117 1.2.4.2 wiz #
13118 1.2.4.2 wiz #
13119 1.2.4.2 wiz # Since the packed number has a long word between the first & second parts,
13120 1.2.4.2 wiz # get the integer digit then skip down & get the rest of the
13121 1.2.4.2 wiz # mantissa. We will unroll the loop once.
13122 1.2.4.2 wiz #
13123 1.2.4.2 wiz bfextu (%a0){&28:&4},%d0 # integer part is ls digit in long word
13124 1.2.4.2 wiz fadd.b %d0,%fp0 # add digit to sum in fp0
13125 1.2.4.2 wiz #
13126 1.2.4.2 wiz #
13127 1.2.4.2 wiz # Get the rest of the mantissa.
13128 1.2.4.2 wiz #
13129 1.2.4.2 wiz loadlw:
13130 1.2.4.2 wiz mov.l (%a0,%d1.L*4),%d4 # load mantissa lonqword into d4
13131 1.2.4.2 wiz mov.l &FSTRT,%d3 # counter to pick up digits
13132 1.2.4.2 wiz mov.l &FNIBS,%d2 # reset number of digits per a0 ptr
13133 1.2.4.2 wiz md2b:
13134 1.2.4.2 wiz fmul.s &0x41200000,%fp0 # fp0 = fp0 * 10
13135 1.2.4.2 wiz bfextu %d4{%d3:&4},%d0 # get the digit and zero extend
13136 1.2.4.2 wiz fadd.b %d0,%fp0 # fp0 = fp0 + digit
13137 1.2.4.2 wiz #
13138 1.2.4.2 wiz #
13139 1.2.4.2 wiz # If all the digits (8) in that long word have been converted (d2=0),
13140 1.2.4.2 wiz # then inc d1 (=2) to point to the next long word and reset d3 to 0
13141 1.2.4.2 wiz # to initialize the digit offset, and set d2 to 7 for the digit count;
13142 1.2.4.2 wiz # else continue with this long word.
13143 1.2.4.2 wiz #
13144 1.2.4.2 wiz addq.b &4,%d3 # advance d3 to the next digit
13145 1.2.4.2 wiz dbf.w %d2,md2b # check for last digit in this lw
13146 1.2.4.2 wiz nextlw:
13147 1.2.4.2 wiz addq.l &1,%d1 # inc lw pointer in mantissa
13148 1.2.4.2 wiz cmp.l %d1,&2 # test for last lw
13149 1.2.4.2 wiz ble.b loadlw # if not, get last one
13150 1.2.4.2 wiz #
13151 1.2.4.2 wiz # Check the sign of the mant and make the value in fp0 the same sign.
13152 1.2.4.2 wiz #
13153 1.2.4.2 wiz m_sign:
13154 1.2.4.2 wiz btst &31,(%a0) # test sign of the mantissa
13155 1.2.4.2 wiz beq.b ap_st_z # if clear, go to append/strip zeros
13156 1.2.4.2 wiz fneg.x %fp0 # if set, negate fp0
13157 1.2.4.2 wiz #
13158 1.2.4.2 wiz # Append/strip zeros:
13159 1.2.4.2 wiz #
13160 1.2.4.2 wiz # For adjusted exponents which have an absolute value greater than 27*,
13161 1.2.4.2 wiz # this routine calculates the amount needed to normalize the mantissa
13162 1.2.4.2 wiz # for the adjusted exponent. That number is subtracted from the exp
13163 1.2.4.2 wiz # if the exp was positive, and added if it was negative. The purpose
13164 1.2.4.2 wiz # of this is to reduce the value of the exponent and the possibility
13165 1.2.4.2 wiz # of error in calculation of pwrten.
13166 1.2.4.2 wiz #
13167 1.2.4.2 wiz # 1. Branch on the sign of the adjusted exponent.
13168 1.2.4.2 wiz # 2p.(positive exp)
13169 1.2.4.2 wiz # 2. Check M16 and the digits in lwords 2 and 3 in decending order.
13170 1.2.4.2 wiz # 3. Add one for each zero encountered until a non-zero digit.
13171 1.2.4.2 wiz # 4. Subtract the count from the exp.
13172 1.2.4.2 wiz # 5. Check if the exp has crossed zero in #3 above; make the exp abs
13173 1.2.4.2 wiz # and set SE.
13174 1.2.4.2 wiz # 6. Multiply the mantissa by 10**count.
13175 1.2.4.2 wiz # 2n.(negative exp)
13176 1.2.4.2 wiz # 2. Check the digits in lwords 3 and 2 in decending order.
13177 1.2.4.2 wiz # 3. Add one for each zero encountered until a non-zero digit.
13178 1.2.4.2 wiz # 4. Add the count to the exp.
13179 1.2.4.2 wiz # 5. Check if the exp has crossed zero in #3 above; clear SE.
13180 1.2.4.2 wiz # 6. Divide the mantissa by 10**count.
13181 1.2.4.2 wiz #
13182 1.2.4.2 wiz # *Why 27? If the adjusted exponent is within -28 < expA < 28, than
13183 1.2.4.2 wiz # any adjustment due to append/strip zeros will drive the resultane
13184 1.2.4.2 wiz # exponent towards zero. Since all pwrten constants with a power
13185 1.2.4.2 wiz # of 27 or less are exact, there is no need to use this routine to
13186 1.2.4.2 wiz # attempt to lessen the resultant exponent.
13187 1.2.4.2 wiz #
13188 1.2.4.2 wiz # Register usage:
13189 1.2.4.2 wiz #
13190 1.2.4.2 wiz # ap_st_z:
13191 1.2.4.2 wiz # (*) d0: temp digit storage
13192 1.2.4.2 wiz # (*) d1: zero count
13193 1.2.4.2 wiz # (*) d2: digit count
13194 1.2.4.2 wiz # (*) d3: offset pointer
13195 1.2.4.2 wiz # ( ) d4: first word of bcd
13196 1.2.4.2 wiz # (*) d5: lword counter
13197 1.2.4.2 wiz # ( ) a0: pointer to working bcd value
13198 1.2.4.2 wiz # ( ) FP_SCR1: working copy of original bcd value
13199 1.2.4.2 wiz # ( ) L_SCR1: copy of original exponent word
13200 1.2.4.2 wiz #
13201 1.2.4.2 wiz #
13202 1.2.4.2 wiz # First check the absolute value of the exponent to see if this
13203 1.2.4.2 wiz # routine is necessary. If so, then check the sign of the exponent
13204 1.2.4.2 wiz # and do append (+) or strip (-) zeros accordingly.
13205 1.2.4.2 wiz # This section handles a positive adjusted exponent.
13206 1.2.4.2 wiz #
13207 1.2.4.2 wiz ap_st_z:
13208 1.2.4.2 wiz mov.l (%sp),%d1 # load expA for range test
13209 1.2.4.2 wiz cmp.l %d1,&27 # test is with 27
13210 1.2.4.2 wiz ble.w pwrten # if abs(expA) <28, skip ap/st zeros
13211 1.2.4.2 wiz btst &30,(%a0) # check sign of exp
13212 1.2.4.2 wiz bne.b ap_st_n # if neg, go to neg side
13213 1.2.4.2 wiz clr.l %d1 # zero count reg
13214 1.2.4.2 wiz mov.l (%a0),%d4 # load lword 1 to d4
13215 1.2.4.2 wiz bfextu %d4{&28:&4},%d0 # get M16 in d0
13216 1.2.4.2 wiz bne.b ap_p_fx # if M16 is non-zero, go fix exp
13217 1.2.4.2 wiz addq.l &1,%d1 # inc zero count
13218 1.2.4.2 wiz mov.l &1,%d5 # init lword counter
13219 1.2.4.2 wiz mov.l (%a0,%d5.L*4),%d4 # get lword 2 to d4
13220 1.2.4.2 wiz bne.b ap_p_cl # if lw 2 is zero, skip it
13221 1.2.4.2 wiz addq.l &8,%d1 # and inc count by 8
13222 1.2.4.2 wiz addq.l &1,%d5 # inc lword counter
13223 1.2.4.2 wiz mov.l (%a0,%d5.L*4),%d4 # get lword 3 to d4
13224 1.2.4.2 wiz ap_p_cl:
13225 1.2.4.2 wiz clr.l %d3 # init offset reg
13226 1.2.4.2 wiz mov.l &7,%d2 # init digit counter
13227 1.2.4.2 wiz ap_p_gd:
13228 1.2.4.2 wiz bfextu %d4{%d3:&4},%d0 # get digit
13229 1.2.4.2 wiz bne.b ap_p_fx # if non-zero, go to fix exp
13230 1.2.4.2 wiz addq.l &4,%d3 # point to next digit
13231 1.2.4.2 wiz addq.l &1,%d1 # inc digit counter
13232 1.2.4.2 wiz dbf.w %d2,ap_p_gd # get next digit
13233 1.2.4.2 wiz ap_p_fx:
13234 1.2.4.2 wiz mov.l %d1,%d0 # copy counter to d2
13235 1.2.4.2 wiz mov.l (%sp),%d1 # get adjusted exp from memory
13236 1.2.4.2 wiz sub.l %d0,%d1 # subtract count from exp
13237 1.2.4.2 wiz bge.b ap_p_fm # if still pos, go to pwrten
13238 1.2.4.2 wiz neg.l %d1 # now its neg; get abs
13239 1.2.4.2 wiz mov.l (%a0),%d4 # load lword 1 to d4
13240 1.2.4.2 wiz or.l &0x40000000,%d4 # and set SE in d4
13241 1.2.4.2 wiz or.l &0x40000000,(%a0) # and in memory
13242 1.2.4.2 wiz #
13243 1.2.4.2 wiz # Calculate the mantissa multiplier to compensate for the striping of
13244 1.2.4.2 wiz # zeros from the mantissa.
13245 1.2.4.2 wiz #
13246 1.2.4.2 wiz ap_p_fm:
13247 1.2.4.2 wiz lea.l PTENRN(%pc),%a1 # get address of power-of-ten table
13248 1.2.4.2 wiz clr.l %d3 # init table index
13249 1.2.4.2 wiz fmov.s &0x3f800000,%fp1 # init fp1 to 1
13250 1.2.4.2 wiz mov.l &3,%d2 # init d2 to count bits in counter
13251 1.2.4.2 wiz ap_p_el:
13252 1.2.4.2 wiz asr.l &1,%d0 # shift lsb into carry
13253 1.2.4.2 wiz bcc.b ap_p_en # if 1, mul fp1 by pwrten factor
13254 1.2.4.2 wiz fmul.x (%a1,%d3),%fp1 # mul by 10**(d3_bit_no)
13255 1.2.4.2 wiz ap_p_en:
13256 1.2.4.2 wiz add.l &12,%d3 # inc d3 to next rtable entry
13257 1.2.4.2 wiz tst.l %d0 # check if d0 is zero
13258 1.2.4.2 wiz bne.b ap_p_el # if not, get next bit
13259 1.2.4.2 wiz fmul.x %fp1,%fp0 # mul mantissa by 10**(no_bits_shifted)
13260 1.2.4.2 wiz bra.b pwrten # go calc pwrten
13261 1.2.4.2 wiz #
13262 1.2.4.2 wiz # This section handles a negative adjusted exponent.
13263 1.2.4.2 wiz #
13264 1.2.4.2 wiz ap_st_n:
13265 1.2.4.2 wiz clr.l %d1 # clr counter
13266 1.2.4.2 wiz mov.l &2,%d5 # set up d5 to point to lword 3
13267 1.2.4.2 wiz mov.l (%a0,%d5.L*4),%d4 # get lword 3
13268 1.2.4.2 wiz bne.b ap_n_cl # if not zero, check digits
13269 1.2.4.2 wiz sub.l &1,%d5 # dec d5 to point to lword 2
13270 1.2.4.2 wiz addq.l &8,%d1 # inc counter by 8
13271 1.2.4.2 wiz mov.l (%a0,%d5.L*4),%d4 # get lword 2
13272 1.2.4.2 wiz ap_n_cl:
13273 1.2.4.2 wiz mov.l &28,%d3 # point to last digit
13274 1.2.4.2 wiz mov.l &7,%d2 # init digit counter
13275 1.2.4.2 wiz ap_n_gd:
13276 1.2.4.2 wiz bfextu %d4{%d3:&4},%d0 # get digit
13277 1.2.4.2 wiz bne.b ap_n_fx # if non-zero, go to exp fix
13278 1.2.4.2 wiz subq.l &4,%d3 # point to previous digit
13279 1.2.4.2 wiz addq.l &1,%d1 # inc digit counter
13280 1.2.4.2 wiz dbf.w %d2,ap_n_gd # get next digit
13281 1.2.4.2 wiz ap_n_fx:
13282 1.2.4.2 wiz mov.l %d1,%d0 # copy counter to d0
13283 1.2.4.2 wiz mov.l (%sp),%d1 # get adjusted exp from memory
13284 1.2.4.2 wiz sub.l %d0,%d1 # subtract count from exp
13285 1.2.4.2 wiz bgt.b ap_n_fm # if still pos, go fix mantissa
13286 1.2.4.2 wiz neg.l %d1 # take abs of exp and clr SE
13287 1.2.4.2 wiz mov.l (%a0),%d4 # load lword 1 to d4
13288 1.2.4.2 wiz and.l &0xbfffffff,%d4 # and clr SE in d4
13289 1.2.4.2 wiz and.l &0xbfffffff,(%a0) # and in memory
13290 1.2.4.2 wiz #
13291 1.2.4.2 wiz # Calculate the mantissa multiplier to compensate for the appending of
13292 1.2.4.2 wiz # zeros to the mantissa.
13293 1.2.4.2 wiz #
13294 1.2.4.2 wiz ap_n_fm:
13295 1.2.4.2 wiz lea.l PTENRN(%pc),%a1 # get address of power-of-ten table
13296 1.2.4.2 wiz clr.l %d3 # init table index
13297 1.2.4.2 wiz fmov.s &0x3f800000,%fp1 # init fp1 to 1
13298 1.2.4.2 wiz mov.l &3,%d2 # init d2 to count bits in counter
13299 1.2.4.2 wiz ap_n_el:
13300 1.2.4.2 wiz asr.l &1,%d0 # shift lsb into carry
13301 1.2.4.2 wiz bcc.b ap_n_en # if 1, mul fp1 by pwrten factor
13302 1.2.4.2 wiz fmul.x (%a1,%d3),%fp1 # mul by 10**(d3_bit_no)
13303 1.2.4.2 wiz ap_n_en:
13304 1.2.4.2 wiz add.l &12,%d3 # inc d3 to next rtable entry
13305 1.2.4.2 wiz tst.l %d0 # check if d0 is zero
13306 1.2.4.2 wiz bne.b ap_n_el # if not, get next bit
13307 1.2.4.2 wiz fdiv.x %fp1,%fp0 # div mantissa by 10**(no_bits_shifted)
13308 1.2.4.2 wiz #
13309 1.2.4.2 wiz #
13310 1.2.4.2 wiz # Calculate power-of-ten factor from adjusted and shifted exponent.
13311 1.2.4.2 wiz #
13312 1.2.4.2 wiz # Register usage:
13313 1.2.4.2 wiz #
13314 1.2.4.2 wiz # pwrten:
13315 1.2.4.2 wiz # (*) d0: temp
13316 1.2.4.2 wiz # ( ) d1: exponent
13317 1.2.4.2 wiz # (*) d2: {FPCR[6:5],SM,SE} as index in RTABLE; temp
13318 1.2.4.2 wiz # (*) d3: FPCR work copy
13319 1.2.4.2 wiz # ( ) d4: first word of bcd
13320 1.2.4.2 wiz # (*) a1: RTABLE pointer
13321 1.2.4.2 wiz # calc_p:
13322 1.2.4.2 wiz # (*) d0: temp
13323 1.2.4.2 wiz # ( ) d1: exponent
13324 1.2.4.2 wiz # (*) d3: PWRTxx table index
13325 1.2.4.2 wiz # ( ) a0: pointer to working copy of bcd
13326 1.2.4.2 wiz # (*) a1: PWRTxx pointer
13327 1.2.4.2 wiz # (*) fp1: power-of-ten accumulator
13328 1.2.4.2 wiz #
13329 1.2.4.2 wiz # Pwrten calculates the exponent factor in the selected rounding mode
13330 1.2.4.2 wiz # according to the following table:
13331 1.2.4.2 wiz #
13332 1.2.4.2 wiz # Sign of Mant Sign of Exp Rounding Mode PWRTEN Rounding Mode
13333 1.2.4.2 wiz #
13334 1.2.4.2 wiz # ANY ANY RN RN
13335 1.2.4.2 wiz #
13336 1.2.4.2 wiz # + + RP RP
13337 1.2.4.2 wiz # - + RP RM
13338 1.2.4.2 wiz # + - RP RM
13339 1.2.4.2 wiz # - - RP RP
13340 1.2.4.2 wiz #
13341 1.2.4.2 wiz # + + RM RM
13342 1.2.4.2 wiz # - + RM RP
13343 1.2.4.2 wiz # + - RM RP
13344 1.2.4.2 wiz # - - RM RM
13345 1.2.4.2 wiz #
13346 1.2.4.2 wiz # + + RZ RM
13347 1.2.4.2 wiz # - + RZ RM
13348 1.2.4.2 wiz # + - RZ RP
13349 1.2.4.2 wiz # - - RZ RP
13350 1.2.4.2 wiz #
13351 1.2.4.2 wiz #
13352 1.2.4.2 wiz pwrten:
13353 1.2.4.2 wiz mov.l USER_FPCR(%a6),%d3 # get user's FPCR
13354 1.2.4.2 wiz bfextu %d3{&26:&2},%d2 # isolate rounding mode bits
13355 1.2.4.2 wiz mov.l (%a0),%d4 # reload 1st bcd word to d4
13356 1.2.4.2 wiz asl.l &2,%d2 # format d2 to be
13357 1.2.4.2 wiz bfextu %d4{&0:&2},%d0 # {FPCR[6],FPCR[5],SM,SE}
13358 1.2.4.2 wiz add.l %d0,%d2 # in d2 as index into RTABLE
13359 1.2.4.2 wiz lea.l RTABLE(%pc),%a1 # load rtable base
13360 1.2.4.2 wiz mov.b (%a1,%d2),%d0 # load new rounding bits from table
13361 1.2.4.2 wiz clr.l %d3 # clear d3 to force no exc and extended
13362 1.2.4.2 wiz bfins %d0,%d3{&26:&2} # stuff new rounding bits in FPCR
13363 1.2.4.2 wiz fmov.l %d3,%fpcr # write new FPCR
13364 1.2.4.2 wiz asr.l &1,%d0 # write correct PTENxx table
13365 1.2.4.2 wiz bcc.b not_rp # to a1
13366 1.2.4.2 wiz lea.l PTENRP(%pc),%a1 # it is RP
13367 1.2.4.2 wiz bra.b calc_p # go to init section
13368 1.2.4.2 wiz not_rp:
13369 1.2.4.2 wiz asr.l &1,%d0 # keep checking
13370 1.2.4.2 wiz bcc.b not_rm
13371 1.2.4.2 wiz lea.l PTENRM(%pc),%a1 # it is RM
13372 1.2.4.2 wiz bra.b calc_p # go to init section
13373 1.2.4.2 wiz not_rm:
13374 1.2.4.2 wiz lea.l PTENRN(%pc),%a1 # it is RN
13375 1.2.4.2 wiz calc_p:
13376 1.2.4.2 wiz mov.l %d1,%d0 # copy exp to d0;use d0
13377 1.2.4.2 wiz bpl.b no_neg # if exp is negative,
13378 1.2.4.2 wiz neg.l %d0 # invert it
13379 1.2.4.2 wiz or.l &0x40000000,(%a0) # and set SE bit
13380 1.2.4.2 wiz no_neg:
13381 1.2.4.2 wiz clr.l %d3 # table index
13382 1.2.4.2 wiz fmov.s &0x3f800000,%fp1 # init fp1 to 1
13383 1.2.4.2 wiz e_loop:
13384 1.2.4.2 wiz asr.l &1,%d0 # shift next bit into carry
13385 1.2.4.2 wiz bcc.b e_next # if zero, skip the mul
13386 1.2.4.2 wiz fmul.x (%a1,%d3),%fp1 # mul by 10**(d3_bit_no)
13387 1.2.4.2 wiz e_next:
13388 1.2.4.2 wiz add.l &12,%d3 # inc d3 to next rtable entry
13389 1.2.4.2 wiz tst.l %d0 # check if d0 is zero
13390 1.2.4.2 wiz bne.b e_loop # not zero, continue shifting
13391 1.2.4.2 wiz #
13392 1.2.4.2 wiz #
13393 1.2.4.2 wiz # Check the sign of the adjusted exp and make the value in fp0 the
13394 1.2.4.2 wiz # same sign. If the exp was pos then multiply fp1*fp0;
13395 1.2.4.2 wiz # else divide fp0/fp1.
13396 1.2.4.2 wiz #
13397 1.2.4.2 wiz # Register Usage:
13398 1.2.4.2 wiz # norm:
13399 1.2.4.2 wiz # ( ) a0: pointer to working bcd value
13400 1.2.4.2 wiz # (*) fp0: mantissa accumulator
13401 1.2.4.2 wiz # ( ) fp1: scaling factor - 10**(abs(exp))
13402 1.2.4.2 wiz #
13403 1.2.4.2 wiz pnorm:
13404 1.2.4.2 wiz btst &30,(%a0) # test the sign of the exponent
13405 1.2.4.2 wiz beq.b mul # if clear, go to multiply
13406 1.2.4.2 wiz div:
13407 1.2.4.2 wiz fdiv.x %fp1,%fp0 # exp is negative, so divide mant by exp
13408 1.2.4.2 wiz bra.b end_dec
13409 1.2.4.2 wiz mul:
13410 1.2.4.2 wiz fmul.x %fp1,%fp0 # exp is positive, so multiply by exp
13411 1.2.4.2 wiz #
13412 1.2.4.2 wiz #
13413 1.2.4.2 wiz # Clean up and return with result in fp0.
13414 1.2.4.2 wiz #
13415 1.2.4.2 wiz # If the final mul/div in decbin incurred an inex exception,
13416 1.2.4.2 wiz # it will be inex2, but will be reported as inex1 by get_op.
13417 1.2.4.2 wiz #
13418 1.2.4.2 wiz end_dec:
13419 1.2.4.2 wiz fmov.l %fpsr,%d0 # get status register
13420 1.2.4.2 wiz bclr &inex2_bit+8,%d0 # test for inex2 and clear it
13421 1.2.4.2 wiz beq.b no_exc # skip this if no exc
13422 1.2.4.2 wiz ori.w &inx1a_mask,2+USER_FPSR(%a6) # set INEX1/AINEX
13423 1.2.4.2 wiz no_exc:
13424 1.2.4.2 wiz add.l &0x4,%sp # clear 1 lw param
13425 1.2.4.2 wiz fmovm.x (%sp)+,&0x40 # restore fp1
13426 1.2.4.2 wiz movm.l (%sp)+,&0x3c # restore d2-d5
13427 1.2.4.2 wiz fmov.l &0x0,%fpcr
13428 1.2.4.2 wiz fmov.l &0x0,%fpsr
13429 1.2.4.2 wiz rts
13430 1.2.4.2 wiz
13431 1.2.4.2 wiz #########################################################################
13432 1.2.4.2 wiz # bindec(): Converts an input in extended precision format to bcd format#
13433 1.2.4.2 wiz # #
13434 1.2.4.2 wiz # INPUT *************************************************************** #
13435 1.2.4.2 wiz # a0 = pointer to the input extended precision value in memory. #
13436 1.2.4.2 wiz # the input may be either normalized, unnormalized, or #
13437 1.2.4.2 wiz # denormalized. #
13438 1.2.4.2 wiz # d0 = contains the k-factor sign-extended to 32-bits. #
13439 1.2.4.2 wiz # #
13440 1.2.4.2 wiz # OUTPUT ************************************************************** #
13441 1.2.4.2 wiz # FP_SCR0(a6) = bcd format result on the stack. #
13442 1.2.4.2 wiz # #
13443 1.2.4.2 wiz # ALGORITHM *********************************************************** #
13444 1.2.4.2 wiz # #
13445 1.2.4.2 wiz # A1. Set RM and size ext; Set SIGMA = sign of input. #
13446 1.2.4.2 wiz # The k-factor is saved for use in d7. Clear the #
13447 1.2.4.2 wiz # BINDEC_FLG for separating normalized/denormalized #
13448 1.2.4.2 wiz # input. If input is unnormalized or denormalized, #
13449 1.2.4.2 wiz # normalize it. #
13450 1.2.4.2 wiz # #
13451 1.2.4.2 wiz # A2. Set X = abs(input). #
13452 1.2.4.2 wiz # #
13453 1.2.4.2 wiz # A3. Compute ILOG. #
13454 1.2.4.2 wiz # ILOG is the log base 10 of the input value. It is #
13455 1.2.4.2 wiz # approximated by adding e + 0.f when the original #
13456 1.2.4.2 wiz # value is viewed as 2^^e * 1.f in extended precision. #
13457 1.2.4.2 wiz # This value is stored in d6. #
13458 1.2.4.2 wiz # #
13459 1.2.4.2 wiz # A4. Clr INEX bit. #
13460 1.2.4.2 wiz # The operation in A3 above may have set INEX2. #
13461 1.2.4.2 wiz # #
13462 1.2.4.2 wiz # A5. Set ICTR = 0; #
13463 1.2.4.2 wiz # ICTR is a flag used in A13. It must be set before the #
13464 1.2.4.2 wiz # loop entry A6. #
13465 1.2.4.2 wiz # #
13466 1.2.4.2 wiz # A6. Calculate LEN. #
13467 1.2.4.2 wiz # LEN is the number of digits to be displayed. The #
13468 1.2.4.2 wiz # k-factor can dictate either the total number of digits, #
13469 1.2.4.2 wiz # if it is a positive number, or the number of digits #
13470 1.2.4.2 wiz # after the decimal point which are to be included as #
13471 1.2.4.2 wiz # significant. See the 68882 manual for examples. #
13472 1.2.4.2 wiz # If LEN is computed to be greater than 17, set OPERR in #
13473 1.2.4.2 wiz # USER_FPSR. LEN is stored in d4. #
13474 1.2.4.2 wiz # #
13475 1.2.4.2 wiz # A7. Calculate SCALE. #
13476 1.2.4.2 wiz # SCALE is equal to 10^ISCALE, where ISCALE is the number #
13477 1.2.4.2 wiz # of decimal places needed to insure LEN integer digits #
13478 1.2.4.2 wiz # in the output before conversion to bcd. LAMBDA is the #
13479 1.2.4.2 wiz # sign of ISCALE, used in A9. Fp1 contains #
13480 1.2.4.2 wiz # 10^^(abs(ISCALE)) using a rounding mode which is a #
13481 1.2.4.2 wiz # function of the original rounding mode and the signs #
13482 1.2.4.2 wiz # of ISCALE and X. A table is given in the code. #
13483 1.2.4.2 wiz # #
13484 1.2.4.2 wiz # A8. Clr INEX; Force RZ. #
13485 1.2.4.2 wiz # The operation in A3 above may have set INEX2. #
13486 1.2.4.2 wiz # RZ mode is forced for the scaling operation to insure #
13487 1.2.4.2 wiz # only one rounding error. The grs bits are collected in #
13488 1.2.4.2 wiz # the INEX flag for use in A10. #
13489 1.2.4.2 wiz # #
13490 1.2.4.2 wiz # A9. Scale X -> Y. #
13491 1.2.4.2 wiz # The mantissa is scaled to the desired number of #
13492 1.2.4.2 wiz # significant digits. The excess digits are collected #
13493 1.2.4.2 wiz # in INEX2. #
13494 1.2.4.2 wiz # #
13495 1.2.4.2 wiz # A10. Or in INEX. #
13496 1.2.4.2 wiz # If INEX is set, round error occurred. This is #
13497 1.2.4.2 wiz # compensated for by 'or-ing' in the INEX2 flag to #
13498 1.2.4.2 wiz # the lsb of Y. #
13499 1.2.4.2 wiz # #
13500 1.2.4.2 wiz # A11. Restore original FPCR; set size ext. #
13501 1.2.4.2 wiz # Perform FINT operation in the user's rounding mode. #
13502 1.2.4.2 wiz # Keep the size to extended. #
13503 1.2.4.2 wiz # #
13504 1.2.4.2 wiz # A12. Calculate YINT = FINT(Y) according to user's rounding #
13505 1.2.4.2 wiz # mode. The FPSP routine sintd0 is used. The output #
13506 1.2.4.2 wiz # is in fp0. #
13507 1.2.4.2 wiz # #
13508 1.2.4.2 wiz # A13. Check for LEN digits. #
13509 1.2.4.2 wiz # If the int operation results in more than LEN digits, #
13510 1.2.4.2 wiz # or less than LEN -1 digits, adjust ILOG and repeat from #
13511 1.2.4.2 wiz # A6. This test occurs only on the first pass. If the #
13512 1.2.4.2 wiz # result is exactly 10^LEN, decrement ILOG and divide #
13513 1.2.4.2 wiz # the mantissa by 10. #
13514 1.2.4.2 wiz # #
13515 1.2.4.2 wiz # A14. Convert the mantissa to bcd. #
13516 1.2.4.2 wiz # The binstr routine is used to convert the LEN digit #
13517 1.2.4.2 wiz # mantissa to bcd in memory. The input to binstr is #
13518 1.2.4.2 wiz # to be a fraction; i.e. (mantissa)/10^LEN and adjusted #
13519 1.2.4.2 wiz # such that the decimal point is to the left of bit 63. #
13520 1.2.4.2 wiz # The bcd digits are stored in the correct position in #
13521 1.2.4.2 wiz # the final string area in memory. #
13522 1.2.4.2 wiz # #
13523 1.2.4.2 wiz # A15. Convert the exponent to bcd. #
13524 1.2.4.2 wiz # As in A14 above, the exp is converted to bcd and the #
13525 1.2.4.2 wiz # digits are stored in the final string. #
13526 1.2.4.2 wiz # Test the length of the final exponent string. If the #
13527 1.2.4.2 wiz # length is 4, set operr. #
13528 1.2.4.2 wiz # #
13529 1.2.4.2 wiz # A16. Write sign bits to final string. #
13530 1.2.4.2 wiz # #
13531 1.2.4.2 wiz #########################################################################
13532 1.2.4.2 wiz
13533 1.2.4.2 wiz set BINDEC_FLG, EXC_TEMP # DENORM flag
13534 1.2.4.2 wiz
13535 1.2.4.2 wiz # Constants in extended precision
13536 1.2.4.2 wiz PLOG2:
13537 1.2.4.2 wiz long 0x3FFD0000,0x9A209A84,0xFBCFF798,0x00000000
13538 1.2.4.2 wiz PLOG2UP1:
13539 1.2.4.2 wiz long 0x3FFD0000,0x9A209A84,0xFBCFF799,0x00000000
13540 1.2.4.2 wiz
13541 1.2.4.2 wiz # Constants in single precision
13542 1.2.4.2 wiz FONE:
13543 1.2.4.2 wiz long 0x3F800000,0x00000000,0x00000000,0x00000000
13544 1.2.4.2 wiz FTWO:
13545 1.2.4.2 wiz long 0x40000000,0x00000000,0x00000000,0x00000000
13546 1.2.4.2 wiz FTEN:
13547 1.2.4.2 wiz long 0x41200000,0x00000000,0x00000000,0x00000000
13548 1.2.4.2 wiz F4933:
13549 1.2.4.2 wiz long 0x459A2800,0x00000000,0x00000000,0x00000000
13550 1.2.4.2 wiz
13551 1.2.4.2 wiz RBDTBL:
13552 1.2.4.2 wiz byte 0,0,0,0
13553 1.2.4.2 wiz byte 3,3,2,2
13554 1.2.4.2 wiz byte 3,2,2,3
13555 1.2.4.2 wiz byte 2,3,3,2
13556 1.2.4.2 wiz
13557 1.2.4.2 wiz # Implementation Notes:
13558 1.2.4.2 wiz #
13559 1.2.4.2 wiz # The registers are used as follows:
13560 1.2.4.2 wiz #
13561 1.2.4.2 wiz # d0: scratch; LEN input to binstr
13562 1.2.4.2 wiz # d1: scratch
13563 1.2.4.2 wiz # d2: upper 32-bits of mantissa for binstr
13564 1.2.4.2 wiz # d3: scratch;lower 32-bits of mantissa for binstr
13565 1.2.4.2 wiz # d4: LEN
13566 1.2.4.2 wiz # d5: LAMBDA/ICTR
13567 1.2.4.2 wiz # d6: ILOG
13568 1.2.4.2 wiz # d7: k-factor
13569 1.2.4.2 wiz # a0: ptr for original operand/final result
13570 1.2.4.2 wiz # a1: scratch pointer
13571 1.2.4.2 wiz # a2: pointer to FP_X; abs(original value) in ext
13572 1.2.4.2 wiz # fp0: scratch
13573 1.2.4.2 wiz # fp1: scratch
13574 1.2.4.2 wiz # fp2: scratch
13575 1.2.4.2 wiz # F_SCR1:
13576 1.2.4.2 wiz # F_SCR2:
13577 1.2.4.2 wiz # L_SCR1:
13578 1.2.4.2 wiz # L_SCR2:
13579 1.2.4.2 wiz
13580 1.2.4.2 wiz global bindec
13581 1.2.4.2 wiz bindec:
13582 1.2.4.2 wiz movm.l &0x3f20,-(%sp) # {%d2-%d7/%a2}
13583 1.2.4.2 wiz fmovm.x &0x7,-(%sp) # {%fp0-%fp2}
13584 1.2.4.2 wiz
13585 1.2.4.2 wiz # A1. Set RM and size ext. Set SIGMA = sign input;
13586 1.2.4.2 wiz # The k-factor is saved for use in d7. Clear BINDEC_FLG for
13587 1.2.4.2 wiz # separating normalized/denormalized input. If the input
13588 1.2.4.2 wiz # is a denormalized number, set the BINDEC_FLG memory word
13589 1.2.4.2 wiz # to signal denorm. If the input is unnormalized, normalize
13590 1.2.4.2 wiz # the input and test for denormalized result.
13591 1.2.4.2 wiz #
13592 1.2.4.2 wiz fmov.l &rm_mode*0x10,%fpcr # set RM and ext
13593 1.2.4.2 wiz mov.l (%a0),L_SCR2(%a6) # save exponent for sign check
13594 1.2.4.2 wiz mov.l %d0,%d7 # move k-factor to d7
13595 1.2.4.2 wiz
13596 1.2.4.2 wiz clr.b BINDEC_FLG(%a6) # clr norm/denorm flag
13597 1.2.4.2 wiz cmpi.b STAG(%a6),&DENORM # is input a DENORM?
13598 1.2.4.2 wiz bne.w A2_str # no; input is a NORM
13599 1.2.4.2 wiz
13600 1.2.4.2 wiz #
13601 1.2.4.2 wiz # Normalize the denorm
13602 1.2.4.2 wiz #
13603 1.2.4.2 wiz un_de_norm:
13604 1.2.4.2 wiz mov.w (%a0),%d0
13605 1.2.4.2 wiz and.w &0x7fff,%d0 # strip sign of normalized exp
13606 1.2.4.2 wiz mov.l 4(%a0),%d1
13607 1.2.4.2 wiz mov.l 8(%a0),%d2
13608 1.2.4.2 wiz norm_loop:
13609 1.2.4.2 wiz sub.w &1,%d0
13610 1.2.4.2 wiz lsl.l &1,%d2
13611 1.2.4.2 wiz roxl.l &1,%d1
13612 1.2.4.2 wiz tst.l %d1
13613 1.2.4.2 wiz bge.b norm_loop
13614 1.2.4.2 wiz #
13615 1.2.4.2 wiz # Test if the normalized input is denormalized
13616 1.2.4.2 wiz #
13617 1.2.4.2 wiz tst.w %d0
13618 1.2.4.2 wiz bgt.b pos_exp # if greater than zero, it is a norm
13619 1.2.4.2 wiz st BINDEC_FLG(%a6) # set flag for denorm
13620 1.2.4.2 wiz pos_exp:
13621 1.2.4.2 wiz and.w &0x7fff,%d0 # strip sign of normalized exp
13622 1.2.4.2 wiz mov.w %d0,(%a0)
13623 1.2.4.2 wiz mov.l %d1,4(%a0)
13624 1.2.4.2 wiz mov.l %d2,8(%a0)
13625 1.2.4.2 wiz
13626 1.2.4.2 wiz # A2. Set X = abs(input).
13627 1.2.4.2 wiz #
13628 1.2.4.2 wiz A2_str:
13629 1.2.4.2 wiz mov.l (%a0),FP_SCR1(%a6) # move input to work space
13630 1.2.4.2 wiz mov.l 4(%a0),FP_SCR1+4(%a6) # move input to work space
13631 1.2.4.2 wiz mov.l 8(%a0),FP_SCR1+8(%a6) # move input to work space
13632 1.2.4.2 wiz and.l &0x7fffffff,FP_SCR1(%a6) # create abs(X)
13633 1.2.4.2 wiz
13634 1.2.4.2 wiz # A3. Compute ILOG.
13635 1.2.4.2 wiz # ILOG is the log base 10 of the input value. It is approx-
13636 1.2.4.2 wiz # imated by adding e + 0.f when the original value is viewed
13637 1.2.4.2 wiz # as 2^^e * 1.f in extended precision. This value is stored
13638 1.2.4.2 wiz # in d6.
13639 1.2.4.2 wiz #
13640 1.2.4.2 wiz # Register usage:
13641 1.2.4.2 wiz # Input/Output
13642 1.2.4.2 wiz # d0: k-factor/exponent
13643 1.2.4.2 wiz # d2: x/x
13644 1.2.4.2 wiz # d3: x/x
13645 1.2.4.2 wiz # d4: x/x
13646 1.2.4.2 wiz # d5: x/x
13647 1.2.4.2 wiz # d6: x/ILOG
13648 1.2.4.2 wiz # d7: k-factor/Unchanged
13649 1.2.4.2 wiz # a0: ptr for original operand/final result
13650 1.2.4.2 wiz # a1: x/x
13651 1.2.4.2 wiz # a2: x/x
13652 1.2.4.2 wiz # fp0: x/float(ILOG)
13653 1.2.4.2 wiz # fp1: x/x
13654 1.2.4.2 wiz # fp2: x/x
13655 1.2.4.2 wiz # F_SCR1:x/x
13656 1.2.4.2 wiz # F_SCR2:Abs(X)/Abs(X) with $3fff exponent
13657 1.2.4.2 wiz # L_SCR1:x/x
13658 1.2.4.2 wiz # L_SCR2:first word of X packed/Unchanged
13659 1.2.4.2 wiz
13660 1.2.4.2 wiz tst.b BINDEC_FLG(%a6) # check for denorm
13661 1.2.4.2 wiz beq.b A3_cont # if clr, continue with norm
13662 1.2.4.2 wiz mov.l &-4933,%d6 # force ILOG = -4933
13663 1.2.4.2 wiz bra.b A4_str
13664 1.2.4.2 wiz A3_cont:
13665 1.2.4.2 wiz mov.w FP_SCR1(%a6),%d0 # move exp to d0
13666 1.2.4.2 wiz mov.w &0x3fff,FP_SCR1(%a6) # replace exponent with 0x3fff
13667 1.2.4.2 wiz fmov.x FP_SCR1(%a6),%fp0 # now fp0 has 1.f
13668 1.2.4.2 wiz sub.w &0x3fff,%d0 # strip off bias
13669 1.2.4.2 wiz fadd.w %d0,%fp0 # add in exp
13670 1.2.4.2 wiz fsub.s FONE(%pc),%fp0 # subtract off 1.0
13671 1.2.4.2 wiz fbge.w pos_res # if pos, branch
13672 1.2.4.2 wiz fmul.x PLOG2UP1(%pc),%fp0 # if neg, mul by LOG2UP1
13673 1.2.4.2 wiz fmov.l %fp0,%d6 # put ILOG in d6 as a lword
13674 1.2.4.2 wiz bra.b A4_str # go move out ILOG
13675 1.2.4.2 wiz pos_res:
13676 1.2.4.2 wiz fmul.x PLOG2(%pc),%fp0 # if pos, mul by LOG2
13677 1.2.4.2 wiz fmov.l %fp0,%d6 # put ILOG in d6 as a lword
13678 1.2.4.2 wiz
13679 1.2.4.2 wiz
13680 1.2.4.2 wiz # A4. Clr INEX bit.
13681 1.2.4.2 wiz # The operation in A3 above may have set INEX2.
13682 1.2.4.2 wiz
13683 1.2.4.2 wiz A4_str:
13684 1.2.4.2 wiz fmov.l &0,%fpsr # zero all of fpsr - nothing needed
13685 1.2.4.2 wiz
13686 1.2.4.2 wiz
13687 1.2.4.2 wiz # A5. Set ICTR = 0;
13688 1.2.4.2 wiz # ICTR is a flag used in A13. It must be set before the
13689 1.2.4.2 wiz # loop entry A6. The lower word of d5 is used for ICTR.
13690 1.2.4.2 wiz
13691 1.2.4.2 wiz clr.w %d5 # clear ICTR
13692 1.2.4.2 wiz
13693 1.2.4.2 wiz # A6. Calculate LEN.
13694 1.2.4.2 wiz # LEN is the number of digits to be displayed. The k-factor
13695 1.2.4.2 wiz # can dictate either the total number of digits, if it is
13696 1.2.4.2 wiz # a positive number, or the number of digits after the
13697 1.2.4.2 wiz # original decimal point which are to be included as
13698 1.2.4.2 wiz # significant. See the 68882 manual for examples.
13699 1.2.4.2 wiz # If LEN is computed to be greater than 17, set OPERR in
13700 1.2.4.2 wiz # USER_FPSR. LEN is stored in d4.
13701 1.2.4.2 wiz #
13702 1.2.4.2 wiz # Register usage:
13703 1.2.4.2 wiz # Input/Output
13704 1.2.4.2 wiz # d0: exponent/Unchanged
13705 1.2.4.2 wiz # d2: x/x/scratch
13706 1.2.4.2 wiz # d3: x/x
13707 1.2.4.2 wiz # d4: exc picture/LEN
13708 1.2.4.2 wiz # d5: ICTR/Unchanged
13709 1.2.4.2 wiz # d6: ILOG/Unchanged
13710 1.2.4.2 wiz # d7: k-factor/Unchanged
13711 1.2.4.2 wiz # a0: ptr for original operand/final result
13712 1.2.4.2 wiz # a1: x/x
13713 1.2.4.2 wiz # a2: x/x
13714 1.2.4.2 wiz # fp0: float(ILOG)/Unchanged
13715 1.2.4.2 wiz # fp1: x/x
13716 1.2.4.2 wiz # fp2: x/x
13717 1.2.4.2 wiz # F_SCR1:x/x
13718 1.2.4.2 wiz # F_SCR2:Abs(X) with $3fff exponent/Unchanged
13719 1.2.4.2 wiz # L_SCR1:x/x
13720 1.2.4.2 wiz # L_SCR2:first word of X packed/Unchanged
13721 1.2.4.2 wiz
13722 1.2.4.2 wiz A6_str:
13723 1.2.4.2 wiz tst.l %d7 # branch on sign of k
13724 1.2.4.2 wiz ble.b k_neg # if k <= 0, LEN = ILOG + 1 - k
13725 1.2.4.2 wiz mov.l %d7,%d4 # if k > 0, LEN = k
13726 1.2.4.2 wiz bra.b len_ck # skip to LEN check
13727 1.2.4.2 wiz k_neg:
13728 1.2.4.2 wiz mov.l %d6,%d4 # first load ILOG to d4
13729 1.2.4.2 wiz sub.l %d7,%d4 # subtract off k
13730 1.2.4.2 wiz addq.l &1,%d4 # add in the 1
13731 1.2.4.2 wiz len_ck:
13732 1.2.4.2 wiz tst.l %d4 # LEN check: branch on sign of LEN
13733 1.2.4.2 wiz ble.b LEN_ng # if neg, set LEN = 1
13734 1.2.4.2 wiz cmp.l %d4,&17 # test if LEN > 17
13735 1.2.4.2 wiz ble.b A7_str # if not, forget it
13736 1.2.4.2 wiz mov.l &17,%d4 # set max LEN = 17
13737 1.2.4.2 wiz tst.l %d7 # if negative, never set OPERR
13738 1.2.4.2 wiz ble.b A7_str # if positive, continue
13739 1.2.4.2 wiz or.l &opaop_mask,USER_FPSR(%a6) # set OPERR & AIOP in USER_FPSR
13740 1.2.4.2 wiz bra.b A7_str # finished here
13741 1.2.4.2 wiz LEN_ng:
13742 1.2.4.2 wiz mov.l &1,%d4 # min LEN is 1
13743 1.2.4.2 wiz
13744 1.2.4.2 wiz
13745 1.2.4.2 wiz # A7. Calculate SCALE.
13746 1.2.4.2 wiz # SCALE is equal to 10^ISCALE, where ISCALE is the number
13747 1.2.4.2 wiz # of decimal places needed to insure LEN integer digits
13748 1.2.4.2 wiz # in the output before conversion to bcd. LAMBDA is the sign
13749 1.2.4.2 wiz # of ISCALE, used in A9. Fp1 contains 10^^(abs(ISCALE)) using
13750 1.2.4.2 wiz # the rounding mode as given in the following table (see
13751 1.2.4.2 wiz # Coonen, p. 7.23 as ref.; however, the SCALE variable is
13752 1.2.4.2 wiz # of opposite sign in bindec.sa from Coonen).
13753 1.2.4.2 wiz #
13754 1.2.4.2 wiz # Initial USE
13755 1.2.4.2 wiz # FPCR[6:5] LAMBDA SIGN(X) FPCR[6:5]
13756 1.2.4.2 wiz # ----------------------------------------------
13757 1.2.4.2 wiz # RN 00 0 0 00/0 RN
13758 1.2.4.2 wiz # RN 00 0 1 00/0 RN
13759 1.2.4.2 wiz # RN 00 1 0 00/0 RN
13760 1.2.4.2 wiz # RN 00 1 1 00/0 RN
13761 1.2.4.2 wiz # RZ 01 0 0 11/3 RP
13762 1.2.4.2 wiz # RZ 01 0 1 11/3 RP
13763 1.2.4.2 wiz # RZ 01 1 0 10/2 RM
13764 1.2.4.2 wiz # RZ 01 1 1 10/2 RM
13765 1.2.4.2 wiz # RM 10 0 0 11/3 RP
13766 1.2.4.2 wiz # RM 10 0 1 10/2 RM
13767 1.2.4.2 wiz # RM 10 1 0 10/2 RM
13768 1.2.4.2 wiz # RM 10 1 1 11/3 RP
13769 1.2.4.2 wiz # RP 11 0 0 10/2 RM
13770 1.2.4.2 wiz # RP 11 0 1 11/3 RP
13771 1.2.4.2 wiz # RP 11 1 0 11/3 RP
13772 1.2.4.2 wiz # RP 11 1 1 10/2 RM
13773 1.2.4.2 wiz #
13774 1.2.4.2 wiz # Register usage:
13775 1.2.4.2 wiz # Input/Output
13776 1.2.4.2 wiz # d0: exponent/scratch - final is 0
13777 1.2.4.2 wiz # d2: x/0 or 24 for A9
13778 1.2.4.2 wiz # d3: x/scratch - offset ptr into PTENRM array
13779 1.2.4.2 wiz # d4: LEN/Unchanged
13780 1.2.4.2 wiz # d5: 0/ICTR:LAMBDA
13781 1.2.4.2 wiz # d6: ILOG/ILOG or k if ((k<=0)&(ILOG<k))
13782 1.2.4.2 wiz # d7: k-factor/Unchanged
13783 1.2.4.2 wiz # a0: ptr for original operand/final result
13784 1.2.4.2 wiz # a1: x/ptr to PTENRM array
13785 1.2.4.2 wiz # a2: x/x
13786 1.2.4.2 wiz # fp0: float(ILOG)/Unchanged
13787 1.2.4.2 wiz # fp1: x/10^ISCALE
13788 1.2.4.2 wiz # fp2: x/x
13789 1.2.4.2 wiz # F_SCR1:x/x
13790 1.2.4.2 wiz # F_SCR2:Abs(X) with $3fff exponent/Unchanged
13791 1.2.4.2 wiz # L_SCR1:x/x
13792 1.2.4.2 wiz # L_SCR2:first word of X packed/Unchanged
13793 1.2.4.2 wiz
13794 1.2.4.2 wiz A7_str:
13795 1.2.4.2 wiz tst.l %d7 # test sign of k
13796 1.2.4.2 wiz bgt.b k_pos # if pos and > 0, skip this
13797 1.2.4.2 wiz cmp.l %d7,%d6 # test k - ILOG
13798 1.2.4.2 wiz blt.b k_pos # if ILOG >= k, skip this
13799 1.2.4.2 wiz mov.l %d7,%d6 # if ((k<0) & (ILOG < k)) ILOG = k
13800 1.2.4.2 wiz k_pos:
13801 1.2.4.2 wiz mov.l %d6,%d0 # calc ILOG + 1 - LEN in d0
13802 1.2.4.2 wiz addq.l &1,%d0 # add the 1
13803 1.2.4.2 wiz sub.l %d4,%d0 # sub off LEN
13804 1.2.4.2 wiz swap %d5 # use upper word of d5 for LAMBDA
13805 1.2.4.2 wiz clr.w %d5 # set it zero initially
13806 1.2.4.2 wiz clr.w %d2 # set up d2 for very small case
13807 1.2.4.2 wiz tst.l %d0 # test sign of ISCALE
13808 1.2.4.2 wiz bge.b iscale # if pos, skip next inst
13809 1.2.4.2 wiz addq.w &1,%d5 # if neg, set LAMBDA true
13810 1.2.4.2 wiz cmp.l %d0,&0xffffecd4 # test iscale <= -4908
13811 1.2.4.2 wiz bgt.b no_inf # if false, skip rest
13812 1.2.4.2 wiz add.l &24,%d0 # add in 24 to iscale
13813 1.2.4.2 wiz mov.l &24,%d2 # put 24 in d2 for A9
13814 1.2.4.2 wiz no_inf:
13815 1.2.4.2 wiz neg.l %d0 # and take abs of ISCALE
13816 1.2.4.2 wiz iscale:
13817 1.2.4.2 wiz fmov.s FONE(%pc),%fp1 # init fp1 to 1
13818 1.2.4.2 wiz bfextu USER_FPCR(%a6){&26:&2},%d1 # get initial rmode bits
13819 1.2.4.2 wiz lsl.w &1,%d1 # put them in bits 2:1
13820 1.2.4.2 wiz add.w %d5,%d1 # add in LAMBDA
13821 1.2.4.2 wiz lsl.w &1,%d1 # put them in bits 3:1
13822 1.2.4.2 wiz tst.l L_SCR2(%a6) # test sign of original x
13823 1.2.4.2 wiz bge.b x_pos # if pos, don't set bit 0
13824 1.2.4.2 wiz addq.l &1,%d1 # if neg, set bit 0
13825 1.2.4.2 wiz x_pos:
13826 1.2.4.2 wiz lea.l RBDTBL(%pc),%a2 # load rbdtbl base
13827 1.2.4.2 wiz mov.b (%a2,%d1),%d3 # load d3 with new rmode
13828 1.2.4.2 wiz lsl.l &4,%d3 # put bits in proper position
13829 1.2.4.2 wiz fmov.l %d3,%fpcr # load bits into fpu
13830 1.2.4.2 wiz lsr.l &4,%d3 # put bits in proper position
13831 1.2.4.2 wiz tst.b %d3 # decode new rmode for pten table
13832 1.2.4.2 wiz bne.b not_rn # if zero, it is RN
13833 1.2.4.2 wiz lea.l PTENRN(%pc),%a1 # load a1 with RN table base
13834 1.2.4.2 wiz bra.b rmode # exit decode
13835 1.2.4.2 wiz not_rn:
13836 1.2.4.2 wiz lsr.b &1,%d3 # get lsb in carry
13837 1.2.4.2 wiz bcc.b not_rp2 # if carry clear, it is RM
13838 1.2.4.2 wiz lea.l PTENRP(%pc),%a1 # load a1 with RP table base
13839 1.2.4.2 wiz bra.b rmode # exit decode
13840 1.2.4.2 wiz not_rp2:
13841 1.2.4.2 wiz lea.l PTENRM(%pc),%a1 # load a1 with RM table base
13842 1.2.4.2 wiz rmode:
13843 1.2.4.2 wiz clr.l %d3 # clr table index
13844 1.2.4.2 wiz e_loop2:
13845 1.2.4.2 wiz lsr.l &1,%d0 # shift next bit into carry
13846 1.2.4.2 wiz bcc.b e_next2 # if zero, skip the mul
13847 1.2.4.2 wiz fmul.x (%a1,%d3),%fp1 # mul by 10**(d3_bit_no)
13848 1.2.4.2 wiz e_next2:
13849 1.2.4.2 wiz add.l &12,%d3 # inc d3 to next pwrten table entry
13850 1.2.4.2 wiz tst.l %d0 # test if ISCALE is zero
13851 1.2.4.2 wiz bne.b e_loop2 # if not, loop
13852 1.2.4.2 wiz
13853 1.2.4.2 wiz # A8. Clr INEX; Force RZ.
13854 1.2.4.2 wiz # The operation in A3 above may have set INEX2.
13855 1.2.4.2 wiz # RZ mode is forced for the scaling operation to insure
13856 1.2.4.2 wiz # only one rounding error. The grs bits are collected in
13857 1.2.4.2 wiz # the INEX flag for use in A10.
13858 1.2.4.2 wiz #
13859 1.2.4.2 wiz # Register usage:
13860 1.2.4.2 wiz # Input/Output
13861 1.2.4.2 wiz
13862 1.2.4.2 wiz fmov.l &0,%fpsr # clr INEX
13863 1.2.4.2 wiz fmov.l &rz_mode*0x10,%fpcr # set RZ rounding mode
13864 1.2.4.2 wiz
13865 1.2.4.2 wiz # A9. Scale X -> Y.
13866 1.2.4.2 wiz # The mantissa is scaled to the desired number of significant
13867 1.2.4.2 wiz # digits. The excess digits are collected in INEX2. If mul,
13868 1.2.4.2 wiz # Check d2 for excess 10 exponential value. If not zero,
13869 1.2.4.2 wiz # the iscale value would have caused the pwrten calculation
13870 1.2.4.2 wiz # to overflow. Only a negative iscale can cause this, so
13871 1.2.4.2 wiz # multiply by 10^(d2), which is now only allowed to be 24,
13872 1.2.4.2 wiz # with a multiply by 10^8 and 10^16, which is exact since
13873 1.2.4.2 wiz # 10^24 is exact. If the input was denormalized, we must
13874 1.2.4.2 wiz # create a busy stack frame with the mul command and the
13875 1.2.4.2 wiz # two operands, and allow the fpu to complete the multiply.
13876 1.2.4.2 wiz #
13877 1.2.4.2 wiz # Register usage:
13878 1.2.4.2 wiz # Input/Output
13879 1.2.4.2 wiz # d0: FPCR with RZ mode/Unchanged
13880 1.2.4.2 wiz # d2: 0 or 24/unchanged
13881 1.2.4.2 wiz # d3: x/x
13882 1.2.4.2 wiz # d4: LEN/Unchanged
13883 1.2.4.2 wiz # d5: ICTR:LAMBDA
13884 1.2.4.2 wiz # d6: ILOG/Unchanged
13885 1.2.4.2 wiz # d7: k-factor/Unchanged
13886 1.2.4.2 wiz # a0: ptr for original operand/final result
13887 1.2.4.2 wiz # a1: ptr to PTENRM array/Unchanged
13888 1.2.4.2 wiz # a2: x/x
13889 1.2.4.2 wiz # fp0: float(ILOG)/X adjusted for SCALE (Y)
13890 1.2.4.2 wiz # fp1: 10^ISCALE/Unchanged
13891 1.2.4.2 wiz # fp2: x/x
13892 1.2.4.2 wiz # F_SCR1:x/x
13893 1.2.4.2 wiz # F_SCR2:Abs(X) with $3fff exponent/Unchanged
13894 1.2.4.2 wiz # L_SCR1:x/x
13895 1.2.4.2 wiz # L_SCR2:first word of X packed/Unchanged
13896 1.2.4.2 wiz
13897 1.2.4.2 wiz A9_str:
13898 1.2.4.2 wiz fmov.x (%a0),%fp0 # load X from memory
13899 1.2.4.2 wiz fabs.x %fp0 # use abs(X)
13900 1.2.4.2 wiz tst.w %d5 # LAMBDA is in lower word of d5
13901 1.2.4.2 wiz bne.b sc_mul # if neg (LAMBDA = 1), scale by mul
13902 1.2.4.2 wiz fdiv.x %fp1,%fp0 # calculate X / SCALE -> Y to fp0
13903 1.2.4.2 wiz bra.w A10_st # branch to A10
13904 1.2.4.2 wiz
13905 1.2.4.2 wiz sc_mul:
13906 1.2.4.2 wiz tst.b BINDEC_FLG(%a6) # check for denorm
13907 1.2.4.2 wiz beq.w A9_norm # if norm, continue with mul
13908 1.2.4.2 wiz
13909 1.2.4.2 wiz # for DENORM, we must calculate:
13910 1.2.4.2 wiz # fp0 = input_op * 10^ISCALE * 10^24
13911 1.2.4.2 wiz # since the input operand is a DENORM, we can't multiply it directly.
13912 1.2.4.2 wiz # so, we do the multiplication of the exponents and mantissas separately.
13913 1.2.4.2 wiz # in this way, we avoid underflow on intermediate stages of the
13914 1.2.4.2 wiz # multiplication and guarantee a result without exception.
13915 1.2.4.2 wiz fmovm.x &0x2,-(%sp) # save 10^ISCALE to stack
13916 1.2.4.2 wiz
13917 1.2.4.2 wiz mov.w (%sp),%d3 # grab exponent
13918 1.2.4.2 wiz andi.w &0x7fff,%d3 # clear sign
13919 1.2.4.2 wiz ori.w &0x8000,(%a0) # make DENORM exp negative
13920 1.2.4.2 wiz add.w (%a0),%d3 # add DENORM exp to 10^ISCALE exp
13921 1.2.4.2 wiz subi.w &0x3fff,%d3 # subtract BIAS
13922 1.2.4.2 wiz add.w 36(%a1),%d3
13923 1.2.4.2 wiz subi.w &0x3fff,%d3 # subtract BIAS
13924 1.2.4.2 wiz add.w 48(%a1),%d3
13925 1.2.4.2 wiz subi.w &0x3fff,%d3 # subtract BIAS
13926 1.2.4.2 wiz
13927 1.2.4.2 wiz bmi.w sc_mul_err # is result is DENORM, punt!!!
13928 1.2.4.2 wiz
13929 1.2.4.2 wiz andi.w &0x8000,(%sp) # keep sign
13930 1.2.4.2 wiz or.w %d3,(%sp) # insert new exponent
13931 1.2.4.2 wiz andi.w &0x7fff,(%a0) # clear sign bit on DENORM again
13932 1.2.4.2 wiz mov.l 0x8(%a0),-(%sp) # put input op mantissa on stk
13933 1.2.4.2 wiz mov.l 0x4(%a0),-(%sp)
13934 1.2.4.2 wiz mov.l &0x3fff0000,-(%sp) # force exp to zero
13935 1.2.4.2 wiz fmovm.x (%sp)+,&0x80 # load normalized DENORM into fp0
13936 1.2.4.2 wiz fmul.x (%sp)+,%fp0
13937 1.2.4.2 wiz
13938 1.2.4.2 wiz # fmul.x 36(%a1),%fp0 # multiply fp0 by 10^8
13939 1.2.4.2 wiz # fmul.x 48(%a1),%fp0 # multiply fp0 by 10^16
13940 1.2.4.2 wiz mov.l 36+8(%a1),-(%sp) # get 10^8 mantissa
13941 1.2.4.2 wiz mov.l 36+4(%a1),-(%sp)
13942 1.2.4.2 wiz mov.l &0x3fff0000,-(%sp) # force exp to zero
13943 1.2.4.2 wiz mov.l 48+8(%a1),-(%sp) # get 10^16 mantissa
13944 1.2.4.2 wiz mov.l 48+4(%a1),-(%sp)
13945 1.2.4.2 wiz mov.l &0x3fff0000,-(%sp)# force exp to zero
13946 1.2.4.2 wiz fmul.x (%sp)+,%fp0 # multiply fp0 by 10^8
13947 1.2.4.2 wiz fmul.x (%sp)+,%fp0 # multiply fp0 by 10^16
13948 1.2.4.2 wiz bra.b A10_st
13949 1.2.4.2 wiz
13950 1.2.4.2 wiz sc_mul_err:
13951 1.2.4.2 wiz bra.b sc_mul_err
13952 1.2.4.2 wiz
13953 1.2.4.2 wiz A9_norm:
13954 1.2.4.2 wiz tst.w %d2 # test for small exp case
13955 1.2.4.2 wiz beq.b A9_con # if zero, continue as normal
13956 1.2.4.2 wiz fmul.x 36(%a1),%fp0 # multiply fp0 by 10^8
13957 1.2.4.2 wiz fmul.x 48(%a1),%fp0 # multiply fp0 by 10^16
13958 1.2.4.2 wiz A9_con:
13959 1.2.4.2 wiz fmul.x %fp1,%fp0 # calculate X * SCALE -> Y to fp0
13960 1.2.4.2 wiz
13961 1.2.4.2 wiz # A10. Or in INEX.
13962 1.2.4.2 wiz # If INEX is set, round error occurred. This is compensated
13963 1.2.4.2 wiz # for by 'or-ing' in the INEX2 flag to the lsb of Y.
13964 1.2.4.2 wiz #
13965 1.2.4.2 wiz # Register usage:
13966 1.2.4.2 wiz # Input/Output
13967 1.2.4.2 wiz # d0: FPCR with RZ mode/FPSR with INEX2 isolated
13968 1.2.4.2 wiz # d2: x/x
13969 1.2.4.2 wiz # d3: x/x
13970 1.2.4.2 wiz # d4: LEN/Unchanged
13971 1.2.4.2 wiz # d5: ICTR:LAMBDA
13972 1.2.4.2 wiz # d6: ILOG/Unchanged
13973 1.2.4.2 wiz # d7: k-factor/Unchanged
13974 1.2.4.2 wiz # a0: ptr for original operand/final result
13975 1.2.4.2 wiz # a1: ptr to PTENxx array/Unchanged
13976 1.2.4.2 wiz # a2: x/ptr to FP_SCR1(a6)
13977 1.2.4.2 wiz # fp0: Y/Y with lsb adjusted
13978 1.2.4.2 wiz # fp1: 10^ISCALE/Unchanged
13979 1.2.4.2 wiz # fp2: x/x
13980 1.2.4.2 wiz
13981 1.2.4.2 wiz A10_st:
13982 1.2.4.2 wiz fmov.l %fpsr,%d0 # get FPSR
13983 1.2.4.2 wiz fmov.x %fp0,FP_SCR1(%a6) # move Y to memory
13984 1.2.4.2 wiz lea.l FP_SCR1(%a6),%a2 # load a2 with ptr to FP_SCR1
13985 1.2.4.2 wiz btst &9,%d0 # check if INEX2 set
13986 1.2.4.2 wiz beq.b A11_st # if clear, skip rest
13987 1.2.4.2 wiz or.l &1,8(%a2) # or in 1 to lsb of mantissa
13988 1.2.4.2 wiz fmov.x FP_SCR1(%a6),%fp0 # write adjusted Y back to fpu
13989 1.2.4.2 wiz
13990 1.2.4.2 wiz
13991 1.2.4.2 wiz # A11. Restore original FPCR; set size ext.
13992 1.2.4.2 wiz # Perform FINT operation in the user's rounding mode. Keep
13993 1.2.4.2 wiz # the size to extended. The sintdo entry point in the sint
13994 1.2.4.2 wiz # routine expects the FPCR value to be in USER_FPCR for
13995 1.2.4.2 wiz # mode and precision. The original FPCR is saved in L_SCR1.
13996 1.2.4.2 wiz
13997 1.2.4.2 wiz A11_st:
13998 1.2.4.2 wiz mov.l USER_FPCR(%a6),L_SCR1(%a6) # save it for later
13999 1.2.4.2 wiz and.l &0x00000030,USER_FPCR(%a6) # set size to ext,
14000 1.2.4.2 wiz # ;block exceptions
14001 1.2.4.2 wiz
14002 1.2.4.2 wiz
14003 1.2.4.2 wiz # A12. Calculate YINT = FINT(Y) according to user's rounding mode.
14004 1.2.4.2 wiz # The FPSP routine sintd0 is used. The output is in fp0.
14005 1.2.4.2 wiz #
14006 1.2.4.2 wiz # Register usage:
14007 1.2.4.2 wiz # Input/Output
14008 1.2.4.2 wiz # d0: FPSR with AINEX cleared/FPCR with size set to ext
14009 1.2.4.2 wiz # d2: x/x/scratch
14010 1.2.4.2 wiz # d3: x/x
14011 1.2.4.2 wiz # d4: LEN/Unchanged
14012 1.2.4.2 wiz # d5: ICTR:LAMBDA/Unchanged
14013 1.2.4.2 wiz # d6: ILOG/Unchanged
14014 1.2.4.2 wiz # d7: k-factor/Unchanged
14015 1.2.4.2 wiz # a0: ptr for original operand/src ptr for sintdo
14016 1.2.4.2 wiz # a1: ptr to PTENxx array/Unchanged
14017 1.2.4.2 wiz # a2: ptr to FP_SCR1(a6)/Unchanged
14018 1.2.4.2 wiz # a6: temp pointer to FP_SCR1(a6) - orig value saved and restored
14019 1.2.4.2 wiz # fp0: Y/YINT
14020 1.2.4.2 wiz # fp1: 10^ISCALE/Unchanged
14021 1.2.4.2 wiz # fp2: x/x
14022 1.2.4.2 wiz # F_SCR1:x/x
14023 1.2.4.2 wiz # F_SCR2:Y adjusted for inex/Y with original exponent
14024 1.2.4.2 wiz # L_SCR1:x/original USER_FPCR
14025 1.2.4.2 wiz # L_SCR2:first word of X packed/Unchanged
14026 1.2.4.2 wiz
14027 1.2.4.2 wiz A12_st:
14028 1.2.4.2 wiz movm.l &0xc0c0,-(%sp) # save regs used by sintd0 {%d0-%d1/%a0-%a1}
14029 1.2.4.2 wiz mov.l L_SCR1(%a6),-(%sp)
14030 1.2.4.2 wiz mov.l L_SCR2(%a6),-(%sp)
14031 1.2.4.2 wiz
14032 1.2.4.2 wiz lea.l FP_SCR1(%a6),%a0 # a0 is ptr to FP_SCR1(a6)
14033 1.2.4.2 wiz fmov.x %fp0,(%a0) # move Y to memory at FP_SCR1(a6)
14034 1.2.4.2 wiz tst.l L_SCR2(%a6) # test sign of original operand
14035 1.2.4.2 wiz bge.b do_fint12 # if pos, use Y
14036 1.2.4.2 wiz or.l &0x80000000,(%a0) # if neg, use -Y
14037 1.2.4.2 wiz do_fint12:
14038 1.2.4.2 wiz mov.l USER_FPSR(%a6),-(%sp)
14039 1.2.4.2 wiz # bsr sintdo # sint routine returns int in fp0
14040 1.2.4.2 wiz
14041 1.2.4.2 wiz fmov.l USER_FPCR(%a6),%fpcr
14042 1.2.4.2 wiz fmov.l &0x0,%fpsr # clear the AEXC bits!!!
14043 1.2.4.2 wiz ## mov.l USER_FPCR(%a6),%d0 # ext prec/keep rnd mode
14044 1.2.4.2 wiz ## andi.l &0x00000030,%d0
14045 1.2.4.2 wiz ## fmov.l %d0,%fpcr
14046 1.2.4.2 wiz fint.x FP_SCR1(%a6),%fp0 # do fint()
14047 1.2.4.2 wiz fmov.l %fpsr,%d0
14048 1.2.4.2 wiz or.w %d0,FPSR_EXCEPT(%a6)
14049 1.2.4.2 wiz ## fmov.l &0x0,%fpcr
14050 1.2.4.2 wiz ## fmov.l %fpsr,%d0 # don't keep ccodes
14051 1.2.4.2 wiz ## or.w %d0,FPSR_EXCEPT(%a6)
14052 1.2.4.2 wiz
14053 1.2.4.2 wiz mov.b (%sp),USER_FPSR(%a6)
14054 1.2.4.2 wiz add.l &4,%sp
14055 1.2.4.2 wiz
14056 1.2.4.2 wiz mov.l (%sp)+,L_SCR2(%a6)
14057 1.2.4.2 wiz mov.l (%sp)+,L_SCR1(%a6)
14058 1.2.4.2 wiz movm.l (%sp)+,&0x303 # restore regs used by sint {%d0-%d1/%a0-%a1}
14059 1.2.4.2 wiz
14060 1.2.4.2 wiz mov.l L_SCR2(%a6),FP_SCR1(%a6) # restore original exponent
14061 1.2.4.2 wiz mov.l L_SCR1(%a6),USER_FPCR(%a6) # restore user's FPCR
14062 1.2.4.2 wiz
14063 1.2.4.2 wiz # A13. Check for LEN digits.
14064 1.2.4.2 wiz # If the int operation results in more than LEN digits,
14065 1.2.4.2 wiz # or less than LEN -1 digits, adjust ILOG and repeat from
14066 1.2.4.2 wiz # A6. This test occurs only on the first pass. If the
14067 1.2.4.2 wiz # result is exactly 10^LEN, decrement ILOG and divide
14068 1.2.4.2 wiz # the mantissa by 10. The calculation of 10^LEN cannot
14069 1.2.4.2 wiz # be inexact, since all powers of ten upto 10^27 are exact
14070 1.2.4.2 wiz # in extended precision, so the use of a previous power-of-ten
14071 1.2.4.2 wiz # table will introduce no error.
14072 1.2.4.2 wiz #
14073 1.2.4.2 wiz #
14074 1.2.4.2 wiz # Register usage:
14075 1.2.4.2 wiz # Input/Output
14076 1.2.4.2 wiz # d0: FPCR with size set to ext/scratch final = 0
14077 1.2.4.2 wiz # d2: x/x
14078 1.2.4.2 wiz # d3: x/scratch final = x
14079 1.2.4.2 wiz # d4: LEN/LEN adjusted
14080 1.2.4.2 wiz # d5: ICTR:LAMBDA/LAMBDA:ICTR
14081 1.2.4.2 wiz # d6: ILOG/ILOG adjusted
14082 1.2.4.2 wiz # d7: k-factor/Unchanged
14083 1.2.4.2 wiz # a0: pointer into memory for packed bcd string formation
14084 1.2.4.2 wiz # a1: ptr to PTENxx array/Unchanged
14085 1.2.4.2 wiz # a2: ptr to FP_SCR1(a6)/Unchanged
14086 1.2.4.2 wiz # fp0: int portion of Y/abs(YINT) adjusted
14087 1.2.4.2 wiz # fp1: 10^ISCALE/Unchanged
14088 1.2.4.2 wiz # fp2: x/10^LEN
14089 1.2.4.2 wiz # F_SCR1:x/x
14090 1.2.4.2 wiz # F_SCR2:Y with original exponent/Unchanged
14091 1.2.4.2 wiz # L_SCR1:original USER_FPCR/Unchanged
14092 1.2.4.2 wiz # L_SCR2:first word of X packed/Unchanged
14093 1.2.4.2 wiz
14094 1.2.4.2 wiz A13_st:
14095 1.2.4.2 wiz swap %d5 # put ICTR in lower word of d5
14096 1.2.4.2 wiz tst.w %d5 # check if ICTR = 0
14097 1.2.4.2 wiz bne not_zr # if non-zero, go to second test
14098 1.2.4.2 wiz #
14099 1.2.4.2 wiz # Compute 10^(LEN-1)
14100 1.2.4.2 wiz #
14101 1.2.4.2 wiz fmov.s FONE(%pc),%fp2 # init fp2 to 1.0
14102 1.2.4.2 wiz mov.l %d4,%d0 # put LEN in d0
14103 1.2.4.2 wiz subq.l &1,%d0 # d0 = LEN -1
14104 1.2.4.2 wiz clr.l %d3 # clr table index
14105 1.2.4.2 wiz l_loop:
14106 1.2.4.2 wiz lsr.l &1,%d0 # shift next bit into carry
14107 1.2.4.2 wiz bcc.b l_next # if zero, skip the mul
14108 1.2.4.2 wiz fmul.x (%a1,%d3),%fp2 # mul by 10**(d3_bit_no)
14109 1.2.4.2 wiz l_next:
14110 1.2.4.2 wiz add.l &12,%d3 # inc d3 to next pwrten table entry
14111 1.2.4.2 wiz tst.l %d0 # test if LEN is zero
14112 1.2.4.2 wiz bne.b l_loop # if not, loop
14113 1.2.4.2 wiz #
14114 1.2.4.2 wiz # 10^LEN-1 is computed for this test and A14. If the input was
14115 1.2.4.2 wiz # denormalized, check only the case in which YINT > 10^LEN.
14116 1.2.4.2 wiz #
14117 1.2.4.2 wiz tst.b BINDEC_FLG(%a6) # check if input was norm
14118 1.2.4.2 wiz beq.b A13_con # if norm, continue with checking
14119 1.2.4.2 wiz fabs.x %fp0 # take abs of YINT
14120 1.2.4.2 wiz bra test_2
14121 1.2.4.2 wiz #
14122 1.2.4.2 wiz # Compare abs(YINT) to 10^(LEN-1) and 10^LEN
14123 1.2.4.2 wiz #
14124 1.2.4.2 wiz A13_con:
14125 1.2.4.2 wiz fabs.x %fp0 # take abs of YINT
14126 1.2.4.2 wiz fcmp.x %fp0,%fp2 # compare abs(YINT) with 10^(LEN-1)
14127 1.2.4.2 wiz fbge.w test_2 # if greater, do next test
14128 1.2.4.2 wiz subq.l &1,%d6 # subtract 1 from ILOG
14129 1.2.4.2 wiz mov.w &1,%d5 # set ICTR
14130 1.2.4.2 wiz fmov.l &rm_mode*0x10,%fpcr # set rmode to RM
14131 1.2.4.2 wiz fmul.s FTEN(%pc),%fp2 # compute 10^LEN
14132 1.2.4.2 wiz bra.w A6_str # return to A6 and recompute YINT
14133 1.2.4.2 wiz test_2:
14134 1.2.4.2 wiz fmul.s FTEN(%pc),%fp2 # compute 10^LEN
14135 1.2.4.2 wiz fcmp.x %fp0,%fp2 # compare abs(YINT) with 10^LEN
14136 1.2.4.2 wiz fblt.w A14_st # if less, all is ok, go to A14
14137 1.2.4.2 wiz fbgt.w fix_ex # if greater, fix and redo
14138 1.2.4.2 wiz fdiv.s FTEN(%pc),%fp0 # if equal, divide by 10
14139 1.2.4.2 wiz addq.l &1,%d6 # and inc ILOG
14140 1.2.4.2 wiz bra.b A14_st # and continue elsewhere
14141 1.2.4.2 wiz fix_ex:
14142 1.2.4.2 wiz addq.l &1,%d6 # increment ILOG by 1
14143 1.2.4.2 wiz mov.w &1,%d5 # set ICTR
14144 1.2.4.2 wiz fmov.l &rm_mode*0x10,%fpcr # set rmode to RM
14145 1.2.4.2 wiz bra.w A6_str # return to A6 and recompute YINT
14146 1.2.4.2 wiz #
14147 1.2.4.2 wiz # Since ICTR <> 0, we have already been through one adjustment,
14148 1.2.4.2 wiz # and shouldn't have another; this is to check if abs(YINT) = 10^LEN
14149 1.2.4.2 wiz # 10^LEN is again computed using whatever table is in a1 since the
14150 1.2.4.2 wiz # value calculated cannot be inexact.
14151 1.2.4.2 wiz #
14152 1.2.4.2 wiz not_zr:
14153 1.2.4.2 wiz fmov.s FONE(%pc),%fp2 # init fp2 to 1.0
14154 1.2.4.2 wiz mov.l %d4,%d0 # put LEN in d0
14155 1.2.4.2 wiz clr.l %d3 # clr table index
14156 1.2.4.2 wiz z_loop:
14157 1.2.4.2 wiz lsr.l &1,%d0 # shift next bit into carry
14158 1.2.4.2 wiz bcc.b z_next # if zero, skip the mul
14159 1.2.4.2 wiz fmul.x (%a1,%d3),%fp2 # mul by 10**(d3_bit_no)
14160 1.2.4.2 wiz z_next:
14161 1.2.4.2 wiz add.l &12,%d3 # inc d3 to next pwrten table entry
14162 1.2.4.2 wiz tst.l %d0 # test if LEN is zero
14163 1.2.4.2 wiz bne.b z_loop # if not, loop
14164 1.2.4.2 wiz fabs.x %fp0 # get abs(YINT)
14165 1.2.4.2 wiz fcmp.x %fp0,%fp2 # check if abs(YINT) = 10^LEN
14166 1.2.4.2 wiz fbneq.w A14_st # if not, skip this
14167 1.2.4.2 wiz fdiv.s FTEN(%pc),%fp0 # divide abs(YINT) by 10
14168 1.2.4.2 wiz addq.l &1,%d6 # and inc ILOG by 1
14169 1.2.4.2 wiz addq.l &1,%d4 # and inc LEN
14170 1.2.4.2 wiz fmul.s FTEN(%pc),%fp2 # if LEN++, the get 10^^LEN
14171 1.2.4.2 wiz
14172 1.2.4.2 wiz # A14. Convert the mantissa to bcd.
14173 1.2.4.2 wiz # The binstr routine is used to convert the LEN digit
14174 1.2.4.2 wiz # mantissa to bcd in memory. The input to binstr is
14175 1.2.4.2 wiz # to be a fraction; i.e. (mantissa)/10^LEN and adjusted
14176 1.2.4.2 wiz # such that the decimal point is to the left of bit 63.
14177 1.2.4.2 wiz # The bcd digits are stored in the correct position in
14178 1.2.4.2 wiz # the final string area in memory.
14179 1.2.4.2 wiz #
14180 1.2.4.2 wiz #
14181 1.2.4.2 wiz # Register usage:
14182 1.2.4.2 wiz # Input/Output
14183 1.2.4.2 wiz # d0: x/LEN call to binstr - final is 0
14184 1.2.4.2 wiz # d1: x/0
14185 1.2.4.2 wiz # d2: x/ms 32-bits of mant of abs(YINT)
14186 1.2.4.2 wiz # d3: x/ls 32-bits of mant of abs(YINT)
14187 1.2.4.2 wiz # d4: LEN/Unchanged
14188 1.2.4.2 wiz # d5: ICTR:LAMBDA/LAMBDA:ICTR
14189 1.2.4.2 wiz # d6: ILOG
14190 1.2.4.2 wiz # d7: k-factor/Unchanged
14191 1.2.4.2 wiz # a0: pointer into memory for packed bcd string formation
14192 1.2.4.2 wiz # /ptr to first mantissa byte in result string
14193 1.2.4.2 wiz # a1: ptr to PTENxx array/Unchanged
14194 1.2.4.2 wiz # a2: ptr to FP_SCR1(a6)/Unchanged
14195 1.2.4.2 wiz # fp0: int portion of Y/abs(YINT) adjusted
14196 1.2.4.2 wiz # fp1: 10^ISCALE/Unchanged
14197 1.2.4.2 wiz # fp2: 10^LEN/Unchanged
14198 1.2.4.2 wiz # F_SCR1:x/Work area for final result
14199 1.2.4.2 wiz # F_SCR2:Y with original exponent/Unchanged
14200 1.2.4.2 wiz # L_SCR1:original USER_FPCR/Unchanged
14201 1.2.4.2 wiz # L_SCR2:first word of X packed/Unchanged
14202 1.2.4.2 wiz
14203 1.2.4.2 wiz A14_st:
14204 1.2.4.2 wiz fmov.l &rz_mode*0x10,%fpcr # force rz for conversion
14205 1.2.4.2 wiz fdiv.x %fp2,%fp0 # divide abs(YINT) by 10^LEN
14206 1.2.4.2 wiz lea.l FP_SCR0(%a6),%a0
14207 1.2.4.2 wiz fmov.x %fp0,(%a0) # move abs(YINT)/10^LEN to memory
14208 1.2.4.2 wiz mov.l 4(%a0),%d2 # move 2nd word of FP_RES to d2
14209 1.2.4.2 wiz mov.l 8(%a0),%d3 # move 3rd word of FP_RES to d3
14210 1.2.4.2 wiz clr.l 4(%a0) # zero word 2 of FP_RES
14211 1.2.4.2 wiz clr.l 8(%a0) # zero word 3 of FP_RES
14212 1.2.4.2 wiz mov.l (%a0),%d0 # move exponent to d0
14213 1.2.4.2 wiz swap %d0 # put exponent in lower word
14214 1.2.4.2 wiz beq.b no_sft # if zero, don't shift
14215 1.2.4.2 wiz sub.l &0x3ffd,%d0 # sub bias less 2 to make fract
14216 1.2.4.2 wiz tst.l %d0 # check if > 1
14217 1.2.4.2 wiz bgt.b no_sft # if so, don't shift
14218 1.2.4.2 wiz neg.l %d0 # make exp positive
14219 1.2.4.2 wiz m_loop:
14220 1.2.4.2 wiz lsr.l &1,%d2 # shift d2:d3 right, add 0s
14221 1.2.4.2 wiz roxr.l &1,%d3 # the number of places
14222 1.2.4.2 wiz dbf.w %d0,m_loop # given in d0
14223 1.2.4.2 wiz no_sft:
14224 1.2.4.2 wiz tst.l %d2 # check for mantissa of zero
14225 1.2.4.2 wiz bne.b no_zr # if not, go on
14226 1.2.4.2 wiz tst.l %d3 # continue zero check
14227 1.2.4.2 wiz beq.b zer_m # if zero, go directly to binstr
14228 1.2.4.2 wiz no_zr:
14229 1.2.4.2 wiz clr.l %d1 # put zero in d1 for addx
14230 1.2.4.2 wiz add.l &0x00000080,%d3 # inc at bit 7
14231 1.2.4.2 wiz addx.l %d1,%d2 # continue inc
14232 1.2.4.2 wiz and.l &0xffffff80,%d3 # strip off lsb not used by 882
14233 1.2.4.2 wiz zer_m:
14234 1.2.4.2 wiz mov.l %d4,%d0 # put LEN in d0 for binstr call
14235 1.2.4.2 wiz addq.l &3,%a0 # a0 points to M16 byte in result
14236 1.2.4.2 wiz bsr binstr # call binstr to convert mant
14237 1.2.4.2 wiz
14238 1.2.4.2 wiz
14239 1.2.4.2 wiz # A15. Convert the exponent to bcd.
14240 1.2.4.2 wiz # As in A14 above, the exp is converted to bcd and the
14241 1.2.4.2 wiz # digits are stored in the final string.
14242 1.2.4.2 wiz #
14243 1.2.4.2 wiz # Digits are stored in L_SCR1(a6) on return from BINDEC as:
14244 1.2.4.2 wiz #
14245 1.2.4.2 wiz # 32 16 15 0
14246 1.2.4.2 wiz # -----------------------------------------
14247 1.2.4.2 wiz # | 0 | e3 | e2 | e1 | e4 | X | X | X |
14248 1.2.4.2 wiz # -----------------------------------------
14249 1.2.4.2 wiz #
14250 1.2.4.2 wiz # And are moved into their proper places in FP_SCR0. If digit e4
14251 1.2.4.2 wiz # is non-zero, OPERR is signaled. In all cases, all 4 digits are
14252 1.2.4.2 wiz # written as specified in the 881/882 manual for packed decimal.
14253 1.2.4.2 wiz #
14254 1.2.4.2 wiz # Register usage:
14255 1.2.4.2 wiz # Input/Output
14256 1.2.4.2 wiz # d0: x/LEN call to binstr - final is 0
14257 1.2.4.2 wiz # d1: x/scratch (0);shift count for final exponent packing
14258 1.2.4.2 wiz # d2: x/ms 32-bits of exp fraction/scratch
14259 1.2.4.2 wiz # d3: x/ls 32-bits of exp fraction
14260 1.2.4.2 wiz # d4: LEN/Unchanged
14261 1.2.4.2 wiz # d5: ICTR:LAMBDA/LAMBDA:ICTR
14262 1.2.4.2 wiz # d6: ILOG
14263 1.2.4.2 wiz # d7: k-factor/Unchanged
14264 1.2.4.2 wiz # a0: ptr to result string/ptr to L_SCR1(a6)
14265 1.2.4.2 wiz # a1: ptr to PTENxx array/Unchanged
14266 1.2.4.2 wiz # a2: ptr to FP_SCR1(a6)/Unchanged
14267 1.2.4.2 wiz # fp0: abs(YINT) adjusted/float(ILOG)
14268 1.2.4.2 wiz # fp1: 10^ISCALE/Unchanged
14269 1.2.4.2 wiz # fp2: 10^LEN/Unchanged
14270 1.2.4.2 wiz # F_SCR1:Work area for final result/BCD result
14271 1.2.4.2 wiz # F_SCR2:Y with original exponent/ILOG/10^4
14272 1.2.4.2 wiz # L_SCR1:original USER_FPCR/Exponent digits on return from binstr
14273 1.2.4.2 wiz # L_SCR2:first word of X packed/Unchanged
14274 1.2.4.2 wiz
14275 1.2.4.2 wiz A15_st:
14276 1.2.4.2 wiz tst.b BINDEC_FLG(%a6) # check for denorm
14277 1.2.4.2 wiz beq.b not_denorm
14278 1.2.4.2 wiz ftest.x %fp0 # test for zero
14279 1.2.4.2 wiz fbeq.w den_zero # if zero, use k-factor or 4933
14280 1.2.4.2 wiz fmov.l %d6,%fp0 # float ILOG
14281 1.2.4.2 wiz fabs.x %fp0 # get abs of ILOG
14282 1.2.4.2 wiz bra.b convrt
14283 1.2.4.2 wiz den_zero:
14284 1.2.4.2 wiz tst.l %d7 # check sign of the k-factor
14285 1.2.4.2 wiz blt.b use_ilog # if negative, use ILOG
14286 1.2.4.2 wiz fmov.s F4933(%pc),%fp0 # force exponent to 4933
14287 1.2.4.2 wiz bra.b convrt # do it
14288 1.2.4.2 wiz use_ilog:
14289 1.2.4.2 wiz fmov.l %d6,%fp0 # float ILOG
14290 1.2.4.2 wiz fabs.x %fp0 # get abs of ILOG
14291 1.2.4.2 wiz bra.b convrt
14292 1.2.4.2 wiz not_denorm:
14293 1.2.4.2 wiz ftest.x %fp0 # test for zero
14294 1.2.4.2 wiz fbneq.w not_zero # if zero, force exponent
14295 1.2.4.2 wiz fmov.s FONE(%pc),%fp0 # force exponent to 1
14296 1.2.4.2 wiz bra.b convrt # do it
14297 1.2.4.2 wiz not_zero:
14298 1.2.4.2 wiz fmov.l %d6,%fp0 # float ILOG
14299 1.2.4.2 wiz fabs.x %fp0 # get abs of ILOG
14300 1.2.4.2 wiz convrt:
14301 1.2.4.2 wiz fdiv.x 24(%a1),%fp0 # compute ILOG/10^4
14302 1.2.4.2 wiz fmov.x %fp0,FP_SCR1(%a6) # store fp0 in memory
14303 1.2.4.2 wiz mov.l 4(%a2),%d2 # move word 2 to d2
14304 1.2.4.2 wiz mov.l 8(%a2),%d3 # move word 3 to d3
14305 1.2.4.2 wiz mov.w (%a2),%d0 # move exp to d0
14306 1.2.4.2 wiz beq.b x_loop_fin # if zero, skip the shift
14307 1.2.4.2 wiz sub.w &0x3ffd,%d0 # subtract off bias
14308 1.2.4.2 wiz neg.w %d0 # make exp positive
14309 1.2.4.2 wiz x_loop:
14310 1.2.4.2 wiz lsr.l &1,%d2 # shift d2:d3 right
14311 1.2.4.2 wiz roxr.l &1,%d3 # the number of places
14312 1.2.4.2 wiz dbf.w %d0,x_loop # given in d0
14313 1.2.4.2 wiz x_loop_fin:
14314 1.2.4.2 wiz clr.l %d1 # put zero in d1 for addx
14315 1.2.4.2 wiz add.l &0x00000080,%d3 # inc at bit 6
14316 1.2.4.2 wiz addx.l %d1,%d2 # continue inc
14317 1.2.4.2 wiz and.l &0xffffff80,%d3 # strip off lsb not used by 882
14318 1.2.4.2 wiz mov.l &4,%d0 # put 4 in d0 for binstr call
14319 1.2.4.2 wiz lea.l L_SCR1(%a6),%a0 # a0 is ptr to L_SCR1 for exp digits
14320 1.2.4.2 wiz bsr binstr # call binstr to convert exp
14321 1.2.4.2 wiz mov.l L_SCR1(%a6),%d0 # load L_SCR1 lword to d0
14322 1.2.4.2 wiz mov.l &12,%d1 # use d1 for shift count
14323 1.2.4.2 wiz lsr.l %d1,%d0 # shift d0 right by 12
14324 1.2.4.2 wiz bfins %d0,FP_SCR0(%a6){&4:&12} # put e3:e2:e1 in FP_SCR0
14325 1.2.4.2 wiz lsr.l %d1,%d0 # shift d0 right by 12
14326 1.2.4.2 wiz bfins %d0,FP_SCR0(%a6){&16:&4} # put e4 in FP_SCR0
14327 1.2.4.2 wiz tst.b %d0 # check if e4 is zero
14328 1.2.4.2 wiz beq.b A16_st # if zero, skip rest
14329 1.2.4.2 wiz or.l &opaop_mask,USER_FPSR(%a6) # set OPERR & AIOP in USER_FPSR
14330 1.2.4.2 wiz
14331 1.2.4.2 wiz
14332 1.2.4.2 wiz # A16. Write sign bits to final string.
14333 1.2.4.2 wiz # Sigma is bit 31 of initial value; RHO is bit 31 of d6 (ILOG).
14334 1.2.4.2 wiz #
14335 1.2.4.2 wiz # Register usage:
14336 1.2.4.2 wiz # Input/Output
14337 1.2.4.2 wiz # d0: x/scratch - final is x
14338 1.2.4.2 wiz # d2: x/x
14339 1.2.4.2 wiz # d3: x/x
14340 1.2.4.2 wiz # d4: LEN/Unchanged
14341 1.2.4.2 wiz # d5: ICTR:LAMBDA/LAMBDA:ICTR
14342 1.2.4.2 wiz # d6: ILOG/ILOG adjusted
14343 1.2.4.2 wiz # d7: k-factor/Unchanged
14344 1.2.4.2 wiz # a0: ptr to L_SCR1(a6)/Unchanged
14345 1.2.4.2 wiz # a1: ptr to PTENxx array/Unchanged
14346 1.2.4.2 wiz # a2: ptr to FP_SCR1(a6)/Unchanged
14347 1.2.4.2 wiz # fp0: float(ILOG)/Unchanged
14348 1.2.4.2 wiz # fp1: 10^ISCALE/Unchanged
14349 1.2.4.2 wiz # fp2: 10^LEN/Unchanged
14350 1.2.4.2 wiz # F_SCR1:BCD result with correct signs
14351 1.2.4.2 wiz # F_SCR2:ILOG/10^4
14352 1.2.4.2 wiz # L_SCR1:Exponent digits on return from binstr
14353 1.2.4.2 wiz # L_SCR2:first word of X packed/Unchanged
14354 1.2.4.2 wiz
14355 1.2.4.2 wiz A16_st:
14356 1.2.4.2 wiz clr.l %d0 # clr d0 for collection of signs
14357 1.2.4.2 wiz and.b &0x0f,FP_SCR0(%a6) # clear first nibble of FP_SCR0
14358 1.2.4.2 wiz tst.l L_SCR2(%a6) # check sign of original mantissa
14359 1.2.4.2 wiz bge.b mant_p # if pos, don't set SM
14360 1.2.4.2 wiz mov.l &2,%d0 # move 2 in to d0 for SM
14361 1.2.4.2 wiz mant_p:
14362 1.2.4.2 wiz tst.l %d6 # check sign of ILOG
14363 1.2.4.2 wiz bge.b wr_sgn # if pos, don't set SE
14364 1.2.4.2 wiz addq.l &1,%d0 # set bit 0 in d0 for SE
14365 1.2.4.2 wiz wr_sgn:
14366 1.2.4.2 wiz bfins %d0,FP_SCR0(%a6){&0:&2} # insert SM and SE into FP_SCR0
14367 1.2.4.2 wiz
14368 1.2.4.2 wiz # Clean up and restore all registers used.
14369 1.2.4.2 wiz
14370 1.2.4.2 wiz fmov.l &0,%fpsr # clear possible inex2/ainex bits
14371 1.2.4.2 wiz fmovm.x (%sp)+,&0xe0 # {%fp0-%fp2}
14372 1.2.4.2 wiz movm.l (%sp)+,&0x4fc # {%d2-%d7/%a2}
14373 1.2.4.2 wiz rts
14374 1.2.4.2 wiz
14375 1.2.4.2 wiz global PTENRN
14376 1.2.4.2 wiz PTENRN:
14377 1.2.4.2 wiz long 0x40020000,0xA0000000,0x00000000 # 10 ^ 1
14378 1.2.4.2 wiz long 0x40050000,0xC8000000,0x00000000 # 10 ^ 2
14379 1.2.4.2 wiz long 0x400C0000,0x9C400000,0x00000000 # 10 ^ 4
14380 1.2.4.2 wiz long 0x40190000,0xBEBC2000,0x00000000 # 10 ^ 8
14381 1.2.4.2 wiz long 0x40340000,0x8E1BC9BF,0x04000000 # 10 ^ 16
14382 1.2.4.2 wiz long 0x40690000,0x9DC5ADA8,0x2B70B59E # 10 ^ 32
14383 1.2.4.2 wiz long 0x40D30000,0xC2781F49,0xFFCFA6D5 # 10 ^ 64
14384 1.2.4.2 wiz long 0x41A80000,0x93BA47C9,0x80E98CE0 # 10 ^ 128
14385 1.2.4.2 wiz long 0x43510000,0xAA7EEBFB,0x9DF9DE8E # 10 ^ 256
14386 1.2.4.2 wiz long 0x46A30000,0xE319A0AE,0xA60E91C7 # 10 ^ 512
14387 1.2.4.2 wiz long 0x4D480000,0xC9767586,0x81750C17 # 10 ^ 1024
14388 1.2.4.2 wiz long 0x5A920000,0x9E8B3B5D,0xC53D5DE5 # 10 ^ 2048
14389 1.2.4.2 wiz long 0x75250000,0xC4605202,0x8A20979B # 10 ^ 4096
14390 1.2.4.2 wiz
14391 1.2.4.2 wiz global PTENRP
14392 1.2.4.2 wiz PTENRP:
14393 1.2.4.2 wiz long 0x40020000,0xA0000000,0x00000000 # 10 ^ 1
14394 1.2.4.2 wiz long 0x40050000,0xC8000000,0x00000000 # 10 ^ 2
14395 1.2.4.2 wiz long 0x400C0000,0x9C400000,0x00000000 # 10 ^ 4
14396 1.2.4.2 wiz long 0x40190000,0xBEBC2000,0x00000000 # 10 ^ 8
14397 1.2.4.2 wiz long 0x40340000,0x8E1BC9BF,0x04000000 # 10 ^ 16
14398 1.2.4.2 wiz long 0x40690000,0x9DC5ADA8,0x2B70B59E # 10 ^ 32
14399 1.2.4.2 wiz long 0x40D30000,0xC2781F49,0xFFCFA6D6 # 10 ^ 64
14400 1.2.4.2 wiz long 0x41A80000,0x93BA47C9,0x80E98CE0 # 10 ^ 128
14401 1.2.4.2 wiz long 0x43510000,0xAA7EEBFB,0x9DF9DE8E # 10 ^ 256
14402 1.2.4.2 wiz long 0x46A30000,0xE319A0AE,0xA60E91C7 # 10 ^ 512
14403 1.2.4.2 wiz long 0x4D480000,0xC9767586,0x81750C18 # 10 ^ 1024
14404 1.2.4.2 wiz long 0x5A920000,0x9E8B3B5D,0xC53D5DE5 # 10 ^ 2048
14405 1.2.4.2 wiz long 0x75250000,0xC4605202,0x8A20979B # 10 ^ 4096
14406 1.2.4.2 wiz
14407 1.2.4.2 wiz global PTENRM
14408 1.2.4.2 wiz PTENRM:
14409 1.2.4.2 wiz long 0x40020000,0xA0000000,0x00000000 # 10 ^ 1
14410 1.2.4.2 wiz long 0x40050000,0xC8000000,0x00000000 # 10 ^ 2
14411 1.2.4.2 wiz long 0x400C0000,0x9C400000,0x00000000 # 10 ^ 4
14412 1.2.4.2 wiz long 0x40190000,0xBEBC2000,0x00000000 # 10 ^ 8
14413 1.2.4.2 wiz long 0x40340000,0x8E1BC9BF,0x04000000 # 10 ^ 16
14414 1.2.4.2 wiz long 0x40690000,0x9DC5ADA8,0x2B70B59D # 10 ^ 32
14415 1.2.4.2 wiz long 0x40D30000,0xC2781F49,0xFFCFA6D5 # 10 ^ 64
14416 1.2.4.2 wiz long 0x41A80000,0x93BA47C9,0x80E98CDF # 10 ^ 128
14417 1.2.4.2 wiz long 0x43510000,0xAA7EEBFB,0x9DF9DE8D # 10 ^ 256
14418 1.2.4.2 wiz long 0x46A30000,0xE319A0AE,0xA60E91C6 # 10 ^ 512
14419 1.2.4.2 wiz long 0x4D480000,0xC9767586,0x81750C17 # 10 ^ 1024
14420 1.2.4.2 wiz long 0x5A920000,0x9E8B3B5D,0xC53D5DE4 # 10 ^ 2048
14421 1.2.4.2 wiz long 0x75250000,0xC4605202,0x8A20979A # 10 ^ 4096
14422 1.2.4.2 wiz
14423 1.2.4.2 wiz #########################################################################
14424 1.2.4.2 wiz # binstr(): Converts a 64-bit binary integer to bcd. #
14425 1.2.4.2 wiz # #
14426 1.2.4.2 wiz # INPUT *************************************************************** #
14427 1.2.4.2 wiz # d2:d3 = 64-bit binary integer #
14428 1.2.4.2 wiz # d0 = desired length (LEN) #
14429 1.2.4.2 wiz # a0 = pointer to start in memory for bcd characters #
14430 1.2.4.2 wiz # (This pointer must point to byte 4 of the first #
14431 1.2.4.2 wiz # lword of the packed decimal memory string.) #
14432 1.2.4.2 wiz # #
14433 1.2.4.2 wiz # OUTPUT ************************************************************** #
14434 1.2.4.2 wiz # a0 = pointer to LEN bcd digits representing the 64-bit integer. #
14435 1.2.4.2 wiz # #
14436 1.2.4.2 wiz # ALGORITHM *********************************************************** #
14437 1.2.4.2 wiz # The 64-bit binary is assumed to have a decimal point before #
14438 1.2.4.2 wiz # bit 63. The fraction is multiplied by 10 using a mul by 2 #
14439 1.2.4.2 wiz # shift and a mul by 8 shift. The bits shifted out of the #
14440 1.2.4.2 wiz # msb form a decimal digit. This process is iterated until #
14441 1.2.4.2 wiz # LEN digits are formed. #
14442 1.2.4.2 wiz # #
14443 1.2.4.2 wiz # A1. Init d7 to 1. D7 is the byte digit counter, and if 1, the #
14444 1.2.4.2 wiz # digit formed will be assumed the least significant. This is #
14445 1.2.4.2 wiz # to force the first byte formed to have a 0 in the upper 4 bits. #
14446 1.2.4.2 wiz # #
14447 1.2.4.2 wiz # A2. Beginning of the loop: #
14448 1.2.4.2 wiz # Copy the fraction in d2:d3 to d4:d5. #
14449 1.2.4.2 wiz # #
14450 1.2.4.2 wiz # A3. Multiply the fraction in d2:d3 by 8 using bit-field #
14451 1.2.4.2 wiz # extracts and shifts. The three msbs from d2 will go into d1. #
14452 1.2.4.2 wiz # #
14453 1.2.4.2 wiz # A4. Multiply the fraction in d4:d5 by 2 using shifts. The msb #
14454 1.2.4.2 wiz # will be collected by the carry. #
14455 1.2.4.2 wiz # #
14456 1.2.4.2 wiz # A5. Add using the carry the 64-bit quantities in d2:d3 and d4:d5 #
14457 1.2.4.2 wiz # into d2:d3. D1 will contain the bcd digit formed. #
14458 1.2.4.2 wiz # #
14459 1.2.4.2 wiz # A6. Test d7. If zero, the digit formed is the ms digit. If non- #
14460 1.2.4.2 wiz # zero, it is the ls digit. Put the digit in its place in the #
14461 1.2.4.2 wiz # upper word of d0. If it is the ls digit, write the word #
14462 1.2.4.2 wiz # from d0 to memory. #
14463 1.2.4.2 wiz # #
14464 1.2.4.2 wiz # A7. Decrement d6 (LEN counter) and repeat the loop until zero. #
14465 1.2.4.2 wiz # #
14466 1.2.4.2 wiz #########################################################################
14467 1.2.4.2 wiz
14468 1.2.4.2 wiz # Implementation Notes:
14469 1.2.4.2 wiz #
14470 1.2.4.2 wiz # The registers are used as follows:
14471 1.2.4.2 wiz #
14472 1.2.4.2 wiz # d0: LEN counter
14473 1.2.4.2 wiz # d1: temp used to form the digit
14474 1.2.4.2 wiz # d2: upper 32-bits of fraction for mul by 8
14475 1.2.4.2 wiz # d3: lower 32-bits of fraction for mul by 8
14476 1.2.4.2 wiz # d4: upper 32-bits of fraction for mul by 2
14477 1.2.4.2 wiz # d5: lower 32-bits of fraction for mul by 2
14478 1.2.4.2 wiz # d6: temp for bit-field extracts
14479 1.2.4.2 wiz # d7: byte digit formation word;digit count {0,1}
14480 1.2.4.2 wiz # a0: pointer into memory for packed bcd string formation
14481 1.2.4.2 wiz #
14482 1.2.4.2 wiz
14483 1.2.4.2 wiz global binstr
14484 1.2.4.2 wiz binstr:
14485 1.2.4.2 wiz movm.l &0xff00,-(%sp) # {%d0-%d7}
14486 1.2.4.2 wiz
14487 1.2.4.2 wiz #
14488 1.2.4.2 wiz # A1: Init d7
14489 1.2.4.2 wiz #
14490 1.2.4.2 wiz mov.l &1,%d7 # init d7 for second digit
14491 1.2.4.2 wiz subq.l &1,%d0 # for dbf d0 would have LEN+1 passes
14492 1.2.4.2 wiz #
14493 1.2.4.2 wiz # A2. Copy d2:d3 to d4:d5. Start loop.
14494 1.2.4.2 wiz #
14495 1.2.4.2 wiz loop:
14496 1.2.4.2 wiz mov.l %d2,%d4 # copy the fraction before muls
14497 1.2.4.2 wiz mov.l %d3,%d5 # to d4:d5
14498 1.2.4.2 wiz #
14499 1.2.4.2 wiz # A3. Multiply d2:d3 by 8; extract msbs into d1.
14500 1.2.4.2 wiz #
14501 1.2.4.2 wiz bfextu %d2{&0:&3},%d1 # copy 3 msbs of d2 into d1
14502 1.2.4.2 wiz asl.l &3,%d2 # shift d2 left by 3 places
14503 1.2.4.2 wiz bfextu %d3{&0:&3},%d6 # copy 3 msbs of d3 into d6
14504 1.2.4.2 wiz asl.l &3,%d3 # shift d3 left by 3 places
14505 1.2.4.2 wiz or.l %d6,%d2 # or in msbs from d3 into d2
14506 1.2.4.2 wiz #
14507 1.2.4.2 wiz # A4. Multiply d4:d5 by 2; add carry out to d1.
14508 1.2.4.2 wiz #
14509 1.2.4.2 wiz asl.l &1,%d5 # mul d5 by 2
14510 1.2.4.2 wiz roxl.l &1,%d4 # mul d4 by 2
14511 1.2.4.2 wiz swap %d6 # put 0 in d6 lower word
14512 1.2.4.2 wiz addx.w %d6,%d1 # add in extend from mul by 2
14513 1.2.4.2 wiz #
14514 1.2.4.2 wiz # A5. Add mul by 8 to mul by 2. D1 contains the digit formed.
14515 1.2.4.2 wiz #
14516 1.2.4.2 wiz add.l %d5,%d3 # add lower 32 bits
14517 1.2.4.2 wiz nop # ERRATA FIX #13 (Rev. 1.2 6/6/90)
14518 1.2.4.2 wiz addx.l %d4,%d2 # add with extend upper 32 bits
14519 1.2.4.2 wiz nop # ERRATA FIX #13 (Rev. 1.2 6/6/90)
14520 1.2.4.2 wiz addx.w %d6,%d1 # add in extend from add to d1
14521 1.2.4.2 wiz swap %d6 # with d6 = 0; put 0 in upper word
14522 1.2.4.2 wiz #
14523 1.2.4.2 wiz # A6. Test d7 and branch.
14524 1.2.4.2 wiz #
14525 1.2.4.2 wiz tst.w %d7 # if zero, store digit & to loop
14526 1.2.4.2 wiz beq.b first_d # if non-zero, form byte & write
14527 1.2.4.2 wiz sec_d:
14528 1.2.4.2 wiz swap %d7 # bring first digit to word d7b
14529 1.2.4.2 wiz asl.w &4,%d7 # first digit in upper 4 bits d7b
14530 1.2.4.2 wiz add.w %d1,%d7 # add in ls digit to d7b
14531 1.2.4.2 wiz mov.b %d7,(%a0)+ # store d7b byte in memory
14532 1.2.4.2 wiz swap %d7 # put LEN counter in word d7a
14533 1.2.4.2 wiz clr.w %d7 # set d7a to signal no digits done
14534 1.2.4.2 wiz dbf.w %d0,loop # do loop some more!
14535 1.2.4.2 wiz bra.b end_bstr # finished, so exit
14536 1.2.4.2 wiz first_d:
14537 1.2.4.2 wiz swap %d7 # put digit word in d7b
14538 1.2.4.2 wiz mov.w %d1,%d7 # put new digit in d7b
14539 1.2.4.2 wiz swap %d7 # put LEN counter in word d7a
14540 1.2.4.2 wiz addq.w &1,%d7 # set d7a to signal first digit done
14541 1.2.4.2 wiz dbf.w %d0,loop # do loop some more!
14542 1.2.4.2 wiz swap %d7 # put last digit in string
14543 1.2.4.2 wiz lsl.w &4,%d7 # move it to upper 4 bits
14544 1.2.4.2 wiz mov.b %d7,(%a0)+ # store it in memory string
14545 1.2.4.2 wiz #
14546 1.2.4.2 wiz # Clean up and return with result in fp0.
14547 1.2.4.2 wiz #
14548 1.2.4.2 wiz end_bstr:
14549 1.2.4.2 wiz movm.l (%sp)+,&0xff # {%d0-%d7}
14550 1.2.4.2 wiz rts
14551 1.2.4.2 wiz
14552 1.2.4.2 wiz #########################################################################
14553 1.2.4.2 wiz # XDEF **************************************************************** #
14554 1.2.4.2 wiz # facc_in_b(): dmem_read_byte failed #
14555 1.2.4.2 wiz # facc_in_w(): dmem_read_word failed #
14556 1.2.4.2 wiz # facc_in_l(): dmem_read_long failed #
14557 1.2.4.2 wiz # facc_in_d(): dmem_read of dbl prec failed #
14558 1.2.4.2 wiz # facc_in_x(): dmem_read of ext prec failed #
14559 1.2.4.2 wiz # #
14560 1.2.4.2 wiz # facc_out_b(): dmem_write_byte failed #
14561 1.2.4.2 wiz # facc_out_w(): dmem_write_word failed #
14562 1.2.4.2 wiz # facc_out_l(): dmem_write_long failed #
14563 1.2.4.2 wiz # facc_out_d(): dmem_write of dbl prec failed #
14564 1.2.4.2 wiz # facc_out_x(): dmem_write of ext prec failed #
14565 1.2.4.2 wiz # #
14566 1.2.4.2 wiz # XREF **************************************************************** #
14567 1.2.4.2 wiz # _real_access() - exit through access error handler #
14568 1.2.4.2 wiz # #
14569 1.2.4.2 wiz # INPUT *************************************************************** #
14570 1.2.4.2 wiz # None #
14571 1.2.4.2 wiz # #
14572 1.2.4.2 wiz # OUTPUT ************************************************************** #
14573 1.2.4.2 wiz # None #
14574 1.2.4.2 wiz # #
14575 1.2.4.2 wiz # ALGORITHM *********************************************************** #
14576 1.2.4.2 wiz # Flow jumps here when an FP data fetch call gets an error #
14577 1.2.4.2 wiz # result. This means the operating system wants an access error frame #
14578 1.2.4.2 wiz # made out of the current exception stack frame. #
14579 1.2.4.2 wiz # So, we first call restore() which makes sure that any updated #
14580 1.2.4.2 wiz # -(an)+ register gets returned to its pre-exception value and then #
14581 1.2.4.2 wiz # we change the stack to an acess error stack frame. #
14582 1.2.4.2 wiz # #
14583 1.2.4.2 wiz #########################################################################
14584 1.2.4.2 wiz
14585 1.2.4.2 wiz facc_in_b:
14586 1.2.4.2 wiz movq.l &0x1,%d0 # one byte
14587 1.2.4.2 wiz bsr.w restore # fix An
14588 1.2.4.2 wiz
14589 1.2.4.2 wiz mov.w &0x0121,EXC_VOFF(%a6) # set FSLW
14590 1.2.4.2 wiz bra.w facc_finish
14591 1.2.4.2 wiz
14592 1.2.4.2 wiz facc_in_w:
14593 1.2.4.2 wiz movq.l &0x2,%d0 # two bytes
14594 1.2.4.2 wiz bsr.w restore # fix An
14595 1.2.4.2 wiz
14596 1.2.4.2 wiz mov.w &0x0141,EXC_VOFF(%a6) # set FSLW
14597 1.2.4.2 wiz bra.b facc_finish
14598 1.2.4.2 wiz
14599 1.2.4.2 wiz facc_in_l:
14600 1.2.4.2 wiz movq.l &0x4,%d0 # four bytes
14601 1.2.4.2 wiz bsr.w restore # fix An
14602 1.2.4.2 wiz
14603 1.2.4.2 wiz mov.w &0x0101,EXC_VOFF(%a6) # set FSLW
14604 1.2.4.2 wiz bra.b facc_finish
14605 1.2.4.2 wiz
14606 1.2.4.2 wiz facc_in_d:
14607 1.2.4.2 wiz movq.l &0x8,%d0 # eight bytes
14608 1.2.4.2 wiz bsr.w restore # fix An
14609 1.2.4.2 wiz
14610 1.2.4.2 wiz mov.w &0x0161,EXC_VOFF(%a6) # set FSLW
14611 1.2.4.2 wiz bra.b facc_finish
14612 1.2.4.2 wiz
14613 1.2.4.2 wiz facc_in_x:
14614 1.2.4.2 wiz movq.l &0xc,%d0 # twelve bytes
14615 1.2.4.2 wiz bsr.w restore # fix An
14616 1.2.4.2 wiz
14617 1.2.4.2 wiz mov.w &0x0161,EXC_VOFF(%a6) # set FSLW
14618 1.2.4.2 wiz bra.b facc_finish
14619 1.2.4.2 wiz
14620 1.2.4.2 wiz ################################################################
14621 1.2.4.2 wiz
14622 1.2.4.2 wiz facc_out_b:
14623 1.2.4.2 wiz movq.l &0x1,%d0 # one byte
14624 1.2.4.2 wiz bsr.w restore # restore An
14625 1.2.4.2 wiz
14626 1.2.4.2 wiz mov.w &0x00a1,EXC_VOFF(%a6) # set FSLW
14627 1.2.4.2 wiz bra.b facc_finish
14628 1.2.4.2 wiz
14629 1.2.4.2 wiz facc_out_w:
14630 1.2.4.2 wiz movq.l &0x2,%d0 # two bytes
14631 1.2.4.2 wiz bsr.w restore # restore An
14632 1.2.4.2 wiz
14633 1.2.4.2 wiz mov.w &0x00c1,EXC_VOFF(%a6) # set FSLW
14634 1.2.4.2 wiz bra.b facc_finish
14635 1.2.4.2 wiz
14636 1.2.4.2 wiz facc_out_l:
14637 1.2.4.2 wiz movq.l &0x4,%d0 # four bytes
14638 1.2.4.2 wiz bsr.w restore # restore An
14639 1.2.4.2 wiz
14640 1.2.4.2 wiz mov.w &0x0081,EXC_VOFF(%a6) # set FSLW
14641 1.2.4.2 wiz bra.b facc_finish
14642 1.2.4.2 wiz
14643 1.2.4.2 wiz facc_out_d:
14644 1.2.4.2 wiz movq.l &0x8,%d0 # eight bytes
14645 1.2.4.2 wiz bsr.w restore # restore An
14646 1.2.4.2 wiz
14647 1.2.4.2 wiz mov.w &0x00e1,EXC_VOFF(%a6) # set FSLW
14648 1.2.4.2 wiz bra.b facc_finish
14649 1.2.4.2 wiz
14650 1.2.4.2 wiz facc_out_x:
14651 1.2.4.2 wiz mov.l &0xc,%d0 # twelve bytes
14652 1.2.4.2 wiz bsr.w restore # restore An
14653 1.2.4.2 wiz
14654 1.2.4.2 wiz mov.w &0x00e1,EXC_VOFF(%a6) # set FSLW
14655 1.2.4.2 wiz
14656 1.2.4.2 wiz # here's where we actually create the access error frame from the
14657 1.2.4.2 wiz # current exception stack frame.
14658 1.2.4.2 wiz facc_finish:
14659 1.2.4.2 wiz mov.l USER_FPIAR(%a6),EXC_PC(%a6) # store current PC
14660 1.2.4.2 wiz
14661 1.2.4.2 wiz fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
14662 1.2.4.2 wiz fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
14663 1.2.4.2 wiz movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
14664 1.2.4.2 wiz
14665 1.2.4.2 wiz unlk %a6
14666 1.2.4.2 wiz
14667 1.2.4.2 wiz mov.l (%sp),-(%sp) # store SR, hi(PC)
14668 1.2.4.2 wiz mov.l 0x8(%sp),0x4(%sp) # store lo(PC)
14669 1.2.4.2 wiz mov.l 0xc(%sp),0x8(%sp) # store EA
14670 1.2.4.2 wiz mov.l &0x00000001,0xc(%sp) # store FSLW
14671 1.2.4.2 wiz mov.w 0x6(%sp),0xc(%sp) # fix FSLW (size)
14672 1.2.4.2 wiz mov.w &0x4008,0x6(%sp) # store voff
14673 1.2.4.2 wiz
14674 1.2.4.2 wiz btst &0x5,(%sp) # supervisor or user mode?
14675 1.2.4.2 wiz beq.b facc_out2 # user
14676 1.2.4.2 wiz bset &0x2,0xd(%sp) # set supervisor TM bit
14677 1.2.4.2 wiz
14678 1.2.4.2 wiz facc_out2:
14679 1.2.4.2 wiz bra.l _real_access
14680 1.2.4.2 wiz
14681 1.2.4.2 wiz ##################################################################
14682 1.2.4.2 wiz
14683 1.2.4.2 wiz # if the effective addressing mode was predecrement or postincrement,
14684 1.2.4.2 wiz # the emulation has already changed its value to the correct post-
14685 1.2.4.2 wiz # instruction value. but since we're exiting to the access error
14686 1.2.4.2 wiz # handler, then AN must be returned to its pre-instruction value.
14687 1.2.4.2 wiz # we do that here.
14688 1.2.4.2 wiz restore:
14689 1.2.4.2 wiz mov.b EXC_OPWORD+0x1(%a6),%d1
14690 1.2.4.2 wiz andi.b &0x38,%d1 # extract opmode
14691 1.2.4.2 wiz cmpi.b %d1,&0x18 # postinc?
14692 1.2.4.2 wiz beq.w rest_inc
14693 1.2.4.2 wiz cmpi.b %d1,&0x20 # predec?
14694 1.2.4.2 wiz beq.w rest_dec
14695 1.2.4.2 wiz rts
14696 1.2.4.2 wiz
14697 1.2.4.2 wiz rest_inc:
14698 1.2.4.2 wiz mov.b EXC_OPWORD+0x1(%a6),%d1
14699 1.2.4.2 wiz andi.w &0x0007,%d1 # fetch An
14700 1.2.4.2 wiz
14701 1.2.4.2 wiz mov.w (tbl_rest_inc.b,%pc,%d1.w*2),%d1
14702 1.2.4.2 wiz jmp (tbl_rest_inc.b,%pc,%d1.w*1)
14703 1.2.4.2 wiz
14704 1.2.4.2 wiz tbl_rest_inc:
14705 1.2.4.2 wiz short ri_a0 - tbl_rest_inc
14706 1.2.4.2 wiz short ri_a1 - tbl_rest_inc
14707 1.2.4.2 wiz short ri_a2 - tbl_rest_inc
14708 1.2.4.2 wiz short ri_a3 - tbl_rest_inc
14709 1.2.4.2 wiz short ri_a4 - tbl_rest_inc
14710 1.2.4.2 wiz short ri_a5 - tbl_rest_inc
14711 1.2.4.2 wiz short ri_a6 - tbl_rest_inc
14712 1.2.4.2 wiz short ri_a7 - tbl_rest_inc
14713 1.2.4.2 wiz
14714 1.2.4.2 wiz ri_a0:
14715 1.2.4.2 wiz sub.l %d0,EXC_DREGS+0x8(%a6) # fix stacked a0
14716 1.2.4.2 wiz rts
14717 1.2.4.2 wiz ri_a1:
14718 1.2.4.2 wiz sub.l %d0,EXC_DREGS+0xc(%a6) # fix stacked a1
14719 1.2.4.2 wiz rts
14720 1.2.4.2 wiz ri_a2:
14721 1.2.4.2 wiz sub.l %d0,%a2 # fix a2
14722 1.2.4.2 wiz rts
14723 1.2.4.2 wiz ri_a3:
14724 1.2.4.2 wiz sub.l %d0,%a3 # fix a3
14725 1.2.4.2 wiz rts
14726 1.2.4.2 wiz ri_a4:
14727 1.2.4.2 wiz sub.l %d0,%a4 # fix a4
14728 1.2.4.2 wiz rts
14729 1.2.4.2 wiz ri_a5:
14730 1.2.4.2 wiz sub.l %d0,%a5 # fix a5
14731 1.2.4.2 wiz rts
14732 1.2.4.2 wiz ri_a6:
14733 1.2.4.2 wiz sub.l %d0,(%a6) # fix stacked a6
14734 1.2.4.2 wiz rts
14735 1.2.4.2 wiz # if it's a fmove out instruction, we don't have to fix a7
14736 1.2.4.2 wiz # because we hadn't changed it yet. if it's an opclass two
14737 1.2.4.2 wiz # instruction (data moved in) and the exception was in supervisor
14738 1.2.4.2 wiz # mode, then also also wasn't updated. if it was user mode, then
14739 1.2.4.2 wiz # restore the correct a7 which is in the USP currently.
14740 1.2.4.2 wiz ri_a7:
14741 1.2.4.2 wiz cmpi.b EXC_VOFF(%a6),&0x30 # move in or out?
14742 1.2.4.2 wiz bne.b ri_a7_done # out
14743 1.2.4.2 wiz
14744 1.2.4.2 wiz btst &0x5,EXC_SR(%a6) # user or supervisor?
14745 1.2.4.2 wiz bne.b ri_a7_done # supervisor
14746 1.2.4.2 wiz movc %usp,%a0 # restore USP
14747 1.2.4.2 wiz sub.l %d0,%a0
14748 1.2.4.2 wiz movc %a0,%usp
14749 1.2.4.2 wiz ri_a7_done:
14750 1.2.4.2 wiz rts
14751 1.2.4.2 wiz
14752 1.2.4.2 wiz # need to invert adjustment value if the <ea> was predec
14753 1.2.4.2 wiz rest_dec:
14754 1.2.4.2 wiz neg.l %d0
14755 1.2.4.2 wiz bra.b rest_inc
14756