tree-wide: fix assorted typos all over the place
[linux-2.6.git] / arch / m68k / ifpsp060 / src / fpsp.S
1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
3 M68000 Hi-Performance Microprocessor Division
4 M68060 Software Package
5 Production Release P1.00 -- October 10, 1994
6
7 M68060 Software Package Copyright © 1993, 1994 Motorola Inc.  All rights reserved.
8
9 THE SOFTWARE is provided on an "AS IS" basis and without warranty.
10 To the maximum extent permitted by applicable law,
11 MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
12 INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
13 and any warranty against infringement with regard to the SOFTWARE
14 (INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
15
16 To the maximum extent permitted by applicable law,
17 IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
18 (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
19 BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
20 ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
21 Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
22
23 You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
24 so long as this entire notice is retained without alteration in any modified and/or
25 redistributed versions, and that such modified versions are clearly identified as such.
26 No licenses are granted by implication, estoppel or otherwise under any patents
27 or trademarks of Motorola, Inc.
28 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29 #
30 # freal.s:
31 #       This file is appended to the top of the 060FPSP package
32 # and contains the entry points into the package. The user, in
33 # effect, branches to one of the branch table entries located
34 # after _060FPSP_TABLE.
35 #       Also, subroutine stubs exist in this file (_fpsp_done for
36 # example) that are referenced by the FPSP package itself in order
37 # to call a given routine. The stub routine actually performs the
38 # callout. The FPSP code does a "bsr" to the stub routine. This
39 # extra layer of hierarchy adds a slight performance penalty but
40 # it makes the FPSP code easier to read and more mainatinable.
41 #
42
43 set     _off_bsun,      0x00
44 set     _off_snan,      0x04
45 set     _off_operr,     0x08
46 set     _off_ovfl,      0x0c
47 set     _off_unfl,      0x10
48 set     _off_dz,        0x14
49 set     _off_inex,      0x18
50 set     _off_fline,     0x1c
51 set     _off_fpu_dis,   0x20
52 set     _off_trap,      0x24
53 set     _off_trace,     0x28
54 set     _off_access,    0x2c
55 set     _off_done,      0x30
56
57 set     _off_imr,       0x40
58 set     _off_dmr,       0x44
59 set     _off_dmw,       0x48
60 set     _off_irw,       0x4c
61 set     _off_irl,       0x50
62 set     _off_drb,       0x54
63 set     _off_drw,       0x58
64 set     _off_drl,       0x5c
65 set     _off_dwb,       0x60
66 set     _off_dww,       0x64
67 set     _off_dwl,       0x68
68
69 _060FPSP_TABLE:
70
71 ###############################################################
72
73 # Here's the table of ENTRY POINTS for those linking the package.
74         bra.l           _fpsp_snan
75         short           0x0000
76         bra.l           _fpsp_operr
77         short           0x0000
78         bra.l           _fpsp_ovfl
79         short           0x0000
80         bra.l           _fpsp_unfl
81         short           0x0000
82         bra.l           _fpsp_dz
83         short           0x0000
84         bra.l           _fpsp_inex
85         short           0x0000
86         bra.l           _fpsp_fline
87         short           0x0000
88         bra.l           _fpsp_unsupp
89         short           0x0000
90         bra.l           _fpsp_effadd
91         short           0x0000
92
93         space           56
94
95 ###############################################################
96         global          _fpsp_done
97 _fpsp_done:
98         mov.l           %d0,-(%sp)
99         mov.l           (_060FPSP_TABLE-0x80+_off_done,%pc),%d0
100         pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
101         mov.l           0x4(%sp),%d0
102         rtd             &0x4
103
104         global          _real_ovfl
105 _real_ovfl:
106         mov.l           %d0,-(%sp)
107         mov.l           (_060FPSP_TABLE-0x80+_off_ovfl,%pc),%d0
108         pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
109         mov.l           0x4(%sp),%d0
110         rtd             &0x4
111
112         global          _real_unfl
113 _real_unfl:
114         mov.l           %d0,-(%sp)
115         mov.l           (_060FPSP_TABLE-0x80+_off_unfl,%pc),%d0
116         pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
117         mov.l           0x4(%sp),%d0
118         rtd             &0x4
119
120         global          _real_inex
121 _real_inex:
122         mov.l           %d0,-(%sp)
123         mov.l           (_060FPSP_TABLE-0x80+_off_inex,%pc),%d0
124         pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
125         mov.l           0x4(%sp),%d0
126         rtd             &0x4
127
128         global          _real_bsun
129 _real_bsun:
130         mov.l           %d0,-(%sp)
131         mov.l           (_060FPSP_TABLE-0x80+_off_bsun,%pc),%d0
132         pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
133         mov.l           0x4(%sp),%d0
134         rtd             &0x4
135
136         global          _real_operr
137 _real_operr:
138         mov.l           %d0,-(%sp)
139         mov.l           (_060FPSP_TABLE-0x80+_off_operr,%pc),%d0
140         pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
141         mov.l           0x4(%sp),%d0
142         rtd             &0x4
143
144         global          _real_snan
145 _real_snan:
146         mov.l           %d0,-(%sp)
147         mov.l           (_060FPSP_TABLE-0x80+_off_snan,%pc),%d0
148         pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
149         mov.l           0x4(%sp),%d0
150         rtd             &0x4
151
152         global          _real_dz
153 _real_dz:
154         mov.l           %d0,-(%sp)
155         mov.l           (_060FPSP_TABLE-0x80+_off_dz,%pc),%d0
156         pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
157         mov.l           0x4(%sp),%d0
158         rtd             &0x4
159
160         global          _real_fline
161 _real_fline:
162         mov.l           %d0,-(%sp)
163         mov.l           (_060FPSP_TABLE-0x80+_off_fline,%pc),%d0
164         pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
165         mov.l           0x4(%sp),%d0
166         rtd             &0x4
167
168         global          _real_fpu_disabled
169 _real_fpu_disabled:
170         mov.l           %d0,-(%sp)
171         mov.l           (_060FPSP_TABLE-0x80+_off_fpu_dis,%pc),%d0
172         pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
173         mov.l           0x4(%sp),%d0
174         rtd             &0x4
175
176         global          _real_trap
177 _real_trap:
178         mov.l           %d0,-(%sp)
179         mov.l           (_060FPSP_TABLE-0x80+_off_trap,%pc),%d0
180         pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
181         mov.l           0x4(%sp),%d0
182         rtd             &0x4
183
184         global          _real_trace
185 _real_trace:
186         mov.l           %d0,-(%sp)
187         mov.l           (_060FPSP_TABLE-0x80+_off_trace,%pc),%d0
188         pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
189         mov.l           0x4(%sp),%d0
190         rtd             &0x4
191
192         global          _real_access
193 _real_access:
194         mov.l           %d0,-(%sp)
195         mov.l           (_060FPSP_TABLE-0x80+_off_access,%pc),%d0
196         pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
197         mov.l           0x4(%sp),%d0
198         rtd             &0x4
199
200 #######################################
201
202         global          _imem_read
203 _imem_read:
204         mov.l           %d0,-(%sp)
205         mov.l           (_060FPSP_TABLE-0x80+_off_imr,%pc),%d0
206         pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
207         mov.l           0x4(%sp),%d0
208         rtd             &0x4
209
210         global          _dmem_read
211 _dmem_read:
212         mov.l           %d0,-(%sp)
213         mov.l           (_060FPSP_TABLE-0x80+_off_dmr,%pc),%d0
214         pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
215         mov.l           0x4(%sp),%d0
216         rtd             &0x4
217
218         global          _dmem_write
219 _dmem_write:
220         mov.l           %d0,-(%sp)
221         mov.l           (_060FPSP_TABLE-0x80+_off_dmw,%pc),%d0
222         pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
223         mov.l           0x4(%sp),%d0
224         rtd             &0x4
225
226         global          _imem_read_word
227 _imem_read_word:
228         mov.l           %d0,-(%sp)
229         mov.l           (_060FPSP_TABLE-0x80+_off_irw,%pc),%d0
230         pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
231         mov.l           0x4(%sp),%d0
232         rtd             &0x4
233
234         global          _imem_read_long
235 _imem_read_long:
236         mov.l           %d0,-(%sp)
237         mov.l           (_060FPSP_TABLE-0x80+_off_irl,%pc),%d0
238         pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
239         mov.l           0x4(%sp),%d0
240         rtd             &0x4
241
242         global          _dmem_read_byte
243 _dmem_read_byte:
244         mov.l           %d0,-(%sp)
245         mov.l           (_060FPSP_TABLE-0x80+_off_drb,%pc),%d0
246         pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
247         mov.l           0x4(%sp),%d0
248         rtd             &0x4
249
250         global          _dmem_read_word
251 _dmem_read_word:
252         mov.l           %d0,-(%sp)
253         mov.l           (_060FPSP_TABLE-0x80+_off_drw,%pc),%d0
254         pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
255         mov.l           0x4(%sp),%d0
256         rtd             &0x4
257
258         global          _dmem_read_long
259 _dmem_read_long:
260         mov.l           %d0,-(%sp)
261         mov.l           (_060FPSP_TABLE-0x80+_off_drl,%pc),%d0
262         pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
263         mov.l           0x4(%sp),%d0
264         rtd             &0x4
265
266         global          _dmem_write_byte
267 _dmem_write_byte:
268         mov.l           %d0,-(%sp)
269         mov.l           (_060FPSP_TABLE-0x80+_off_dwb,%pc),%d0
270         pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
271         mov.l           0x4(%sp),%d0
272         rtd             &0x4
273
274         global          _dmem_write_word
275 _dmem_write_word:
276         mov.l           %d0,-(%sp)
277         mov.l           (_060FPSP_TABLE-0x80+_off_dww,%pc),%d0
278         pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
279         mov.l           0x4(%sp),%d0
280         rtd             &0x4
281
282         global          _dmem_write_long
283 _dmem_write_long:
284         mov.l           %d0,-(%sp)
285         mov.l           (_060FPSP_TABLE-0x80+_off_dwl,%pc),%d0
286         pea.l           (_060FPSP_TABLE-0x80,%pc,%d0)
287         mov.l           0x4(%sp),%d0
288         rtd             &0x4
289
290 #
291 # This file contains a set of define statements for constants
292 # in order to promote readability within the corecode itself.
293 #
294
295 set LOCAL_SIZE,         192                     # stack frame size(bytes)
296 set LV,                 -LOCAL_SIZE             # stack offset
297
298 set EXC_SR,             0x4                     # stack status register
299 set EXC_PC,             0x6                     # stack pc
300 set EXC_VOFF,           0xa                     # stacked vector offset
301 set EXC_EA,             0xc                     # stacked <ea>
302
303 set EXC_FP,             0x0                     # frame pointer
304
305 set EXC_AREGS,          -68                     # offset of all address regs
306 set EXC_DREGS,          -100                    # offset of all data regs
307 set EXC_FPREGS,         -36                     # offset of all fp regs
308
309 set EXC_A7,             EXC_AREGS+(7*4)         # offset of saved a7
310 set OLD_A7,             EXC_AREGS+(6*4)         # extra copy of saved a7
311 set EXC_A6,             EXC_AREGS+(6*4)         # offset of saved a6
312 set EXC_A5,             EXC_AREGS+(5*4)
313 set EXC_A4,             EXC_AREGS+(4*4)
314 set EXC_A3,             EXC_AREGS+(3*4)
315 set EXC_A2,             EXC_AREGS+(2*4)
316 set EXC_A1,             EXC_AREGS+(1*4)
317 set EXC_A0,             EXC_AREGS+(0*4)
318 set EXC_D7,             EXC_DREGS+(7*4)
319 set EXC_D6,             EXC_DREGS+(6*4)
320 set EXC_D5,             EXC_DREGS+(5*4)
321 set EXC_D4,             EXC_DREGS+(4*4)
322 set EXC_D3,             EXC_DREGS+(3*4)
323 set EXC_D2,             EXC_DREGS+(2*4)
324 set EXC_D1,             EXC_DREGS+(1*4)
325 set EXC_D0,             EXC_DREGS+(0*4)
326
327 set EXC_FP0,            EXC_FPREGS+(0*12)       # offset of saved fp0
328 set EXC_FP1,            EXC_FPREGS+(1*12)       # offset of saved fp1
329 set EXC_FP2,            EXC_FPREGS+(2*12)       # offset of saved fp2 (not used)
330
331 set FP_SCR1,            LV+80                   # fp scratch 1
332 set FP_SCR1_EX,         FP_SCR1+0
333 set FP_SCR1_SGN,        FP_SCR1+2
334 set FP_SCR1_HI,         FP_SCR1+4
335 set FP_SCR1_LO,         FP_SCR1+8
336
337 set FP_SCR0,            LV+68                   # fp scratch 0
338 set FP_SCR0_EX,         FP_SCR0+0
339 set FP_SCR0_SGN,        FP_SCR0+2
340 set FP_SCR0_HI,         FP_SCR0+4
341 set FP_SCR0_LO,         FP_SCR0+8
342
343 set FP_DST,             LV+56                   # fp destination operand
344 set FP_DST_EX,          FP_DST+0
345 set FP_DST_SGN,         FP_DST+2
346 set FP_DST_HI,          FP_DST+4
347 set FP_DST_LO,          FP_DST+8
348
349 set FP_SRC,             LV+44                   # fp source operand
350 set FP_SRC_EX,          FP_SRC+0
351 set FP_SRC_SGN,         FP_SRC+2
352 set FP_SRC_HI,          FP_SRC+4
353 set FP_SRC_LO,          FP_SRC+8
354
355 set USER_FPIAR,         LV+40                   # FP instr address register
356
357 set USER_FPSR,          LV+36                   # FP status register
358 set FPSR_CC,            USER_FPSR+0             # FPSR condition codes
359 set FPSR_QBYTE,         USER_FPSR+1             # FPSR qoutient byte
360 set FPSR_EXCEPT,        USER_FPSR+2             # FPSR exception status byte
361 set FPSR_AEXCEPT,       USER_FPSR+3             # FPSR accrued exception byte
362
363 set USER_FPCR,          LV+32                   # FP control register
364 set FPCR_ENABLE,        USER_FPCR+2             # FPCR exception enable
365 set FPCR_MODE,          USER_FPCR+3             # FPCR rounding mode control
366
367 set L_SCR3,             LV+28                   # integer scratch 3
368 set L_SCR2,             LV+24                   # integer scratch 2
369 set L_SCR1,             LV+20                   # integer scratch 1
370
371 set STORE_FLG,          LV+19                   # flag: operand store (ie. not fcmp/ftst)
372
373 set EXC_TEMP2,          LV+24                   # temporary space
374 set EXC_TEMP,           LV+16                   # temporary space
375
376 set DTAG,               LV+15                   # destination operand type
377 set STAG,               LV+14                   # source operand type
378
379 set SPCOND_FLG,         LV+10                   # flag: special case (see below)
380
381 set EXC_CC,             LV+8                    # saved condition codes
382 set EXC_EXTWPTR,        LV+4                    # saved current PC (active)
383 set EXC_EXTWORD,        LV+2                    # saved extension word
384 set EXC_CMDREG,         LV+2                    # saved extension word
385 set EXC_OPWORD,         LV+0                    # saved operation word
386
387 ################################
388
389 # Helpful macros
390
391 set FTEMP,              0                       # offsets within an
392 set FTEMP_EX,           0                       # extended precision
393 set FTEMP_SGN,          2                       # value saved in memory.
394 set FTEMP_HI,           4
395 set FTEMP_LO,           8
396 set FTEMP_GRS,          12
397
398 set LOCAL,              0                       # offsets within an
399 set LOCAL_EX,           0                       # extended precision
400 set LOCAL_SGN,          2                       # value saved in memory.
401 set LOCAL_HI,           4
402 set LOCAL_LO,           8
403 set LOCAL_GRS,          12
404
405 set DST,                0                       # offsets within an
406 set DST_EX,             0                       # extended precision
407 set DST_HI,             4                       # value saved in memory.
408 set DST_LO,             8
409
410 set SRC,                0                       # offsets within an
411 set SRC_EX,             0                       # extended precision
412 set SRC_HI,             4                       # value saved in memory.
413 set SRC_LO,             8
414
415 set SGL_LO,             0x3f81                  # min sgl prec exponent
416 set SGL_HI,             0x407e                  # max sgl prec exponent
417 set DBL_LO,             0x3c01                  # min dbl prec exponent
418 set DBL_HI,             0x43fe                  # max dbl prec exponent
419 set EXT_LO,             0x0                     # min ext prec exponent
420 set EXT_HI,             0x7ffe                  # max ext prec exponent
421
422 set EXT_BIAS,           0x3fff                  # extended precision bias
423 set SGL_BIAS,           0x007f                  # single precision bias
424 set DBL_BIAS,           0x03ff                  # double precision bias
425
426 set NORM,               0x00                    # operand type for STAG/DTAG
427 set ZERO,               0x01                    # operand type for STAG/DTAG
428 set INF,                0x02                    # operand type for STAG/DTAG
429 set QNAN,               0x03                    # operand type for STAG/DTAG
430 set DENORM,             0x04                    # operand type for STAG/DTAG
431 set SNAN,               0x05                    # operand type for STAG/DTAG
432 set UNNORM,             0x06                    # operand type for STAG/DTAG
433
434 ##################
435 # FPSR/FPCR bits #
436 ##################
437 set neg_bit,            0x3                     # negative result
438 set z_bit,              0x2                     # zero result
439 set inf_bit,            0x1                     # infinite result
440 set nan_bit,            0x0                     # NAN result
441
442 set q_sn_bit,           0x7                     # sign bit of quotient byte
443
444 set bsun_bit,           7                       # branch on unordered
445 set snan_bit,           6                       # signalling NAN
446 set operr_bit,          5                       # operand error
447 set ovfl_bit,           4                       # overflow
448 set unfl_bit,           3                       # underflow
449 set dz_bit,             2                       # divide by zero
450 set inex2_bit,          1                       # inexact result 2
451 set inex1_bit,          0                       # inexact result 1
452
453 set aiop_bit,           7                       # accrued inexact operation bit
454 set aovfl_bit,          6                       # accrued overflow bit
455 set aunfl_bit,          5                       # accrued underflow bit
456 set adz_bit,            4                       # accrued dz bit
457 set ainex_bit,          3                       # accrued inexact bit
458
459 #############################
460 # FPSR individual bit masks #
461 #############################
462 set neg_mask,           0x08000000              # negative bit mask (lw)
463 set inf_mask,           0x02000000              # infinity bit mask (lw)
464 set z_mask,             0x04000000              # zero bit mask (lw)
465 set nan_mask,           0x01000000              # nan bit mask (lw)
466
467 set neg_bmask,          0x08                    # negative bit mask (byte)
468 set inf_bmask,          0x02                    # infinity bit mask (byte)
469 set z_bmask,            0x04                    # zero bit mask (byte)
470 set nan_bmask,          0x01                    # nan bit mask (byte)
471
472 set bsun_mask,          0x00008000              # bsun exception mask
473 set snan_mask,          0x00004000              # snan exception mask
474 set operr_mask,         0x00002000              # operr exception mask
475 set ovfl_mask,          0x00001000              # overflow exception mask
476 set unfl_mask,          0x00000800              # underflow exception mask
477 set dz_mask,            0x00000400              # dz exception mask
478 set inex2_mask,         0x00000200              # inex2 exception mask
479 set inex1_mask,         0x00000100              # inex1 exception mask
480
481 set aiop_mask,          0x00000080              # accrued illegal operation
482 set aovfl_mask,         0x00000040              # accrued overflow
483 set aunfl_mask,         0x00000020              # accrued underflow
484 set adz_mask,           0x00000010              # accrued divide by zero
485 set ainex_mask,         0x00000008              # accrued inexact
486
487 ######################################
488 # FPSR combinations used in the FPSP #
489 ######################################
490 set dzinf_mask,         inf_mask+dz_mask+adz_mask
491 set opnan_mask,         nan_mask+operr_mask+aiop_mask
492 set nzi_mask,           0x01ffffff              #clears N, Z, and I
493 set unfinx_mask,        unfl_mask+inex2_mask+aunfl_mask+ainex_mask
494 set unf2inx_mask,       unfl_mask+inex2_mask+ainex_mask
495 set ovfinx_mask,        ovfl_mask+inex2_mask+aovfl_mask+ainex_mask
496 set inx1a_mask,         inex1_mask+ainex_mask
497 set inx2a_mask,         inex2_mask+ainex_mask
498 set snaniop_mask,       nan_mask+snan_mask+aiop_mask
499 set snaniop2_mask,      snan_mask+aiop_mask
500 set naniop_mask,        nan_mask+aiop_mask
501 set neginf_mask,        neg_mask+inf_mask
502 set infaiop_mask,       inf_mask+aiop_mask
503 set negz_mask,          neg_mask+z_mask
504 set opaop_mask,         operr_mask+aiop_mask
505 set unfl_inx_mask,      unfl_mask+aunfl_mask+ainex_mask
506 set ovfl_inx_mask,      ovfl_mask+aovfl_mask+ainex_mask
507
508 #########
509 # misc. #
510 #########
511 set rnd_stky_bit,       29                      # stky bit pos in longword
512
513 set sign_bit,           0x7                     # sign bit
514 set signan_bit,         0x6                     # signalling nan bit
515
516 set sgl_thresh,         0x3f81                  # minimum sgl exponent
517 set dbl_thresh,         0x3c01                  # minimum dbl exponent
518
519 set x_mode,             0x0                     # extended precision
520 set s_mode,             0x4                     # single precision
521 set d_mode,             0x8                     # double precision
522
523 set rn_mode,            0x0                     # round-to-nearest
524 set rz_mode,            0x1                     # round-to-zero
525 set rm_mode,            0x2                     # round-tp-minus-infinity
526 set rp_mode,            0x3                     # round-to-plus-infinity
527
528 set mantissalen,        64                      # length of mantissa in bits
529
530 set BYTE,               1                       # len(byte) == 1 byte
531 set WORD,               2                       # len(word) == 2 bytes
532 set LONG,               4                       # len(longword) == 2 bytes
533
534 set BSUN_VEC,           0xc0                    # bsun    vector offset
535 set INEX_VEC,           0xc4                    # inexact vector offset
536 set DZ_VEC,             0xc8                    # dz      vector offset
537 set UNFL_VEC,           0xcc                    # unfl    vector offset
538 set OPERR_VEC,          0xd0                    # operr   vector offset
539 set OVFL_VEC,           0xd4                    # ovfl    vector offset
540 set SNAN_VEC,           0xd8                    # snan    vector offset
541
542 ###########################
543 # SPecial CONDition FLaGs #
544 ###########################
545 set ftrapcc_flg,        0x01                    # flag bit: ftrapcc exception
546 set fbsun_flg,          0x02                    # flag bit: bsun exception
547 set mia7_flg,           0x04                    # flag bit: (a7)+ <ea>
548 set mda7_flg,           0x08                    # flag bit: -(a7) <ea>
549 set fmovm_flg,          0x40                    # flag bit: fmovm instruction
550 set immed_flg,          0x80                    # flag bit: &<data> <ea>
551
552 set ftrapcc_bit,        0x0
553 set fbsun_bit,          0x1
554 set mia7_bit,           0x2
555 set mda7_bit,           0x3
556 set immed_bit,          0x7
557
558 ##################################
559 # TRANSCENDENTAL "LAST-OP" FLAGS #
560 ##################################
561 set FMUL_OP,            0x0                     # fmul instr performed last
562 set FDIV_OP,            0x1                     # fdiv performed last
563 set FADD_OP,            0x2                     # fadd performed last
564 set FMOV_OP,            0x3                     # fmov performed last
565
566 #############
567 # CONSTANTS #
568 #############
569 T1:     long            0x40C62D38,0xD3D64634   # 16381 LOG2 LEAD
570 T2:     long            0x3D6F90AE,0xB1E75CC7   # 16381 LOG2 TRAIL
571
572 PI:     long            0x40000000,0xC90FDAA2,0x2168C235,0x00000000
573 PIBY2:  long            0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
574
575 TWOBYPI:
576         long            0x3FE45F30,0x6DC9C883
577
578 #########################################################################
579 # XDEF **************************************************************** #
580 #       _fpsp_ovfl(): 060FPSP entry point for FP Overflow exception.    #
581 #                                                                       #
582 #       This handler should be the first code executed upon taking the  #
583 #       FP Overflow exception in an operating system.                   #
584 #                                                                       #
585 # XREF **************************************************************** #
586 #       _imem_read_long() - read instruction longword                   #
587 #       fix_skewed_ops() - adjust src operand in fsave frame            #
588 #       set_tag_x() - determine optype of src/dst operands              #
589 #       store_fpreg() - store opclass 0 or 2 result to FP regfile       #
590 #       unnorm_fix() - change UNNORM operands to NORM or ZERO           #
591 #       load_fpn2() - load dst operand from FP regfile                  #
592 #       fout() - emulate an opclass 3 instruction                       #
593 #       tbl_unsupp - add of table of emulation routines for opclass 0,2 #
594 #       _fpsp_done() - "callout" for 060FPSP exit (all work done!)      #
595 #       _real_ovfl() - "callout" for Overflow exception enabled code    #
596 #       _real_inex() - "callout" for Inexact exception enabled code     #
597 #       _real_trace() - "callout" for Trace exception code              #
598 #                                                                       #
599 # INPUT *************************************************************** #
600 #       - The system stack contains the FP Ovfl exception stack frame   #
601 #       - The fsave frame contains the source operand                   #
602 #                                                                       #
603 # OUTPUT ************************************************************** #
604 #       Overflow Exception enabled:                                     #
605 #       - The system stack is unchanged                                 #
606 #       - The fsave frame contains the adjusted src op for opclass 0,2  #
607 #       Overflow Exception disabled:                                    #
608 #       - The system stack is unchanged                                 #
609 #       - The "exception present" flag in the fsave frame is cleared    #
610 #                                                                       #
611 # ALGORITHM *********************************************************** #
612 #       On the 060, if an FP overflow is present as the result of any   #
613 # instruction, the 060 will take an overflow exception whether the      #
614 # exception is enabled or disabled in the FPCR. For the disabled case,  #
615 # This handler emulates the instruction to determine what the correct   #
616 # default result should be for the operation. This default result is    #
617 # then stored in either the FP regfile, data regfile, or memory.        #
618 # Finally, the handler exits through the "callout" _fpsp_done()         #
619 # denoting that no exceptional conditions exist within the machine.     #
620 #       If the exception is enabled, then this handler must create the  #
621 # exceptional operand and plave it in the fsave state frame, and store  #
622 # the default result (only if the instruction is opclass 3). For        #
623 # exceptions enabled, this handler must exit through the "callout"      #
624 # _real_ovfl() so that the operating system enabled overflow handler    #
625 # can handle this case.                                                 #
626 #       Two other conditions exist. First, if overflow was disabled     #
627 # but the inexact exception was enabled, this handler must exit         #
628 # through the "callout" _real_inex() regardless of whether the result   #
629 # was inexact.                                                          #
630 #       Also, in the case of an opclass three instruction where         #
631 # overflow was disabled and the trace exception was enabled, this       #
632 # handler must exit through the "callout" _real_trace().                #
633 #                                                                       #
634 #########################################################################
635
636         global          _fpsp_ovfl
637 _fpsp_ovfl:
638
639 #$#     sub.l           &24,%sp                 # make room for src/dst
640
641         link.w          %a6,&-LOCAL_SIZE        # init stack frame
642
643         fsave           FP_SRC(%a6)             # grab the "busy" frame
644
645         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
646         fmovm.l         %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
647         fmovm.x         &0xc0,EXC_FPREGS(%a6)   # save fp0-fp1 on stack
648
649 # the FPIAR holds the "current PC" of the faulting instruction
650         mov.l           USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
651         mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
652         addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
653         bsr.l           _imem_read_long         # fetch the instruction words
654         mov.l           %d0,EXC_OPWORD(%a6)
655
656 ##############################################################################
657
658         btst            &0x5,EXC_CMDREG(%a6)    # is instr an fmove out?
659         bne.w           fovfl_out
660
661
662         lea             FP_SRC(%a6),%a0         # pass: ptr to src op
663         bsr.l           fix_skewed_ops          # fix src op
664
665 # since, I believe, only NORMs and DENORMs can come through here,
666 # maybe we can avoid the subroutine call.
667         lea             FP_SRC(%a6),%a0         # pass: ptr to src op
668         bsr.l           set_tag_x               # tag the operand type
669         mov.b           %d0,STAG(%a6)           # maybe NORM,DENORM
670
671 # bit five of the fp extension word separates the monadic and dyadic operations
672 # that can pass through fpsp_ovfl(). remember that fcmp, ftst, and fsincos
673 # will never take this exception.
674         btst            &0x5,1+EXC_CMDREG(%a6)  # is operation monadic or dyadic?
675         beq.b           fovfl_extract           # monadic
676
677         bfextu          EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
678         bsr.l           load_fpn2               # load dst into FP_DST
679
680         lea             FP_DST(%a6),%a0         # pass: ptr to dst op
681         bsr.l           set_tag_x               # tag the operand type
682         cmpi.b          %d0,&UNNORM             # is operand an UNNORM?
683         bne.b           fovfl_op2_done          # no
684         bsr.l           unnorm_fix              # yes; convert to NORM,DENORM,or ZERO
685 fovfl_op2_done:
686         mov.b           %d0,DTAG(%a6)           # save dst optype tag
687
688 fovfl_extract:
689
690 #$#     mov.l           FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
691 #$#     mov.l           FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
692 #$#     mov.l           FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
693 #$#     mov.l           FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6)
694 #$#     mov.l           FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6)
695 #$#     mov.l           FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6)
696
697         clr.l           %d0
698         mov.b           FPCR_MODE(%a6),%d0      # pass rnd prec/mode
699
700         mov.b           1+EXC_CMDREG(%a6),%d1
701         andi.w          &0x007f,%d1             # extract extension
702
703         andi.l          &0x00ff01ff,USER_FPSR(%a6) # zero all but accured field
704
705         fmov.l          &0x0,%fpcr              # zero current control regs
706         fmov.l          &0x0,%fpsr
707
708         lea             FP_SRC(%a6),%a0
709         lea             FP_DST(%a6),%a1
710
711 # maybe we can make these entry points ONLY the OVFL entry points of each routine.
712         mov.l           (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
713         jsr             (tbl_unsupp.l,%pc,%d1.l*1)
714
715 # the operation has been emulated. the result is in fp0.
716 # the EXOP, if an exception occurred, is in fp1.
717 # we must save the default result regardless of whether
718 # traps are enabled or disabled.
719         bfextu          EXC_CMDREG(%a6){&6:&3},%d0
720         bsr.l           store_fpreg
721
722 # the exceptional possibilities we have left ourselves with are ONLY overflow
723 # and inexact. and, the inexact is such that overflow occurred and was disabled
724 # but inexact was enabled.
725         btst            &ovfl_bit,FPCR_ENABLE(%a6)
726         bne.b           fovfl_ovfl_on
727
728         btst            &inex2_bit,FPCR_ENABLE(%a6)
729         bne.b           fovfl_inex_on
730
731         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
732         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
733         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
734
735         unlk            %a6
736 #$#     add.l           &24,%sp
737         bra.l           _fpsp_done
738
739 # overflow is enabled AND overflow, of course, occurred. so, we have the EXOP
740 # in fp1. now, simply jump to _real_ovfl()!
741 fovfl_ovfl_on:
742         fmovm.x         &0x40,FP_SRC(%a6)       # save EXOP (fp1) to stack
743
744         mov.w           &0xe005,2+FP_SRC(%a6)   # save exc status
745
746         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
747         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
748         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
749
750         frestore        FP_SRC(%a6)             # do this after fmovm,other f<op>s!
751
752         unlk            %a6
753
754         bra.l           _real_ovfl
755
756 # overflow occurred but is disabled. meanwhile, inexact is enabled. Therefore,
757 # we must jump to real_inex().
758 fovfl_inex_on:
759
760         fmovm.x         &0x40,FP_SRC(%a6)       # save EXOP (fp1) to stack
761
762         mov.b           &0xc4,1+EXC_VOFF(%a6)   # vector offset = 0xc4
763         mov.w           &0xe001,2+FP_SRC(%a6)   # save exc status
764
765         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
766         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
767         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
768
769         frestore        FP_SRC(%a6)             # do this after fmovm,other f<op>s!
770
771         unlk            %a6
772
773         bra.l           _real_inex
774
775 ########################################################################
776 fovfl_out:
777
778
779 #$#     mov.l           FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
780 #$#     mov.l           FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
781 #$#     mov.l           FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
782
783 # the src operand is definitely a NORM(!), so tag it as such
784         mov.b           &NORM,STAG(%a6)         # set src optype tag
785
786         clr.l           %d0
787         mov.b           FPCR_MODE(%a6),%d0      # pass rnd prec/mode
788
789         and.l           &0xffff00ff,USER_FPSR(%a6) # zero all but accured field
790
791         fmov.l          &0x0,%fpcr              # zero current control regs
792         fmov.l          &0x0,%fpsr
793
794         lea             FP_SRC(%a6),%a0         # pass ptr to src operand
795
796         bsr.l           fout
797
798         btst            &ovfl_bit,FPCR_ENABLE(%a6)
799         bne.w           fovfl_ovfl_on
800
801         btst            &inex2_bit,FPCR_ENABLE(%a6)
802         bne.w           fovfl_inex_on
803
804         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
805         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
806         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
807
808         unlk            %a6
809 #$#     add.l           &24,%sp
810
811         btst            &0x7,(%sp)              # is trace on?
812         beq.l           _fpsp_done              # no
813
814         fmov.l          %fpiar,0x8(%sp)         # "Current PC" is in FPIAR
815         mov.w           &0x2024,0x6(%sp)        # stk fmt = 0x2; voff = 0x024
816         bra.l           _real_trace
817
818 #########################################################################
819 # XDEF **************************************************************** #
820 #       _fpsp_unfl(): 060FPSP entry point for FP Underflow exception.   #
821 #                                                                       #
822 #       This handler should be the first code executed upon taking the  #
823 #       FP Underflow exception in an operating system.                  #
824 #                                                                       #
825 # XREF **************************************************************** #
826 #       _imem_read_long() - read instruction longword                   #
827 #       fix_skewed_ops() - adjust src operand in fsave frame            #
828 #       set_tag_x() - determine optype of src/dst operands              #
829 #       store_fpreg() - store opclass 0 or 2 result to FP regfile       #
830 #       unnorm_fix() - change UNNORM operands to NORM or ZERO           #
831 #       load_fpn2() - load dst operand from FP regfile                  #
832 #       fout() - emulate an opclass 3 instruction                       #
833 #       tbl_unsupp - add of table of emulation routines for opclass 0,2 #
834 #       _fpsp_done() - "callout" for 060FPSP exit (all work done!)      #
835 #       _real_ovfl() - "callout" for Overflow exception enabled code    #
836 #       _real_inex() - "callout" for Inexact exception enabled code     #
837 #       _real_trace() - "callout" for Trace exception code              #
838 #                                                                       #
839 # INPUT *************************************************************** #
840 #       - The system stack contains the FP Unfl exception stack frame   #
841 #       - The fsave frame contains the source operand                   #
842 #                                                                       #
843 # OUTPUT ************************************************************** #
844 #       Underflow Exception enabled:                                    #
845 #       - The system stack is unchanged                                 #
846 #       - The fsave frame contains the adjusted src op for opclass 0,2  #
847 #       Underflow Exception disabled:                                   #
848 #       - The system stack is unchanged                                 #
849 #       - The "exception present" flag in the fsave frame is cleared    #
850 #                                                                       #
851 # ALGORITHM *********************************************************** #
852 #       On the 060, if an FP underflow is present as the result of any  #
853 # instruction, the 060 will take an underflow exception whether the     #
854 # exception is enabled or disabled in the FPCR. For the disabled case,  #
855 # This handler emulates the instruction to determine what the correct   #
856 # default result should be for the operation. This default result is    #
857 # then stored in either the FP regfile, data regfile, or memory.        #
858 # Finally, the handler exits through the "callout" _fpsp_done()         #
859 # denoting that no exceptional conditions exist within the machine.     #
860 #       If the exception is enabled, then this handler must create the  #
861 # exceptional operand and plave it in the fsave state frame, and store  #
862 # the default result (only if the instruction is opclass 3). For        #
863 # exceptions enabled, this handler must exit through the "callout"      #
864 # _real_unfl() so that the operating system enabled overflow handler    #
865 # can handle this case.                                                 #
866 #       Two other conditions exist. First, if underflow was disabled    #
867 # but the inexact exception was enabled and the result was inexact,     #
868 # this handler must exit through the "callout" _real_inex().            #
869 # was inexact.                                                          #
870 #       Also, in the case of an opclass three instruction where         #
871 # underflow was disabled and the trace exception was enabled, this      #
872 # handler must exit through the "callout" _real_trace().                #
873 #                                                                       #
874 #########################################################################
875
876         global          _fpsp_unfl
877 _fpsp_unfl:
878
879 #$#     sub.l           &24,%sp                 # make room for src/dst
880
881         link.w          %a6,&-LOCAL_SIZE        # init stack frame
882
883         fsave           FP_SRC(%a6)             # grab the "busy" frame
884
885         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
886         fmovm.l         %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
887         fmovm.x         &0xc0,EXC_FPREGS(%a6)   # save fp0-fp1 on stack
888
889 # the FPIAR holds the "current PC" of the faulting instruction
890         mov.l           USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
891         mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
892         addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
893         bsr.l           _imem_read_long         # fetch the instruction words
894         mov.l           %d0,EXC_OPWORD(%a6)
895
896 ##############################################################################
897
898         btst            &0x5,EXC_CMDREG(%a6)    # is instr an fmove out?
899         bne.w           funfl_out
900
901
902         lea             FP_SRC(%a6),%a0         # pass: ptr to src op
903         bsr.l           fix_skewed_ops          # fix src op
904
905         lea             FP_SRC(%a6),%a0         # pass: ptr to src op
906         bsr.l           set_tag_x               # tag the operand type
907         mov.b           %d0,STAG(%a6)           # maybe NORM,DENORM
908
909 # bit five of the fp ext word separates the monadic and dyadic operations
910 # that can pass through fpsp_unfl(). remember that fcmp, and ftst
911 # will never take this exception.
912         btst            &0x5,1+EXC_CMDREG(%a6)  # is op monadic or dyadic?
913         beq.b           funfl_extract           # monadic
914
915 # now, what's left that's not dyadic is fsincos. we can distinguish it
916 # from all dyadics by the '0110xxx pattern
917         btst            &0x4,1+EXC_CMDREG(%a6)  # is op an fsincos?
918         bne.b           funfl_extract           # yes
919
920         bfextu          EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
921         bsr.l           load_fpn2               # load dst into FP_DST
922
923         lea             FP_DST(%a6),%a0         # pass: ptr to dst op
924         bsr.l           set_tag_x               # tag the operand type
925         cmpi.b          %d0,&UNNORM             # is operand an UNNORM?
926         bne.b           funfl_op2_done          # no
927         bsr.l           unnorm_fix              # yes; convert to NORM,DENORM,or ZERO
928 funfl_op2_done:
929         mov.b           %d0,DTAG(%a6)           # save dst optype tag
930
931 funfl_extract:
932
933 #$#     mov.l           FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
934 #$#     mov.l           FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
935 #$#     mov.l           FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
936 #$#     mov.l           FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6)
937 #$#     mov.l           FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6)
938 #$#     mov.l           FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6)
939
940         clr.l           %d0
941         mov.b           FPCR_MODE(%a6),%d0      # pass rnd prec/mode
942
943         mov.b           1+EXC_CMDREG(%a6),%d1
944         andi.w          &0x007f,%d1             # extract extension
945
946         andi.l          &0x00ff01ff,USER_FPSR(%a6)
947
948         fmov.l          &0x0,%fpcr              # zero current control regs
949         fmov.l          &0x0,%fpsr
950
951         lea             FP_SRC(%a6),%a0
952         lea             FP_DST(%a6),%a1
953
954 # maybe we can make these entry points ONLY the OVFL entry points of each routine.
955         mov.l           (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
956         jsr             (tbl_unsupp.l,%pc,%d1.l*1)
957
958         bfextu          EXC_CMDREG(%a6){&6:&3},%d0
959         bsr.l           store_fpreg
960
961 # The `060 FPU multiplier hardware is such that if the result of a
962 # multiply operation is the smallest possible normalized number
963 # (0x00000000_80000000_00000000), then the machine will take an
964 # underflow exception. Since this is incorrect, we need to check
965 # if our emulation, after re-doing the operation, decided that
966 # no underflow was called for. We do these checks only in
967 # funfl_{unfl,inex}_on() because w/ both exceptions disabled, this
968 # special case will simply exit gracefully with the correct result.
969
970 # the exceptional possibilities we have left ourselves with are ONLY overflow
971 # and inexact. and, the inexact is such that overflow occurred and was disabled
972 # but inexact was enabled.
973         btst            &unfl_bit,FPCR_ENABLE(%a6)
974         bne.b           funfl_unfl_on
975
976 funfl_chkinex:
977         btst            &inex2_bit,FPCR_ENABLE(%a6)
978         bne.b           funfl_inex_on
979
980 funfl_exit:
981         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
982         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
983         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
984
985         unlk            %a6
986 #$#     add.l           &24,%sp
987         bra.l           _fpsp_done
988
989 # overflow is enabled AND overflow, of course, occurred. so, we have the EXOP
990 # in fp1 (don't forget to save fp0). what to do now?
991 # well, we simply have to get to go to _real_unfl()!
992 funfl_unfl_on:
993
994 # The `060 FPU multiplier hardware is such that if the result of a
995 # multiply operation is the smallest possible normalized number
996 # (0x00000000_80000000_00000000), then the machine will take an
997 # underflow exception. Since this is incorrect, we check here to see
998 # if our emulation, after re-doing the operation, decided that
999 # no underflow was called for.
1000         btst            &unfl_bit,FPSR_EXCEPT(%a6)
1001         beq.w           funfl_chkinex
1002
1003 funfl_unfl_on2:
1004         fmovm.x         &0x40,FP_SRC(%a6)       # save EXOP (fp1) to stack
1005
1006         mov.w           &0xe003,2+FP_SRC(%a6)   # save exc status
1007
1008         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
1009         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1010         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1011
1012         frestore        FP_SRC(%a6)             # do this after fmovm,other f<op>s!
1013
1014         unlk            %a6
1015
1016         bra.l           _real_unfl
1017
1018 # underflow occurred but is disabled. meanwhile, inexact is enabled. Therefore,
1019 # we must jump to real_inex().
1020 funfl_inex_on:
1021
1022 # The `060 FPU multiplier hardware is such that if the result of a
1023 # multiply operation is the smallest possible normalized number
1024 # (0x00000000_80000000_00000000), then the machine will take an
1025 # underflow exception.
1026 # But, whether bogus or not, if inexact is enabled AND it occurred,
1027 # then we have to branch to real_inex.
1028
1029         btst            &inex2_bit,FPSR_EXCEPT(%a6)
1030         beq.w           funfl_exit
1031
1032 funfl_inex_on2:
1033
1034         fmovm.x         &0x40,FP_SRC(%a6)       # save EXOP to stack
1035
1036         mov.b           &0xc4,1+EXC_VOFF(%a6)   # vector offset = 0xc4
1037         mov.w           &0xe001,2+FP_SRC(%a6)   # save exc status
1038
1039         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
1040         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1041         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1042
1043         frestore        FP_SRC(%a6)             # do this after fmovm,other f<op>s!
1044
1045         unlk            %a6
1046
1047         bra.l           _real_inex
1048
1049 #######################################################################
1050 funfl_out:
1051
1052
1053 #$#     mov.l           FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
1054 #$#     mov.l           FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
1055 #$#     mov.l           FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
1056
1057 # the src operand is definitely a NORM(!), so tag it as such
1058         mov.b           &NORM,STAG(%a6)         # set src optype tag
1059
1060         clr.l           %d0
1061         mov.b           FPCR_MODE(%a6),%d0      # pass rnd prec/mode
1062
1063         and.l           &0xffff00ff,USER_FPSR(%a6) # zero all but accured field
1064
1065         fmov.l          &0x0,%fpcr              # zero current control regs
1066         fmov.l          &0x0,%fpsr
1067
1068         lea             FP_SRC(%a6),%a0         # pass ptr to src operand
1069
1070         bsr.l           fout
1071
1072         btst            &unfl_bit,FPCR_ENABLE(%a6)
1073         bne.w           funfl_unfl_on2
1074
1075         btst            &inex2_bit,FPCR_ENABLE(%a6)
1076         bne.w           funfl_inex_on2
1077
1078         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
1079         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1080         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1081
1082         unlk            %a6
1083 #$#     add.l           &24,%sp
1084
1085         btst            &0x7,(%sp)              # is trace on?
1086         beq.l           _fpsp_done              # no
1087
1088         fmov.l          %fpiar,0x8(%sp)         # "Current PC" is in FPIAR
1089         mov.w           &0x2024,0x6(%sp)        # stk fmt = 0x2; voff = 0x024
1090         bra.l           _real_trace
1091
1092 #########################################################################
1093 # XDEF **************************************************************** #
1094 #       _fpsp_unsupp(): 060FPSP entry point for FP "Unimplemented       #
1095 #                       Data Type" exception.                           #
1096 #                                                                       #
1097 #       This handler should be the first code executed upon taking the  #
1098 #       FP Unimplemented Data Type exception in an operating system.    #
1099 #                                                                       #
1100 # XREF **************************************************************** #
1101 #       _imem_read_{word,long}() - read instruction word/longword       #
1102 #       fix_skewed_ops() - adjust src operand in fsave frame            #
1103 #       set_tag_x() - determine optype of src/dst operands              #
1104 #       store_fpreg() - store opclass 0 or 2 result to FP regfile       #
1105 #       unnorm_fix() - change UNNORM operands to NORM or ZERO           #
1106 #       load_fpn2() - load dst operand from FP regfile                  #
1107 #       load_fpn1() - load src operand from FP regfile                  #
1108 #       fout() - emulate an opclass 3 instruction                       #
1109 #       tbl_unsupp - add of table of emulation routines for opclass 0,2 #
1110 #       _real_inex() - "callout" to operating system inexact handler    #
1111 #       _fpsp_done() - "callout" for exit; work all done                #
1112 #       _real_trace() - "callout" for Trace enabled exception           #
1113 #       funimp_skew() - adjust fsave src ops to "incorrect" value       #
1114 #       _real_snan() - "callout" for SNAN exception                     #
1115 #       _real_operr() - "callout" for OPERR exception                   #
1116 #       _real_ovfl() - "callout" for OVFL exception                     #
1117 #       _real_unfl() - "callout" for UNFL exception                     #
1118 #       get_packed() - fetch packed operand from memory                 #
1119 #                                                                       #
1120 # INPUT *************************************************************** #
1121 #       - The system stack contains the "Unimp Data Type" stk frame     #
1122 #       - The fsave frame contains the ssrc op (for UNNORM/DENORM)      #
1123 #                                                                       #
1124 # OUTPUT ************************************************************** #
1125 #       If Inexact exception (opclass 3):                               #
1126 #       - The system stack is changed to an Inexact exception stk frame #
1127 #       If SNAN exception (opclass 3):                                  #
1128 #       - The system stack is changed to an SNAN exception stk frame    #
1129 #       If OPERR exception (opclass 3):                                 #
1130 #       - The system stack is changed to an OPERR exception stk frame   #
1131 #       If OVFL exception (opclass 3):                                  #
1132 #       - The system stack is changed to an OVFL exception stk frame    #
1133 #       If UNFL exception (opclass 3):                                  #
1134 #       - The system stack is changed to an UNFL exception stack frame  #
1135 #       If Trace exception enabled:                                     #
1136 #       - The system stack is changed to a Trace exception stack frame  #
1137 #       Else: (normal case)                                             #
1138 #       - Correct result has been stored as appropriate                 #
1139 #                                                                       #
1140 # ALGORITHM *********************************************************** #
1141 #       Two main instruction types can enter here: (1) DENORM or UNNORM #
1142 # unimplemented data types. These can be either opclass 0,2 or 3        #
1143 # instructions, and (2) PACKED unimplemented data format instructions   #
1144 # also of opclasses 0,2, or 3.                                          #
1145 #       For UNNORM/DENORM opclass 0 and 2, the handler fetches the src  #
1146 # operand from the fsave state frame and the dst operand (if dyadic)    #
1147 # from the FP register file. The instruction is then emulated by        #
1148 # choosing an emulation routine from a table of routines indexed by     #
1149 # instruction type. Once the instruction has been emulated and result   #
1150 # saved, then we check to see if any enabled exceptions resulted from   #
1151 # instruction emulation. If none, then we exit through the "callout"    #
1152 # _fpsp_done(). If there is an enabled FP exception, then we insert     #
1153 # this exception into the FPU in the fsave state frame and then exit    #
1154 # through _fpsp_done().                                                 #
1155 #       PACKED opclass 0 and 2 is similar in how the instruction is     #
1156 # emulated and exceptions handled. The differences occur in how the     #
1157 # handler loads the packed op (by calling get_packed() routine) and     #
1158 # by the fact that a Trace exception could be pending for PACKED ops.   #
1159 # If a Trace exception is pending, then the current exception stack     #
1160 # frame is changed to a Trace exception stack frame and an exit is      #
1161 # made through _real_trace().                                           #
1162 #       For UNNORM/DENORM opclass 3, the actual move out to memory is   #
1163 # performed by calling the routine fout(). If no exception should occur #
1164 # as the result of emulation, then an exit either occurs through        #
1165 # _fpsp_done() or through _real_trace() if a Trace exception is pending #
1166 # (a Trace stack frame must be created here, too). If an FP exception   #
1167 # should occur, then we must create an exception stack frame of that    #
1168 # type and jump to either _real_snan(), _real_operr(), _real_inex(),    #
1169 # _real_unfl(), or _real_ovfl() as appropriate. PACKED opclass 3        #
1170 # emulation is performed in a similar manner.                           #
1171 #                                                                       #
1172 #########################################################################
1173
1174 #
1175 # (1) DENORM and UNNORM (unimplemented) data types:
1176 #
1177 #                               post-instruction
1178 #                               *****************
1179 #                               *      EA       *
1180 #        pre-instruction        *               *
1181 #       *****************       *****************
1182 #       * 0x0 *  0x0dc  *       * 0x3 *  0x0dc  *
1183 #       *****************       *****************
1184 #       *     Next      *       *     Next      *
1185 #       *      PC       *       *      PC       *
1186 #       *****************       *****************
1187 #       *      SR       *       *      SR       *
1188 #       *****************       *****************
1189 #
1190 # (2) PACKED format (unsupported) opclasses two and three:
1191 #       *****************
1192 #       *      EA       *
1193 #       *               *
1194 #       *****************
1195 #       * 0x2 *  0x0dc  *
1196 #       *****************
1197 #       *     Next      *
1198 #       *      PC       *
1199 #       *****************
1200 #       *      SR       *
1201 #       *****************
1202 #
1203         global          _fpsp_unsupp
1204 _fpsp_unsupp:
1205
1206         link.w          %a6,&-LOCAL_SIZE        # init stack frame
1207
1208         fsave           FP_SRC(%a6)             # save fp state
1209
1210         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1211         fmovm.l         %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
1212         fmovm.x         &0xc0,EXC_FPREGS(%a6)   # save fp0-fp1 on stack
1213
1214         btst            &0x5,EXC_SR(%a6)        # user or supervisor mode?
1215         bne.b           fu_s
1216 fu_u:
1217         mov.l           %usp,%a0                # fetch user stack pointer
1218         mov.l           %a0,EXC_A7(%a6)         # save on stack
1219         bra.b           fu_cont
1220 # if the exception is an opclass zero or two unimplemented data type
1221 # exception, then the a7' calculated here is wrong since it doesn't
1222 # stack an ea. however, we don't need an a7' for this case anyways.
1223 fu_s:
1224         lea             0x4+EXC_EA(%a6),%a0     # load old a7'
1225         mov.l           %a0,EXC_A7(%a6)         # save on stack
1226
1227 fu_cont:
1228
1229 # the FPIAR holds the "current PC" of the faulting instruction
1230 # the FPIAR should be set correctly for ALL exceptions passing through
1231 # this point.
1232         mov.l           USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
1233         mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
1234         addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
1235         bsr.l           _imem_read_long         # fetch the instruction words
1236         mov.l           %d0,EXC_OPWORD(%a6)     # store OPWORD and EXTWORD
1237
1238 ############################
1239
1240         clr.b           SPCOND_FLG(%a6)         # clear special condition flag
1241
1242 # Separate opclass three (fpn-to-mem) ops since they have a different
1243 # stack frame and protocol.
1244         btst            &0x5,EXC_CMDREG(%a6)    # is it an fmove out?
1245         bne.w           fu_out                  # yes
1246
1247 # Separate packed opclass two instructions.
1248         bfextu          EXC_CMDREG(%a6){&0:&6},%d0
1249         cmpi.b          %d0,&0x13
1250         beq.w           fu_in_pack
1251
1252
1253 # I'm not sure at this point what FPSR bits are valid for this instruction.
1254 # so, since the emulation routines re-create them anyways, zero exception field
1255         andi.l          &0x00ff00ff,USER_FPSR(%a6) # zero exception field
1256
1257         fmov.l          &0x0,%fpcr              # zero current control regs
1258         fmov.l          &0x0,%fpsr
1259
1260 # Opclass two w/ memory-to-fpn operation will have an incorrect extended
1261 # precision format if the src format was single or double and the
1262 # source data type was an INF, NAN, DENORM, or UNNORM
1263         lea             FP_SRC(%a6),%a0         # pass ptr to input
1264         bsr.l           fix_skewed_ops
1265
1266 # we don't know whether the src operand or the dst operand (or both) is the
1267 # UNNORM or DENORM. call the function that tags the operand type. if the
1268 # input is an UNNORM, then convert it to a NORM, DENORM, or ZERO.
1269         lea             FP_SRC(%a6),%a0         # pass: ptr to src op
1270         bsr.l           set_tag_x               # tag the operand type
1271         cmpi.b          %d0,&UNNORM             # is operand an UNNORM?
1272         bne.b           fu_op2                  # no
1273         bsr.l           unnorm_fix              # yes; convert to NORM,DENORM,or ZERO
1274
1275 fu_op2:
1276         mov.b           %d0,STAG(%a6)           # save src optype tag
1277
1278         bfextu          EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
1279
1280 # bit five of the fp extension word separates the monadic and dyadic operations
1281 # at this point
1282         btst            &0x5,1+EXC_CMDREG(%a6)  # is operation monadic or dyadic?
1283         beq.b           fu_extract              # monadic
1284         cmpi.b          1+EXC_CMDREG(%a6),&0x3a # is operation an ftst?
1285         beq.b           fu_extract              # yes, so it's monadic, too
1286
1287         bsr.l           load_fpn2               # load dst into FP_DST
1288
1289         lea             FP_DST(%a6),%a0         # pass: ptr to dst op
1290         bsr.l           set_tag_x               # tag the operand type
1291         cmpi.b          %d0,&UNNORM             # is operand an UNNORM?
1292         bne.b           fu_op2_done             # no
1293         bsr.l           unnorm_fix              # yes; convert to NORM,DENORM,or ZERO
1294 fu_op2_done:
1295         mov.b           %d0,DTAG(%a6)           # save dst optype tag
1296
1297 fu_extract:
1298         clr.l           %d0
1299         mov.b           FPCR_MODE(%a6),%d0      # fetch rnd mode/prec
1300
1301         bfextu          1+EXC_CMDREG(%a6){&1:&7},%d1 # extract extension
1302
1303         lea             FP_SRC(%a6),%a0
1304         lea             FP_DST(%a6),%a1
1305
1306         mov.l           (tbl_unsupp.l,%pc,%d1.l*4),%d1 # fetch routine addr
1307         jsr             (tbl_unsupp.l,%pc,%d1.l*1)
1308
1309 #
1310 # Exceptions in order of precedence:
1311 #       BSUN    : none
1312 #       SNAN    : all dyadic ops
1313 #       OPERR   : fsqrt(-NORM)
1314 #       OVFL    : all except ftst,fcmp
1315 #       UNFL    : all except ftst,fcmp
1316 #       DZ      : fdiv
1317 #       INEX2   : all except ftst,fcmp
1318 #       INEX1   : none (packed doesn't go through here)
1319 #
1320
1321 # we determine the highest priority exception(if any) set by the
1322 # emulation routine that has also been enabled by the user.
1323         mov.b           FPCR_ENABLE(%a6),%d0    # fetch exceptions set
1324         bne.b           fu_in_ena               # some are enabled
1325
1326 fu_in_cont:
1327 # fcmp and ftst do not store any result.
1328         mov.b           1+EXC_CMDREG(%a6),%d0   # fetch extension
1329         andi.b          &0x38,%d0               # extract bits 3-5
1330         cmpi.b          %d0,&0x38               # is instr fcmp or ftst?
1331         beq.b           fu_in_exit              # yes
1332
1333         bfextu          EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
1334         bsr.l           store_fpreg             # store the result
1335
1336 fu_in_exit:
1337
1338         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
1339         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1340         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1341
1342         unlk            %a6
1343
1344         bra.l           _fpsp_done
1345
1346 fu_in_ena:
1347         and.b           FPSR_EXCEPT(%a6),%d0    # keep only ones enabled
1348         bfffo           %d0{&24:&8},%d0         # find highest priority exception
1349         bne.b           fu_in_exc               # there is at least one set
1350
1351 #
1352 # No exceptions occurred that were also enabled. Now:
1353 #
1354 #       if (OVFL && ovfl_disabled && inexact_enabled) {
1355 #           branch to _real_inex() (even if the result was exact!);
1356 #       } else {
1357 #           save the result in the proper fp reg (unless the op is fcmp or ftst);
1358 #           return;
1359 #       }
1360 #
1361         btst            &ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set?
1362         beq.b           fu_in_cont              # no
1363
1364 fu_in_ovflchk:
1365         btst            &inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled?
1366         beq.b           fu_in_cont              # no
1367         bra.w           fu_in_exc_ovfl          # go insert overflow frame
1368
1369 #
1370 # An exception occurred and that exception was enabled:
1371 #
1372 #       shift enabled exception field into lo byte of d0;
1373 #       if (((INEX2 || INEX1) && inex_enabled && OVFL && ovfl_disabled) ||
1374 #           ((INEX2 || INEX1) && inex_enabled && UNFL && unfl_disabled)) {
1375 #               /*
1376 #                * this is the case where we must call _real_inex() now or else
1377 #                * there will be no other way to pass it the exceptional operand
1378 #                */
1379 #               call _real_inex();
1380 #       } else {
1381 #               restore exc state (SNAN||OPERR||OVFL||UNFL||DZ||INEX) into the FPU;
1382 #       }
1383 #
1384 fu_in_exc:
1385         subi.l          &24,%d0                 # fix offset to be 0-8
1386         cmpi.b          %d0,&0x6                # is exception INEX? (6)
1387         bne.b           fu_in_exc_exit          # no
1388
1389 # the enabled exception was inexact
1390         btst            &unfl_bit,FPSR_EXCEPT(%a6) # did disabled underflow occur?
1391         bne.w           fu_in_exc_unfl          # yes
1392         btst            &ovfl_bit,FPSR_EXCEPT(%a6) # did disabled overflow occur?
1393         bne.w           fu_in_exc_ovfl          # yes
1394
1395 # here, we insert the correct fsave status value into the fsave frame for the
1396 # corresponding exception. the operand in the fsave frame should be the original
1397 # src operand.
1398 fu_in_exc_exit:
1399         mov.l           %d0,-(%sp)              # save d0
1400         bsr.l           funimp_skew             # skew sgl or dbl inputs
1401         mov.l           (%sp)+,%d0              # restore d0
1402
1403         mov.w           (tbl_except.b,%pc,%d0.w*2),2+FP_SRC(%a6) # create exc status
1404
1405         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
1406         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1407         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1408
1409         frestore        FP_SRC(%a6)             # restore src op
1410
1411         unlk            %a6
1412
1413         bra.l           _fpsp_done
1414
1415 tbl_except:
1416         short           0xe000,0xe006,0xe004,0xe005
1417         short           0xe003,0xe002,0xe001,0xe001
1418
1419 fu_in_exc_unfl:
1420         mov.w           &0x4,%d0
1421         bra.b           fu_in_exc_exit
1422 fu_in_exc_ovfl:
1423         mov.w           &0x03,%d0
1424         bra.b           fu_in_exc_exit
1425
1426 # If the input operand to this operation was opclass two and a single
1427 # or double precision denorm, inf, or nan, the operand needs to be
1428 # "corrected" in order to have the proper equivalent extended precision
1429 # number.
1430         global          fix_skewed_ops
1431 fix_skewed_ops:
1432         bfextu          EXC_CMDREG(%a6){&0:&6},%d0 # extract opclass,src fmt
1433         cmpi.b          %d0,&0x11               # is class = 2 & fmt = sgl?
1434         beq.b           fso_sgl                 # yes
1435         cmpi.b          %d0,&0x15               # is class = 2 & fmt = dbl?
1436         beq.b           fso_dbl                 # yes
1437         rts                                     # no
1438
1439 fso_sgl:
1440         mov.w           LOCAL_EX(%a0),%d0       # fetch src exponent
1441         andi.w          &0x7fff,%d0             # strip sign
1442         cmpi.w          %d0,&0x3f80             # is |exp| == $3f80?
1443         beq.b           fso_sgl_dnrm_zero       # yes
1444         cmpi.w          %d0,&0x407f             # no; is |exp| == $407f?
1445         beq.b           fso_infnan              # yes
1446         rts                                     # no
1447
1448 fso_sgl_dnrm_zero:
1449         andi.l          &0x7fffffff,LOCAL_HI(%a0) # clear j-bit
1450         beq.b           fso_zero                # it's a skewed zero
1451 fso_sgl_dnrm:
1452 # here, we count on norm not to alter a0...
1453         bsr.l           norm                    # normalize mantissa
1454         neg.w           %d0                     # -shft amt
1455         addi.w          &0x3f81,%d0             # adjust new exponent
1456         andi.w          &0x8000,LOCAL_EX(%a0)   # clear old exponent
1457         or.w            %d0,LOCAL_EX(%a0)       # insert new exponent
1458         rts
1459
1460 fso_zero:
1461         andi.w          &0x8000,LOCAL_EX(%a0)   # clear bogus exponent
1462         rts
1463
1464 fso_infnan:
1465         andi.b          &0x7f,LOCAL_HI(%a0)     # clear j-bit
1466         ori.w           &0x7fff,LOCAL_EX(%a0)   # make exponent = $7fff
1467         rts
1468
1469 fso_dbl:
1470         mov.w           LOCAL_EX(%a0),%d0       # fetch src exponent
1471         andi.w          &0x7fff,%d0             # strip sign
1472         cmpi.w          %d0,&0x3c00             # is |exp| == $3c00?
1473         beq.b           fso_dbl_dnrm_zero       # yes
1474         cmpi.w          %d0,&0x43ff             # no; is |exp| == $43ff?
1475         beq.b           fso_infnan              # yes
1476         rts                                     # no
1477
1478 fso_dbl_dnrm_zero:
1479         andi.l          &0x7fffffff,LOCAL_HI(%a0) # clear j-bit
1480         bne.b           fso_dbl_dnrm            # it's a skewed denorm
1481         tst.l           LOCAL_LO(%a0)           # is it a zero?
1482         beq.b           fso_zero                # yes
1483 fso_dbl_dnrm:
1484 # here, we count on norm not to alter a0...
1485         bsr.l           norm                    # normalize mantissa
1486         neg.w           %d0                     # -shft amt
1487         addi.w          &0x3c01,%d0             # adjust new exponent
1488         andi.w          &0x8000,LOCAL_EX(%a0)   # clear old exponent
1489         or.w            %d0,LOCAL_EX(%a0)       # insert new exponent
1490         rts
1491
1492 #################################################################
1493
1494 # fmove out took an unimplemented data type exception.
1495 # the src operand is in FP_SRC. Call _fout() to write out the result and
1496 # to determine which exceptions, if any, to take.
1497 fu_out:
1498
1499 # Separate packed move outs from the UNNORM and DENORM move outs.
1500         bfextu          EXC_CMDREG(%a6){&3:&3},%d0
1501         cmpi.b          %d0,&0x3
1502         beq.w           fu_out_pack
1503         cmpi.b          %d0,&0x7
1504         beq.w           fu_out_pack
1505
1506
1507 # I'm not sure at this point what FPSR bits are valid for this instruction.
1508 # so, since the emulation routines re-create them anyways, zero exception field.
1509 # fmove out doesn't affect ccodes.
1510         and.l           &0xffff00ff,USER_FPSR(%a6) # zero exception field
1511
1512         fmov.l          &0x0,%fpcr              # zero current control regs
1513         fmov.l          &0x0,%fpsr
1514
1515 # the src can ONLY be a DENORM or an UNNORM! so, don't make any big subroutine
1516 # call here. just figure out what it is...
1517         mov.w           FP_SRC_EX(%a6),%d0      # get exponent
1518         andi.w          &0x7fff,%d0             # strip sign
1519         beq.b           fu_out_denorm           # it's a DENORM
1520
1521         lea             FP_SRC(%a6),%a0
1522         bsr.l           unnorm_fix              # yes; fix it
1523
1524         mov.b           %d0,STAG(%a6)
1525
1526         bra.b           fu_out_cont
1527 fu_out_denorm:
1528         mov.b           &DENORM,STAG(%a6)
1529 fu_out_cont:
1530
1531         clr.l           %d0
1532         mov.b           FPCR_MODE(%a6),%d0      # fetch rnd mode/prec
1533
1534         lea             FP_SRC(%a6),%a0         # pass ptr to src operand
1535
1536         mov.l           (%a6),EXC_A6(%a6)       # in case a6 changes
1537         bsr.l           fout                    # call fmove out routine
1538
1539 # Exceptions in order of precedence:
1540 #       BSUN    : none
1541 #       SNAN    : none
1542 #       OPERR   : fmove.{b,w,l} out of large UNNORM
1543 #       OVFL    : fmove.{s,d}
1544 #       UNFL    : fmove.{s,d,x}
1545 #       DZ      : none
1546 #       INEX2   : all
1547 #       INEX1   : none (packed doesn't travel through here)
1548
1549 # determine the highest priority exception(if any) set by the
1550 # emulation routine that has also been enabled by the user.
1551         mov.b           FPCR_ENABLE(%a6),%d0    # fetch exceptions enabled
1552         bne.w           fu_out_ena              # some are enabled
1553
1554 fu_out_done:
1555
1556         mov.l           EXC_A6(%a6),(%a6)       # in case a6 changed
1557
1558 # on extended precision opclass three instructions using pre-decrement or
1559 # post-increment addressing mode, the address register is not updated. is the
1560 # address register was the stack pointer used from user mode, then let's update
1561 # it here. if it was used from supervisor mode, then we have to handle this
1562 # as a special case.
1563         btst            &0x5,EXC_SR(%a6)
1564         bne.b           fu_out_done_s
1565
1566         mov.l           EXC_A7(%a6),%a0         # restore a7
1567         mov.l           %a0,%usp
1568
1569 fu_out_done_cont:
1570         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
1571         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1572         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1573
1574         unlk            %a6
1575
1576         btst            &0x7,(%sp)              # is trace on?
1577         bne.b           fu_out_trace            # yes
1578
1579         bra.l           _fpsp_done
1580
1581 # is the ea mode pre-decrement of the stack pointer from supervisor mode?
1582 # ("fmov.x fpm,-(a7)") if so,
1583 fu_out_done_s:
1584         cmpi.b          SPCOND_FLG(%a6),&mda7_flg
1585         bne.b           fu_out_done_cont
1586
1587 # the extended precision result is still in fp0. but, we need to save it
1588 # somewhere on the stack until we can copy it to its final resting place.
1589 # here, we're counting on the top of the stack to be the old place-holders
1590 # for fp0/fp1 which have already been restored. that way, we can write
1591 # over those destinations with the shifted stack frame.
1592         fmovm.x         &0x80,FP_SRC(%a6)       # put answer on stack
1593
1594         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
1595         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1596         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1597
1598         mov.l           (%a6),%a6               # restore frame pointer
1599
1600         mov.l           LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
1601         mov.l           LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
1602
1603 # now, copy the result to the proper place on the stack
1604         mov.l           LOCAL_SIZE+FP_SRC_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp)
1605         mov.l           LOCAL_SIZE+FP_SRC_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp)
1606         mov.l           LOCAL_SIZE+FP_SRC_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp)
1607
1608         add.l           &LOCAL_SIZE-0x8,%sp
1609
1610         btst            &0x7,(%sp)
1611         bne.b           fu_out_trace
1612
1613         bra.l           _fpsp_done
1614
1615 fu_out_ena:
1616         and.b           FPSR_EXCEPT(%a6),%d0    # keep only ones enabled
1617         bfffo           %d0{&24:&8},%d0         # find highest priority exception
1618         bne.b           fu_out_exc              # there is at least one set
1619
1620 # no exceptions were set.
1621 # if a disabled overflow occurred and inexact was enabled but the result
1622 # was exact, then a branch to _real_inex() is made.
1623         btst            &ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set?
1624         beq.w           fu_out_done             # no
1625
1626 fu_out_ovflchk:
1627         btst            &inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled?
1628         beq.w           fu_out_done             # no
1629         bra.w           fu_inex                 # yes
1630
1631 #
1632 # The fp move out that took the "Unimplemented Data Type" exception was
1633 # being traced. Since the stack frames are similar, get the "current" PC
1634 # from FPIAR and put it in the trace stack frame then jump to _real_trace().
1635 #
1636 #                 UNSUPP FRAME             TRACE FRAME
1637 #               *****************       *****************
1638 #               *      EA       *       *    Current    *
1639 #               *               *       *      PC       *
1640 #               *****************       *****************
1641 #               * 0x3 *  0x0dc  *       * 0x2 *  0x024  *
1642 #               *****************       *****************
1643 #               *     Next      *       *     Next      *
1644 #               *      PC       *       *      PC       *
1645 #               *****************       *****************
1646 #               *      SR       *       *      SR       *
1647 #               *****************       *****************
1648 #
1649 fu_out_trace:
1650         mov.w           &0x2024,0x6(%sp)
1651         fmov.l          %fpiar,0x8(%sp)
1652         bra.l           _real_trace
1653
1654 # an exception occurred and that exception was enabled.
1655 fu_out_exc:
1656         subi.l          &24,%d0                 # fix offset to be 0-8
1657
1658 # we don't mess with the existing fsave frame. just re-insert it and
1659 # jump to the "_real_{}()" handler...
1660         mov.w           (tbl_fu_out.b,%pc,%d0.w*2),%d0
1661         jmp             (tbl_fu_out.b,%pc,%d0.w*1)
1662
1663         swbeg           &0x8
1664 tbl_fu_out:
1665         short           tbl_fu_out      - tbl_fu_out    # BSUN can't happen
1666         short           tbl_fu_out      - tbl_fu_out    # SNAN can't happen
1667         short           fu_operr        - tbl_fu_out    # OPERR
1668         short           fu_ovfl         - tbl_fu_out    # OVFL
1669         short           fu_unfl         - tbl_fu_out    # UNFL
1670         short           tbl_fu_out      - tbl_fu_out    # DZ can't happen
1671         short           fu_inex         - tbl_fu_out    # INEX2
1672         short           tbl_fu_out      - tbl_fu_out    # INEX1 won't make it here
1673
1674 # for snan,operr,ovfl,unfl, src op is still in FP_SRC so just
1675 # frestore it.
1676 fu_snan:
1677         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
1678         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1679         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1680
1681         mov.w           &0x30d8,EXC_VOFF(%a6)   # vector offset = 0xd8
1682         mov.w           &0xe006,2+FP_SRC(%a6)
1683
1684         frestore        FP_SRC(%a6)
1685
1686         unlk            %a6
1687
1688
1689         bra.l           _real_snan
1690
1691 fu_operr:
1692         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
1693         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1694         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1695
1696         mov.w           &0x30d0,EXC_VOFF(%a6)   # vector offset = 0xd0
1697         mov.w           &0xe004,2+FP_SRC(%a6)
1698
1699         frestore        FP_SRC(%a6)
1700
1701         unlk            %a6
1702
1703
1704         bra.l           _real_operr
1705
1706 fu_ovfl:
1707         fmovm.x         &0x40,FP_SRC(%a6)       # save EXOP to the stack
1708
1709         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
1710         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1711         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1712
1713         mov.w           &0x30d4,EXC_VOFF(%a6)   # vector offset = 0xd4
1714         mov.w           &0xe005,2+FP_SRC(%a6)
1715
1716         frestore        FP_SRC(%a6)             # restore EXOP
1717
1718         unlk            %a6
1719
1720         bra.l           _real_ovfl
1721
1722 # underflow can happen for extended precision. extended precision opclass
1723 # three instruction exceptions don't update the stack pointer. so, if the
1724 # exception occurred from user mode, then simply update a7 and exit normally.
1725 # if the exception occurred from supervisor mode, check if
1726 fu_unfl:
1727         mov.l           EXC_A6(%a6),(%a6)       # restore a6
1728
1729         btst            &0x5,EXC_SR(%a6)
1730         bne.w           fu_unfl_s
1731
1732         mov.l           EXC_A7(%a6),%a0         # restore a7 whether we need
1733         mov.l           %a0,%usp                # to or not...
1734
1735 fu_unfl_cont:
1736         fmovm.x         &0x40,FP_SRC(%a6)       # save EXOP to the stack
1737
1738         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
1739         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1740         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1741
1742         mov.w           &0x30cc,EXC_VOFF(%a6)   # vector offset = 0xcc
1743         mov.w           &0xe003,2+FP_SRC(%a6)
1744
1745         frestore        FP_SRC(%a6)             # restore EXOP
1746
1747         unlk            %a6
1748
1749         bra.l           _real_unfl
1750
1751 fu_unfl_s:
1752         cmpi.b          SPCOND_FLG(%a6),&mda7_flg # was the <ea> mode -(sp)?
1753         bne.b           fu_unfl_cont
1754
1755 # the extended precision result is still in fp0. but, we need to save it
1756 # somewhere on the stack until we can copy it to its final resting place
1757 # (where the exc frame is currently). make sure it's not at the top of the
1758 # frame or it will get overwritten when the exc stack frame is shifted "down".
1759         fmovm.x         &0x80,FP_SRC(%a6)       # put answer on stack
1760         fmovm.x         &0x40,FP_DST(%a6)       # put EXOP on stack
1761
1762         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
1763         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1764         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1765
1766         mov.w           &0x30cc,EXC_VOFF(%a6)   # vector offset = 0xcc
1767         mov.w           &0xe003,2+FP_DST(%a6)
1768
1769         frestore        FP_DST(%a6)             # restore EXOP
1770
1771         mov.l           (%a6),%a6               # restore frame pointer
1772
1773         mov.l           LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
1774         mov.l           LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
1775         mov.l           LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
1776
1777 # now, copy the result to the proper place on the stack
1778         mov.l           LOCAL_SIZE+FP_SRC_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp)
1779         mov.l           LOCAL_SIZE+FP_SRC_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp)
1780         mov.l           LOCAL_SIZE+FP_SRC_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp)
1781
1782         add.l           &LOCAL_SIZE-0x8,%sp
1783
1784         bra.l           _real_unfl
1785
1786 # fmove in and out enter here.
1787 fu_inex:
1788         fmovm.x         &0x40,FP_SRC(%a6)       # save EXOP to the stack
1789
1790         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
1791         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1792         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1793
1794         mov.w           &0x30c4,EXC_VOFF(%a6)   # vector offset = 0xc4
1795         mov.w           &0xe001,2+FP_SRC(%a6)
1796
1797         frestore        FP_SRC(%a6)             # restore EXOP
1798
1799         unlk            %a6
1800
1801
1802         bra.l           _real_inex
1803
1804 #########################################################################
1805 #########################################################################
1806 fu_in_pack:
1807
1808
1809 # I'm not sure at this point what FPSR bits are valid for this instruction.
1810 # so, since the emulation routines re-create them anyways, zero exception field
1811         andi.l          &0x0ff00ff,USER_FPSR(%a6) # zero exception field
1812
1813         fmov.l          &0x0,%fpcr              # zero current control regs
1814         fmov.l          &0x0,%fpsr
1815
1816         bsr.l           get_packed              # fetch packed src operand
1817
1818         lea             FP_SRC(%a6),%a0         # pass ptr to src
1819         bsr.l           set_tag_x               # set src optype tag
1820
1821         mov.b           %d0,STAG(%a6)           # save src optype tag
1822
1823         bfextu          EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
1824
1825 # bit five of the fp extension word separates the monadic and dyadic operations
1826 # at this point
1827         btst            &0x5,1+EXC_CMDREG(%a6)  # is operation monadic or dyadic?
1828         beq.b           fu_extract_p            # monadic
1829         cmpi.b          1+EXC_CMDREG(%a6),&0x3a # is operation an ftst?
1830         beq.b           fu_extract_p            # yes, so it's monadic, too
1831
1832         bsr.l           load_fpn2               # load dst into FP_DST
1833
1834         lea             FP_DST(%a6),%a0         # pass: ptr to dst op
1835         bsr.l           set_tag_x               # tag the operand type
1836         cmpi.b          %d0,&UNNORM             # is operand an UNNORM?
1837         bne.b           fu_op2_done_p           # no
1838         bsr.l           unnorm_fix              # yes; convert to NORM,DENORM,or ZERO
1839 fu_op2_done_p:
1840         mov.b           %d0,DTAG(%a6)           # save dst optype tag
1841
1842 fu_extract_p:
1843         clr.l           %d0
1844         mov.b           FPCR_MODE(%a6),%d0      # fetch rnd mode/prec
1845
1846         bfextu          1+EXC_CMDREG(%a6){&1:&7},%d1 # extract extension
1847
1848         lea             FP_SRC(%a6),%a0
1849         lea             FP_DST(%a6),%a1
1850
1851         mov.l           (tbl_unsupp.l,%pc,%d1.l*4),%d1 # fetch routine addr
1852         jsr             (tbl_unsupp.l,%pc,%d1.l*1)
1853
1854 #
1855 # Exceptions in order of precedence:
1856 #       BSUN    : none
1857 #       SNAN    : all dyadic ops
1858 #       OPERR   : fsqrt(-NORM)
1859 #       OVFL    : all except ftst,fcmp
1860 #       UNFL    : all except ftst,fcmp
1861 #       DZ      : fdiv
1862 #       INEX2   : all except ftst,fcmp
1863 #       INEX1   : all
1864 #
1865
1866 # we determine the highest priority exception(if any) set by the
1867 # emulation routine that has also been enabled by the user.
1868         mov.b           FPCR_ENABLE(%a6),%d0    # fetch exceptions enabled
1869         bne.w           fu_in_ena_p             # some are enabled
1870
1871 fu_in_cont_p:
1872 # fcmp and ftst do not store any result.
1873         mov.b           1+EXC_CMDREG(%a6),%d0   # fetch extension
1874         andi.b          &0x38,%d0               # extract bits 3-5
1875         cmpi.b          %d0,&0x38               # is instr fcmp or ftst?
1876         beq.b           fu_in_exit_p            # yes
1877
1878         bfextu          EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
1879         bsr.l           store_fpreg             # store the result
1880
1881 fu_in_exit_p:
1882
1883         btst            &0x5,EXC_SR(%a6)        # user or supervisor?
1884         bne.w           fu_in_exit_s_p          # supervisor
1885
1886         mov.l           EXC_A7(%a6),%a0         # update user a7
1887         mov.l           %a0,%usp
1888
1889 fu_in_exit_cont_p:
1890         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
1891         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1892         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1893
1894         unlk            %a6                     # unravel stack frame
1895
1896         btst            &0x7,(%sp)              # is trace on?
1897         bne.w           fu_trace_p              # yes
1898
1899         bra.l           _fpsp_done              # exit to os
1900
1901 # the exception occurred in supervisor mode. check to see if the
1902 # addressing mode was (a7)+. if so, we'll need to shift the
1903 # stack frame "up".
1904 fu_in_exit_s_p:
1905         btst            &mia7_bit,SPCOND_FLG(%a6) # was ea mode (a7)+
1906         beq.b           fu_in_exit_cont_p       # no
1907
1908         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
1909         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1910         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1911
1912         unlk            %a6                     # unravel stack frame
1913
1914 # shift the stack frame "up". we don't really care about the <ea> field.
1915         mov.l           0x4(%sp),0x10(%sp)
1916         mov.l           0x0(%sp),0xc(%sp)
1917         add.l           &0xc,%sp
1918
1919         btst            &0x7,(%sp)              # is trace on?
1920         bne.w           fu_trace_p              # yes
1921
1922         bra.l           _fpsp_done              # exit to os
1923
1924 fu_in_ena_p:
1925         and.b           FPSR_EXCEPT(%a6),%d0    # keep only ones enabled & set
1926         bfffo           %d0{&24:&8},%d0         # find highest priority exception
1927         bne.b           fu_in_exc_p             # at least one was set
1928
1929 #
1930 # No exceptions occurred that were also enabled. Now:
1931 #
1932 #       if (OVFL && ovfl_disabled && inexact_enabled) {
1933 #           branch to _real_inex() (even if the result was exact!);
1934 #       } else {
1935 #           save the result in the proper fp reg (unless the op is fcmp or ftst);
1936 #           return;
1937 #       }
1938 #
1939         btst            &ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set?
1940         beq.w           fu_in_cont_p            # no
1941
1942 fu_in_ovflchk_p:
1943         btst            &inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled?
1944         beq.w           fu_in_cont_p            # no
1945         bra.w           fu_in_exc_ovfl_p        # do _real_inex() now
1946
1947 #
1948 # An exception occurred and that exception was enabled:
1949 #
1950 #       shift enabled exception field into lo byte of d0;
1951 #       if (((INEX2 || INEX1) && inex_enabled && OVFL && ovfl_disabled) ||
1952 #           ((INEX2 || INEX1) && inex_enabled && UNFL && unfl_disabled)) {
1953 #               /*
1954 #                * this is the case where we must call _real_inex() now or else
1955 #                * there will be no other way to pass it the exceptional operand
1956 #                */
1957 #               call _real_inex();
1958 #       } else {
1959 #               restore exc state (SNAN||OPERR||OVFL||UNFL||DZ||INEX) into the FPU;
1960 #       }
1961 #
1962 fu_in_exc_p:
1963         subi.l          &24,%d0                 # fix offset to be 0-8
1964         cmpi.b          %d0,&0x6                # is exception INEX? (6 or 7)
1965         blt.b           fu_in_exc_exit_p        # no
1966
1967 # the enabled exception was inexact
1968         btst            &unfl_bit,FPSR_EXCEPT(%a6) # did disabled underflow occur?
1969         bne.w           fu_in_exc_unfl_p        # yes
1970         btst            &ovfl_bit,FPSR_EXCEPT(%a6) # did disabled overflow occur?
1971         bne.w           fu_in_exc_ovfl_p        # yes
1972
1973 # here, we insert the correct fsave status value into the fsave frame for the
1974 # corresponding exception. the operand in the fsave frame should be the original
1975 # src operand.
1976 # as a reminder for future predicted pain and agony, we are passing in fsave the
1977 # "non-skewed" operand for cases of sgl and dbl src INFs,NANs, and DENORMs.
1978 # this is INCORRECT for enabled SNAN which would give to the user the skewed SNAN!!!
1979 fu_in_exc_exit_p:
1980         btst            &0x5,EXC_SR(%a6)        # user or supervisor?
1981         bne.w           fu_in_exc_exit_s_p      # supervisor
1982
1983         mov.l           EXC_A7(%a6),%a0         # update user a7
1984         mov.l           %a0,%usp
1985
1986 fu_in_exc_exit_cont_p:
1987         mov.w           (tbl_except_p.b,%pc,%d0.w*2),2+FP_SRC(%a6)
1988
1989         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
1990         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1991         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1992
1993         frestore        FP_SRC(%a6)             # restore src op
1994
1995         unlk            %a6
1996
1997         btst            &0x7,(%sp)              # is trace enabled?
1998         bne.w           fu_trace_p              # yes
1999
2000         bra.l           _fpsp_done
2001
2002 tbl_except_p:
2003         short           0xe000,0xe006,0xe004,0xe005
2004         short           0xe003,0xe002,0xe001,0xe001
2005
2006 fu_in_exc_ovfl_p:
2007         mov.w           &0x3,%d0
2008         bra.w           fu_in_exc_exit_p
2009
2010 fu_in_exc_unfl_p:
2011         mov.w           &0x4,%d0
2012         bra.w           fu_in_exc_exit_p
2013
2014 fu_in_exc_exit_s_p:
2015         btst            &mia7_bit,SPCOND_FLG(%a6)
2016         beq.b           fu_in_exc_exit_cont_p
2017
2018         mov.w           (tbl_except_p.b,%pc,%d0.w*2),2+FP_SRC(%a6)
2019
2020         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
2021         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2022         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2023
2024         frestore        FP_SRC(%a6)             # restore src op
2025
2026         unlk            %a6                     # unravel stack frame
2027
2028 # shift stack frame "up". who cares about <ea> field.
2029         mov.l           0x4(%sp),0x10(%sp)
2030         mov.l           0x0(%sp),0xc(%sp)
2031         add.l           &0xc,%sp
2032
2033         btst            &0x7,(%sp)              # is trace on?
2034         bne.b           fu_trace_p              # yes
2035
2036         bra.l           _fpsp_done              # exit to os
2037
2038 #
2039 # The opclass two PACKED instruction that took an "Unimplemented Data Type"
2040 # exception was being traced. Make the "current" PC the FPIAR and put it in the
2041 # trace stack frame then jump to _real_trace().
2042 #
2043 #                 UNSUPP FRAME             TRACE FRAME
2044 #               *****************       *****************
2045 #               *      EA       *       *    Current    *
2046 #               *               *       *      PC       *
2047 #               *****************       *****************
2048 #               * 0x2 * 0x0dc   *       * 0x2 *  0x024  *
2049 #               *****************       *****************
2050 #               *     Next      *       *     Next      *
2051 #               *      PC       *       *      PC       *
2052 #               *****************       *****************
2053 #               *      SR       *       *      SR       *
2054 #               *****************       *****************
2055 fu_trace_p:
2056         mov.w           &0x2024,0x6(%sp)
2057         fmov.l          %fpiar,0x8(%sp)
2058
2059         bra.l           _real_trace
2060
2061 #########################################################
2062 #########################################################
2063 fu_out_pack:
2064
2065
2066 # I'm not sure at this point what FPSR bits are valid for this instruction.
2067 # so, since the emulation routines re-create them anyways, zero exception field.
2068 # fmove out doesn't affect ccodes.
2069         and.l           &0xffff00ff,USER_FPSR(%a6) # zero exception field
2070
2071         fmov.l          &0x0,%fpcr              # zero current control regs
2072         fmov.l          &0x0,%fpsr
2073
2074         bfextu          EXC_CMDREG(%a6){&6:&3},%d0
2075         bsr.l           load_fpn1
2076
2077 # unlike other opclass 3, unimplemented data type exceptions, packed must be
2078 # able to detect all operand types.
2079         lea             FP_SRC(%a6),%a0
2080         bsr.l           set_tag_x               # tag the operand type
2081         cmpi.b          %d0,&UNNORM             # is operand an UNNORM?
2082         bne.b           fu_op2_p                # no
2083         bsr.l           unnorm_fix              # yes; convert to NORM,DENORM,or ZERO
2084
2085 fu_op2_p:
2086         mov.b           %d0,STAG(%a6)           # save src optype tag
2087
2088         clr.l           %d0
2089         mov.b           FPCR_MODE(%a6),%d0      # fetch rnd mode/prec
2090
2091         lea             FP_SRC(%a6),%a0         # pass ptr to src operand
2092
2093         mov.l           (%a6),EXC_A6(%a6)       # in case a6 changes
2094         bsr.l           fout                    # call fmove out routine
2095
2096 # Exceptions in order of precedence:
2097 #       BSUN    : no
2098 #       SNAN    : yes
2099 #       OPERR   : if ((k_factor > +17) || (dec. exp exceeds 3 digits))
2100 #       OVFL    : no
2101 #       UNFL    : no
2102 #       DZ      : no
2103 #       INEX2   : yes
2104 #       INEX1   : no
2105
2106 # determine the highest priority exception(if any) set by the
2107 # emulation routine that has also been enabled by the user.
2108         mov.b           FPCR_ENABLE(%a6),%d0    # fetch exceptions enabled
2109         bne.w           fu_out_ena_p            # some are enabled
2110
2111 fu_out_exit_p:
2112         mov.l           EXC_A6(%a6),(%a6)       # restore a6
2113
2114         btst            &0x5,EXC_SR(%a6)        # user or supervisor?
2115         bne.b           fu_out_exit_s_p         # supervisor
2116
2117         mov.l           EXC_A7(%a6),%a0         # update user a7
2118         mov.l           %a0,%usp
2119
2120 fu_out_exit_cont_p:
2121         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
2122         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2123         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2124
2125         unlk            %a6                     # unravel stack frame
2126
2127         btst            &0x7,(%sp)              # is trace on?
2128         bne.w           fu_trace_p              # yes
2129
2130         bra.l           _fpsp_done              # exit to os
2131
2132 # the exception occurred in supervisor mode. check to see if the
2133 # addressing mode was -(a7). if so, we'll need to shift the
2134 # stack frame "down".
2135 fu_out_exit_s_p:
2136         btst            &mda7_bit,SPCOND_FLG(%a6) # was ea mode -(a7)
2137         beq.b           fu_out_exit_cont_p      # no
2138
2139         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
2140         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2141         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2142
2143         mov.l           (%a6),%a6               # restore frame pointer
2144
2145         mov.l           LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
2146         mov.l           LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
2147
2148 # now, copy the result to the proper place on the stack
2149         mov.l           LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp)
2150         mov.l           LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp)
2151         mov.l           LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp)
2152
2153         add.l           &LOCAL_SIZE-0x8,%sp
2154
2155         btst            &0x7,(%sp)
2156         bne.w           fu_trace_p
2157
2158         bra.l           _fpsp_done
2159
2160 fu_out_ena_p:
2161         and.b           FPSR_EXCEPT(%a6),%d0    # keep only ones enabled
2162         bfffo           %d0{&24:&8},%d0         # find highest priority exception
2163         beq.w           fu_out_exit_p
2164
2165         mov.l           EXC_A6(%a6),(%a6)       # restore a6
2166
2167 # an exception occurred and that exception was enabled.
2168 # the only exception possible on packed move out are INEX, OPERR, and SNAN.
2169 fu_out_exc_p:
2170         cmpi.b          %d0,&0x1a
2171         bgt.w           fu_inex_p2
2172         beq.w           fu_operr_p
2173
2174 fu_snan_p:
2175         btst            &0x5,EXC_SR(%a6)
2176         bne.b           fu_snan_s_p
2177
2178         mov.l           EXC_A7(%a6),%a0
2179         mov.l           %a0,%usp
2180         bra.w           fu_snan
2181
2182 fu_snan_s_p:
2183         cmpi.b          SPCOND_FLG(%a6),&mda7_flg
2184         bne.w           fu_snan
2185
2186 # the instruction was "fmove.p fpn,-(a7)" from supervisor mode.
2187 # the strategy is to move the exception frame "down" 12 bytes. then, we
2188 # can store the default result where the exception frame was.
2189         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
2190         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2191         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2192
2193         mov.w           &0x30d8,EXC_VOFF(%a6)   # vector offset = 0xd0
2194         mov.w           &0xe006,2+FP_SRC(%a6)   # set fsave status
2195
2196         frestore        FP_SRC(%a6)             # restore src operand
2197
2198         mov.l           (%a6),%a6               # restore frame pointer
2199
2200         mov.l           LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
2201         mov.l           LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
2202         mov.l           LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
2203
2204 # now, we copy the default result to its proper location
2205         mov.l           LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+0x4(%sp)
2206         mov.l           LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+0x8(%sp)
2207         mov.l           LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+0xc(%sp)
2208
2209         add.l           &LOCAL_SIZE-0x8,%sp
2210
2211
2212         bra.l           _real_snan
2213
2214 fu_operr_p:
2215         btst            &0x5,EXC_SR(%a6)
2216         bne.w           fu_operr_p_s
2217
2218         mov.l           EXC_A7(%a6),%a0
2219         mov.l           %a0,%usp
2220         bra.w           fu_operr
2221
2222 fu_operr_p_s:
2223         cmpi.b          SPCOND_FLG(%a6),&mda7_flg
2224         bne.w           fu_operr
2225
2226 # the instruction was "fmove.p fpn,-(a7)" from supervisor mode.
2227 # the strategy is to move the exception frame "down" 12 bytes. then, we
2228 # can store the default result where the exception frame was.
2229         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
2230         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2231         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2232
2233         mov.w           &0x30d0,EXC_VOFF(%a6)   # vector offset = 0xd0
2234         mov.w           &0xe004,2+FP_SRC(%a6)   # set fsave status
2235
2236         frestore        FP_SRC(%a6)             # restore src operand
2237
2238         mov.l           (%a6),%a6               # restore frame pointer
2239
2240         mov.l           LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
2241         mov.l           LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
2242         mov.l           LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
2243
2244 # now, we copy the default result to its proper location
2245         mov.l           LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+0x4(%sp)
2246         mov.l           LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+0x8(%sp)
2247         mov.l           LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+0xc(%sp)
2248
2249         add.l           &LOCAL_SIZE-0x8,%sp
2250
2251
2252         bra.l           _real_operr
2253
2254 fu_inex_p2:
2255         btst            &0x5,EXC_SR(%a6)
2256         bne.w           fu_inex_s_p2
2257
2258         mov.l           EXC_A7(%a6),%a0
2259         mov.l           %a0,%usp
2260         bra.w           fu_inex
2261
2262 fu_inex_s_p2:
2263         cmpi.b          SPCOND_FLG(%a6),&mda7_flg
2264         bne.w           fu_inex
2265
2266 # the instruction was "fmove.p fpn,-(a7)" from supervisor mode.
2267 # the strategy is to move the exception frame "down" 12 bytes. then, we
2268 # can store the default result where the exception frame was.
2269         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0/fp1
2270         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2271         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2272
2273         mov.w           &0x30c4,EXC_VOFF(%a6)   # vector offset = 0xc4
2274         mov.w           &0xe001,2+FP_SRC(%a6)   # set fsave status
2275
2276         frestore        FP_SRC(%a6)             # restore src operand
2277
2278         mov.l           (%a6),%a6               # restore frame pointer
2279
2280         mov.l           LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
2281         mov.l           LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
2282         mov.l           LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
2283
2284 # now, we copy the default result to its proper location
2285         mov.l           LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+0x4(%sp)
2286         mov.l           LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+0x8(%sp)
2287         mov.l           LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+0xc(%sp)
2288
2289         add.l           &LOCAL_SIZE-0x8,%sp
2290
2291
2292         bra.l           _real_inex
2293
2294 #########################################################################
2295
2296 #
2297 # if we're stuffing a source operand back into an fsave frame then we
2298 # have to make sure that for single or double source operands that the
2299 # format stuffed is as weird as the hardware usually makes it.
2300 #
2301         global          funimp_skew
2302 funimp_skew:
2303         bfextu          EXC_EXTWORD(%a6){&3:&3},%d0 # extract src specifier
2304         cmpi.b          %d0,&0x1                # was src sgl?
2305         beq.b           funimp_skew_sgl         # yes
2306         cmpi.b          %d0,&0x5                # was src dbl?
2307         beq.b           funimp_skew_dbl         # yes
2308         rts
2309
2310 funimp_skew_sgl:
2311         mov.w           FP_SRC_EX(%a6),%d0      # fetch DENORM exponent
2312         andi.w          &0x7fff,%d0             # strip sign
2313         beq.b           funimp_skew_sgl_not
2314         cmpi.w          %d0,&0x3f80
2315         bgt.b           funimp_skew_sgl_not
2316         neg.w           %d0                     # make exponent negative
2317         addi.w          &0x3f81,%d0             # find amt to shift
2318         mov.l           FP_SRC_HI(%a6),%d1      # fetch DENORM hi(man)
2319         lsr.l           %d0,%d1                 # shift it
2320         bset            &31,%d1                 # set j-bit
2321         mov.l           %d1,FP_SRC_HI(%a6)      # insert new hi(man)
2322         andi.w          &0x8000,FP_SRC_EX(%a6)  # clear old exponent
2323         ori.w           &0x3f80,FP_SRC_EX(%a6)  # insert new "skewed" exponent
2324 funimp_skew_sgl_not:
2325         rts
2326
2327 funimp_skew_dbl:
2328         mov.w           FP_SRC_EX(%a6),%d0      # fetch DENORM exponent
2329         andi.w          &0x7fff,%d0             # strip sign
2330         beq.b           funimp_skew_dbl_not
2331         cmpi.w          %d0,&0x3c00
2332         bgt.b           funimp_skew_dbl_not
2333
2334         tst.b           FP_SRC_EX(%a6)          # make "internal format"
2335         smi.b           0x2+FP_SRC(%a6)
2336         mov.w           %d0,FP_SRC_EX(%a6)      # insert exponent with cleared sign
2337         clr.l           %d0                     # clear g,r,s
2338         lea             FP_SRC(%a6),%a0         # pass ptr to src op
2339         mov.w           &0x3c01,%d1             # pass denorm threshold
2340         bsr.l           dnrm_lp                 # denorm it
2341         mov.w           &0x3c00,%d0             # new exponent
2342         tst.b           0x2+FP_SRC(%a6)         # is sign set?
2343         beq.b           fss_dbl_denorm_done     # no
2344         bset            &15,%d0                 # set sign
2345 fss_dbl_denorm_done:
2346         bset            &0x7,FP_SRC_HI(%a6)     # set j-bit
2347         mov.w           %d0,FP_SRC_EX(%a6)      # insert new exponent
2348 funimp_skew_dbl_not:
2349         rts
2350
2351 #########################################################################
2352         global          _mem_write2
2353 _mem_write2:
2354         btst            &0x5,EXC_SR(%a6)
2355         beq.l           _dmem_write
2356         mov.l           0x0(%a0),FP_DST_EX(%a6)
2357         mov.l           0x4(%a0),FP_DST_HI(%a6)
2358         mov.l           0x8(%a0),FP_DST_LO(%a6)
2359         clr.l           %d1
2360         rts
2361
2362 #########################################################################
2363 # XDEF **************************************************************** #
2364 #       _fpsp_effadd(): 060FPSP entry point for FP "Unimplemented       #
2365 #                       effective address" exception.                   #
2366 #                                                                       #
2367 #       This handler should be the first code executed upon taking the  #
2368 #       FP Unimplemented Effective Address exception in an operating    #
2369 #       system.                                                         #
2370 #                                                                       #
2371 # XREF **************************************************************** #
2372 #       _imem_read_long() - read instruction longword                   #
2373 #       fix_skewed_ops() - adjust src operand in fsave frame            #
2374 #       set_tag_x() - determine optype of src/dst operands              #
2375 #       store_fpreg() - store opclass 0 or 2 result to FP regfile       #
2376 #       unnorm_fix() - change UNNORM operands to NORM or ZERO           #
2377 #       load_fpn2() - load dst operand from FP regfile                  #
2378 #       tbl_unsupp - add of table of emulation routines for opclass 0,2 #
2379 #       decbin() - convert packed data to FP binary data                #
2380 #       _real_fpu_disabled() - "callout" for "FPU disabled" exception   #
2381 #       _real_access() - "callout" for access error exception           #
2382 #       _mem_read() - read extended immediate operand from memory       #
2383 #       _fpsp_done() - "callout" for exit; work all done                #
2384 #       _real_trace() - "callout" for Trace enabled exception           #
2385 #       fmovm_dynamic() - emulate dynamic fmovm instruction             #
2386 #       fmovm_ctrl() - emulate fmovm control instruction                #
2387 #                                                                       #
2388 # INPUT *************************************************************** #
2389 #       - The system stack contains the "Unimplemented <ea>" stk frame  #
2390 #                                                                       #
2391 # OUTPUT ************************************************************** #
2392 #       If access error:                                                #
2393 #       - The system stack is changed to an access error stack frame    #
2394 #       If FPU disabled:                                                #
2395 #       - The system stack is changed to an FPU disabled stack frame    #
2396 #       If Trace exception enabled:                                     #
2397 #       - The system stack is changed to a Trace exception stack frame  #
2398 #       Else: (normal case)                                             #
2399 #       - None (correct result has been stored as appropriate)          #
2400 #                                                                       #
2401 # ALGORITHM *********************************************************** #
2402 #       This exception handles 3 types of operations:                   #
2403 # (1) FP Instructions using extended precision or packed immediate      #
2404 #     addressing mode.                                                  #
2405 # (2) The "fmovm.x" instruction w/ dynamic register specification.      #
2406 # (3) The "fmovm.l" instruction w/ 2 or 3 control registers.            #
2407 #                                                                       #
2408 #       For immediate data operations, the data is read in w/ a         #
2409 # _mem_read() "callout", converted to FP binary (if packed), and used   #
2410 # as the source operand to the instruction specified by the instruction #
2411 # word. If no FP exception should be reported ads a result of the       #
2412 # emulation, then the result is stored to the destination register and  #
2413 # the handler exits through _fpsp_done(). If an enabled exc has been    #
2414 # signalled as a result of emulation, then an fsave state frame         #
2415 # corresponding to the FP exception type must be entered into the 060   #
2416 # FPU before exiting. In either the enabled or disabled cases, we       #
2417 # must also check if a Trace exception is pending, in which case, we    #
2418 # must create a Trace exception stack frame from the current exception  #
2419 # stack frame. If no Trace is pending, we simply exit through           #
2420 # _fpsp_done().                                                         #
2421 #       For "fmovm.x", call the routine fmovm_dynamic() which will      #
2422 # decode and emulate the instruction. No FP exceptions can be pending   #
2423 # as a result of this operation emulation. A Trace exception can be     #
2424 # pending, though, which means the current stack frame must be changed  #
2425 # to a Trace stack frame and an exit made through _real_trace().        #
2426 # For the case of "fmovm.x Dn,-(a7)", where the offending instruction   #
2427 # was executed from supervisor mode, this handler must store the FP     #
2428 # register file values to the system stack by itself since              #
2429 # fmovm_dynamic() can't handle this. A normal exit is made through      #
2430 # fpsp_done().                                                          #
2431 #       For "fmovm.l", fmovm_ctrl() is used to emulate the instruction. #
2432 # Again, a Trace exception may be pending and an exit made through      #
2433 # _real_trace(). Else, a normal exit is made through _fpsp_done().      #
2434 #                                                                       #
2435 #       Before any of the above is attempted, it must be checked to     #
2436 # see if the FPU is disabled. Since the "Unimp <ea>" exception is taken #
2437 # before the "FPU disabled" exception, but the "FPU disabled" exception #
2438 # has higher priority, we check the disabled bit in the PCR. If set,    #
2439 # then we must create an 8 word "FPU disabled" exception stack frame    #
2440 # from the current 4 word exception stack frame. This includes          #
2441 # reproducing the effective address of the instruction to put on the    #
2442 # new stack frame.                                                      #
2443 #                                                                       #
2444 #       In the process of all emulation work, if a _mem_read()          #
2445 # "callout" returns a failing result indicating an access error, then   #
2446 # we must create an access error stack frame from the current stack     #
2447 # frame. This information includes a faulting address and a fault-      #
2448 # status-longword. These are created within this handler.               #
2449 #                                                                       #
2450 #########################################################################
2451
2452         global          _fpsp_effadd
2453 _fpsp_effadd:
2454
2455 # This exception type takes priority over the "Line F Emulator"
2456 # exception. Therefore, the FPU could be disabled when entering here.
2457 # So, we must check to see if it's disabled and handle that case separately.
2458         mov.l           %d0,-(%sp)              # save d0
2459         movc            %pcr,%d0                # load proc cr
2460         btst            &0x1,%d0                # is FPU disabled?
2461         bne.w           iea_disabled            # yes
2462         mov.l           (%sp)+,%d0              # restore d0
2463
2464         link            %a6,&-LOCAL_SIZE        # init stack frame
2465
2466         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2467         fmovm.l         %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
2468         fmovm.x         &0xc0,EXC_FPREGS(%a6)   # save fp0-fp1 on stack
2469
2470 # PC of instruction that took the exception is the PC in the frame
2471         mov.l           EXC_PC(%a6),EXC_EXTWPTR(%a6)
2472
2473         mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
2474         addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
2475         bsr.l           _imem_read_long         # fetch the instruction words
2476         mov.l           %d0,EXC_OPWORD(%a6)     # store OPWORD and EXTWORD
2477
2478 #########################################################################
2479
2480         tst.w           %d0                     # is operation fmovem?
2481         bmi.w           iea_fmovm               # yes
2482
2483 #
2484 # here, we will have:
2485 #       fabs    fdabs   fsabs           facos           fmod
2486 #       fadd    fdadd   fsadd           fasin           frem
2487 #       fcmp                            fatan           fscale
2488 #       fdiv    fddiv   fsdiv           fatanh          fsin
2489 #       fint                            fcos            fsincos
2490 #       fintrz                          fcosh           fsinh
2491 #       fmove   fdmove  fsmove          fetox           ftan
2492 #       fmul    fdmul   fsmul           fetoxm1         ftanh
2493 #       fneg    fdneg   fsneg           fgetexp         ftentox
2494 #       fsgldiv                         fgetman         ftwotox
2495 #       fsglmul                         flog10
2496 #       fsqrt                           flog2
2497 #       fsub    fdsub   fssub           flogn
2498 #       ftst                            flognp1
2499 # which can all use f<op>.{x,p}
2500 # so, now it's immediate data extended precision AND PACKED FORMAT!
2501 #
2502 iea_op:
2503         andi.l          &0x00ff00ff,USER_FPSR(%a6)
2504
2505         btst            &0xa,%d0                # is src fmt x or p?
2506         bne.b           iea_op_pack             # packed
2507
2508
2509         mov.l           EXC_EXTWPTR(%a6),%a0    # pass: ptr to #<data>
2510         lea             FP_SRC(%a6),%a1         # pass: ptr to super addr
2511         mov.l           &0xc,%d0                # pass: 12 bytes
2512         bsr.l           _imem_read              # read extended immediate
2513
2514         tst.l           %d1                     # did ifetch fail?
2515         bne.w           iea_iacc                # yes
2516
2517         bra.b           iea_op_setsrc
2518
2519 iea_op_pack:
2520
2521         mov.l           EXC_EXTWPTR(%a6),%a0    # pass: ptr to #<data>
2522         lea             FP_SRC(%a6),%a1         # pass: ptr to super dst
2523         mov.l           &0xc,%d0                # pass: 12 bytes
2524         bsr.l           _imem_read              # read packed operand
2525
2526         tst.l           %d1                     # did ifetch fail?
2527         bne.w           iea_iacc                # yes
2528
2529 # The packed operand is an INF or a NAN if the exponent field is all ones.
2530         bfextu          FP_SRC(%a6){&1:&15},%d0 # get exp
2531         cmpi.w          %d0,&0x7fff             # INF or NAN?
2532         beq.b           iea_op_setsrc           # operand is an INF or NAN
2533
2534 # The packed operand is a zero if the mantissa is all zero, else it's
2535 # a normal packed op.
2536         mov.b           3+FP_SRC(%a6),%d0       # get byte 4
2537         andi.b          &0x0f,%d0               # clear all but last nybble
2538         bne.b           iea_op_gp_not_spec      # not a zero
2539         tst.l           FP_SRC_HI(%a6)          # is lw 2 zero?
2540         bne.b           iea_op_gp_not_spec      # not a zero
2541         tst.l           FP_SRC_LO(%a6)          # is lw 3 zero?
2542         beq.b           iea_op_setsrc           # operand is a ZERO
2543 iea_op_gp_not_spec:
2544         lea             FP_SRC(%a6),%a0         # pass: ptr to packed op
2545         bsr.l           decbin                  # convert to extended
2546         fmovm.x         &0x80,FP_SRC(%a6)       # make this the srcop
2547
2548 iea_op_setsrc:
2549         addi.l          &0xc,EXC_EXTWPTR(%a6)   # update extension word pointer
2550
2551 # FP_SRC now holds the src operand.
2552         lea             FP_SRC(%a6),%a0         # pass: ptr to src op
2553         bsr.l           set_tag_x               # tag the operand type
2554         mov.b           %d0,STAG(%a6)           # could be ANYTHING!!!
2555         cmpi.b          %d0,&UNNORM             # is operand an UNNORM?
2556         bne.b           iea_op_getdst           # no
2557         bsr.l           unnorm_fix              # yes; convert to NORM/DENORM/ZERO
2558         mov.b           %d0,STAG(%a6)           # set new optype tag
2559 iea_op_getdst:
2560         clr.b           STORE_FLG(%a6)          # clear "store result" boolean
2561
2562         btst            &0x5,1+EXC_CMDREG(%a6)  # is operation monadic or dyadic?
2563         beq.b           iea_op_extract          # monadic
2564         btst            &0x4,1+EXC_CMDREG(%a6)  # is operation fsincos,ftst,fcmp?
2565         bne.b           iea_op_spec             # yes
2566
2567 iea_op_loaddst:
2568         bfextu          EXC_CMDREG(%a6){&6:&3},%d0 # fetch dst regno
2569         bsr.l           load_fpn2               # load dst operand
2570
2571         lea             FP_DST(%a6),%a0         # pass: ptr to dst op
2572         bsr.l           set_tag_x               # tag the operand type
2573         mov.b           %d0,DTAG(%a6)           # could be ANYTHING!!!
2574         cmpi.b          %d0,&UNNORM             # is operand an UNNORM?
2575         bne.b           iea_op_extract          # no
2576         bsr.l           unnorm_fix              # yes; convert to NORM/DENORM/ZERO
2577         mov.b           %d0,DTAG(%a6)           # set new optype tag
2578         bra.b           iea_op_extract
2579
2580 # the operation is fsincos, ftst, or fcmp. only fcmp is dyadic
2581 iea_op_spec:
2582         btst            &0x3,1+EXC_CMDREG(%a6)  # is operation fsincos?
2583         beq.b           iea_op_extract          # yes
2584 # now, we're left with ftst and fcmp. so, first let's tag them so that they don't
2585 # store a result. then, only fcmp will branch back and pick up a dst operand.
2586         st              STORE_FLG(%a6)          # don't store a final result
2587         btst            &0x1,1+EXC_CMDREG(%a6)  # is operation fcmp?
2588         beq.b           iea_op_loaddst          # yes
2589
2590 iea_op_extract:
2591         clr.l           %d0
2592         mov.b           FPCR_MODE(%a6),%d0      # pass: rnd mode,prec
2593
2594         mov.b           1+EXC_CMDREG(%a6),%d1
2595         andi.w          &0x007f,%d1             # extract extension
2596
2597         fmov.l          &0x0,%fpcr
2598         fmov.l          &0x0,%fpsr
2599
2600         lea             FP_SRC(%a6),%a0
2601         lea             FP_DST(%a6),%a1
2602
2603         mov.l           (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
2604         jsr             (tbl_unsupp.l,%pc,%d1.l*1)
2605
2606 #
2607 # Exceptions in order of precedence:
2608 #       BSUN    : none
2609 #       SNAN    : all operations
2610 #       OPERR   : all reg-reg or mem-reg operations that can normally operr
2611 #       OVFL    : same as OPERR
2612 #       UNFL    : same as OPERR
2613 #       DZ      : same as OPERR
2614 #       INEX2   : same as OPERR
2615 #       INEX1   : all packed immediate operations
2616 #
2617
2618 # we determine the highest priority exception(if any) set by the
2619 # emulation routine that has also been enabled by the user.
2620         mov.b           FPCR_ENABLE(%a6),%d0    # fetch exceptions enabled
2621         bne.b           iea_op_ena              # some are enabled
2622
2623 # now, we save the result, unless, of course, the operation was ftst or fcmp.
2624 # these don't save results.
2625 iea_op_save:
2626         tst.b           STORE_FLG(%a6)          # does this op store a result?
2627         bne.b           iea_op_exit1            # exit with no frestore
2628
2629 iea_op_store:
2630         bfextu          EXC_CMDREG(%a6){&6:&3},%d0 # fetch dst regno
2631         bsr.l           store_fpreg             # store the result
2632
2633 iea_op_exit1:
2634         mov.l           EXC_PC(%a6),USER_FPIAR(%a6) # set FPIAR to "Current PC"
2635         mov.l           EXC_EXTWPTR(%a6),EXC_PC(%a6) # set "Next PC" in exc frame
2636
2637         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
2638         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2639         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2640
2641         unlk            %a6                     # unravel the frame
2642
2643         btst            &0x7,(%sp)              # is trace on?
2644         bne.w           iea_op_trace            # yes
2645
2646         bra.l           _fpsp_done              # exit to os
2647
2648 iea_op_ena:
2649         and.b           FPSR_EXCEPT(%a6),%d0    # keep only ones enable and set
2650         bfffo           %d0{&24:&8},%d0         # find highest priority exception
2651         bne.b           iea_op_exc              # at least one was set
2652
2653 # no exception occurred. now, did a disabled, exact overflow occur with inexact
2654 # enabled? if so, then we have to stuff an overflow frame into the FPU.
2655         btst            &ovfl_bit,FPSR_EXCEPT(%a6) # did overflow occur?
2656         beq.b           iea_op_save
2657
2658 iea_op_ovfl:
2659         btst            &inex2_bit,FPCR_ENABLE(%a6) # is inexact enabled?
2660         beq.b           iea_op_store            # no
2661         bra.b           iea_op_exc_ovfl         # yes
2662
2663 # an enabled exception occurred. we have to insert the exception type back into
2664 # the machine.
2665 iea_op_exc:
2666         subi.l          &24,%d0                 # fix offset to be 0-8
2667         cmpi.b          %d0,&0x6                # is exception INEX?
2668         bne.b           iea_op_exc_force        # no
2669
2670 # the enabled exception was inexact. so, if it occurs with an overflow
2671 # or underflow that was disabled, then we have to force an overflow or
2672 # underflow frame.
2673         btst            &ovfl_bit,FPSR_EXCEPT(%a6) # did overflow occur?
2674         bne.b           iea_op_exc_ovfl         # yes
2675         btst            &unfl_bit,FPSR_EXCEPT(%a6) # did underflow occur?
2676         bne.b           iea_op_exc_unfl         # yes
2677
2678 iea_op_exc_force:
2679         mov.w           (tbl_iea_except.b,%pc,%d0.w*2),2+FP_SRC(%a6)
2680         bra.b           iea_op_exit2            # exit with frestore
2681
2682 tbl_iea_except:
2683         short           0xe002, 0xe006, 0xe004, 0xe005
2684         short           0xe003, 0xe002, 0xe001, 0xe001
2685
2686 iea_op_exc_ovfl:
2687         mov.w           &0xe005,2+FP_SRC(%a6)
2688         bra.b           iea_op_exit2
2689
2690 iea_op_exc_unfl:
2691         mov.w           &0xe003,2+FP_SRC(%a6)
2692
2693 iea_op_exit2:
2694         mov.l           EXC_PC(%a6),USER_FPIAR(%a6) # set FPIAR to "Current PC"
2695         mov.l           EXC_EXTWPTR(%a6),EXC_PC(%a6) # set "Next PC" in exc frame
2696
2697         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
2698         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2699         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2700
2701         frestore        FP_SRC(%a6)             # restore exceptional state
2702
2703         unlk            %a6                     # unravel the frame
2704
2705         btst            &0x7,(%sp)              # is trace on?
2706         bne.b           iea_op_trace            # yes
2707
2708         bra.l           _fpsp_done              # exit to os
2709
2710 #
2711 # The opclass two instruction that took an "Unimplemented Effective Address"
2712 # exception was being traced. Make the "current" PC the FPIAR and put it in
2713 # the trace stack frame then jump to _real_trace().
2714 #
2715 #                UNIMP EA FRAME            TRACE FRAME
2716 #               *****************       *****************
2717 #               * 0x0 *  0x0f0  *       *    Current    *
2718 #               *****************       *      PC       *
2719 #               *    Current    *       *****************
2720 #               *      PC       *       * 0x2 *  0x024  *
2721 #               *****************       *****************
2722 #               *      SR       *       *     Next      *
2723 #               *****************       *      PC       *
2724 #                                       *****************
2725 #                                       *      SR       *
2726 #                                       *****************
2727 iea_op_trace:
2728         mov.l           (%sp),-(%sp)            # shift stack frame "down"
2729         mov.w           0x8(%sp),0x4(%sp)
2730         mov.w           &0x2024,0x6(%sp)        # stk fmt = 0x2; voff = 0x024
2731         fmov.l          %fpiar,0x8(%sp)         # "Current PC" is in FPIAR
2732
2733         bra.l           _real_trace
2734
2735 #########################################################################
2736 iea_fmovm:
2737         btst            &14,%d0                 # ctrl or data reg
2738         beq.w           iea_fmovm_ctrl
2739
2740 iea_fmovm_data:
2741
2742         btst            &0x5,EXC_SR(%a6)        # user or supervisor mode
2743         bne.b           iea_fmovm_data_s
2744
2745 iea_fmovm_data_u:
2746         mov.l           %usp,%a0
2747         mov.l           %a0,EXC_A7(%a6)         # store current a7
2748         bsr.l           fmovm_dynamic           # do dynamic fmovm
2749         mov.l           EXC_A7(%a6),%a0         # load possibly new a7
2750         mov.l           %a0,%usp                # update usp
2751         bra.w           iea_fmovm_exit
2752
2753 iea_fmovm_data_s:
2754         clr.b           SPCOND_FLG(%a6)
2755         lea             0x2+EXC_VOFF(%a6),%a0
2756         mov.l           %a0,EXC_A7(%a6)
2757         bsr.l           fmovm_dynamic           # do dynamic fmovm
2758
2759         cmpi.b          SPCOND_FLG(%a6),&mda7_flg
2760         beq.w           iea_fmovm_data_predec
2761         cmpi.b          SPCOND_FLG(%a6),&mia7_flg
2762         bne.w           iea_fmovm_exit
2763
2764 # right now, d0 = the size.
2765 # the data has been fetched from the supervisor stack, but we have not
2766 # incremented the stack pointer by the appropriate number of bytes.
2767 # do it here.
2768 iea_fmovm_data_postinc:
2769         btst            &0x7,EXC_SR(%a6)
2770         bne.b           iea_fmovm_data_pi_trace
2771
2772         mov.w           EXC_SR(%a6),(EXC_SR,%a6,%d0)
2773         mov.l           EXC_EXTWPTR(%a6),(EXC_PC,%a6,%d0)
2774         mov.w           &0x00f0,(EXC_VOFF,%a6,%d0)
2775
2776         lea             (EXC_SR,%a6,%d0),%a0
2777         mov.l           %a0,EXC_SR(%a6)
2778
2779         fmovm.x         EXC_FP0(%a6),&0xc0      # restore fp0-fp1
2780         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2781         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2782
2783         unlk            %a6
2784         mov.l           (%sp)+,%sp
2785         bra.l           _fpsp_done
2786
2787 iea_fmovm_data_pi_trace:
2788         mov.w           EXC_SR(%a6),(EXC_SR-0x4,%a6,%d0)
2789         mov.l           EXC_EXTWPTR(%a6),(EXC_PC-0x4,%a6,%d0)
2790         mov.w           &0x2024,(EXC_VOFF-0x4,%a6,%d0)
2791         mov.l           EXC_PC(%a6),(EXC_VOFF+0x2-0x4,%a6,%d0)
2792
2793         lea             (EXC_SR-0x4,%a6,%d0),%a0
2794         mov.l           %a0,EXC_SR(%a6)
2795
2796         fmovm.x         EXC_FP0(%a6),&0xc0      # restore fp0-fp1
2797         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2798         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2799
2800         unlk            %a6
2801         mov.l           (%sp)+,%sp
2802         bra.l           _real_trace
2803
2804 # right now, d1 = size and d0 = the strg.
2805 iea_fmovm_data_predec:
2806         mov.b           %d1,EXC_VOFF(%a6)       # store strg
2807         mov.b           %d0,0x1+EXC_VOFF(%a6)   # store size
2808
2809         fmovm.x         EXC_FP0(%a6),&0xc0      # restore fp0-fp1
2810         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2811         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2812
2813         mov.l           (%a6),-(%sp)            # make a copy of a6
2814         mov.l           %d0,-(%sp)              # save d0
2815         mov.l           %d1,-(%sp)              # save d1
2816         mov.l           EXC_EXTWPTR(%a6),-(%sp) # make a copy of Next PC
2817
2818         clr.l           %d0
2819         mov.b           0x1+EXC_VOFF(%a6),%d0   # fetch size
2820         neg.l           %d0                     # get negative of size
2821
2822         btst            &0x7,EXC_SR(%a6)        # is trace enabled?
2823         beq.b           iea_fmovm_data_p2
2824
2825         mov.w           EXC_SR(%a6),(EXC_SR-0x4,%a6,%d0)
2826         mov.l           EXC_PC(%a6),(EXC_VOFF-0x2,%a6,%d0)
2827         mov.l           (%sp)+,(EXC_PC-0x4,%a6,%d0)
2828         mov.w           &0x2024,(EXC_VOFF-0x4,%a6,%d0)
2829
2830         pea             (%a6,%d0)               # create final sp
2831         bra.b           iea_fmovm_data_p3
2832
2833 iea_fmovm_data_p2:
2834         mov.w           EXC_SR(%a6),(EXC_SR,%a6,%d0)
2835         mov.l           (%sp)+,(EXC_PC,%a6,%d0)
2836         mov.w           &0x00f0,(EXC_VOFF,%a6,%d0)
2837
2838         pea             (0x4,%a6,%d0)           # create final sp
2839
2840 iea_fmovm_data_p3:
2841         clr.l           %d1
2842         mov.b           EXC_VOFF(%a6),%d1       # fetch strg
2843
2844         tst.b           %d1
2845         bpl.b           fm_1
2846         fmovm.x         &0x80,(0x4+0x8,%a6,%d0)
2847         addi.l          &0xc,%d0
2848 fm_1:
2849         lsl.b           &0x1,%d1
2850         bpl.b           fm_2
2851         fmovm.x         &0x40,(0x4+0x8,%a6,%d0)
2852         addi.l          &0xc,%d0
2853 fm_2:
2854         lsl.b           &0x1,%d1
2855         bpl.b           fm_3
2856         fmovm.x         &0x20,(0x4+0x8,%a6,%d0)
2857         addi.l          &0xc,%d0
2858 fm_3:
2859         lsl.b           &0x1,%d1
2860         bpl.b           fm_4
2861         fmovm.x         &0x10,(0x4+0x8,%a6,%d0)
2862         addi.l          &0xc,%d0
2863 fm_4:
2864         lsl.b           &0x1,%d1
2865         bpl.b           fm_5
2866         fmovm.x         &0x08,(0x4+0x8,%a6,%d0)
2867         addi.l          &0xc,%d0
2868 fm_5:
2869         lsl.b           &0x1,%d1
2870         bpl.b           fm_6
2871         fmovm.x         &0x04,(0x4+0x8,%a6,%d0)
2872         addi.l          &0xc,%d0
2873 fm_6:
2874         lsl.b           &0x1,%d1
2875         bpl.b           fm_7
2876         fmovm.x         &0x02,(0x4+0x8,%a6,%d0)
2877         addi.l          &0xc,%d0
2878 fm_7:
2879         lsl.b           &0x1,%d1
2880         bpl.b           fm_end
2881         fmovm.x         &0x01,(0x4+0x8,%a6,%d0)
2882 fm_end:
2883         mov.l           0x4(%sp),%d1
2884         mov.l           0x8(%sp),%d0
2885         mov.l           0xc(%sp),%a6
2886         mov.l           (%sp)+,%sp
2887
2888         btst            &0x7,(%sp)              # is trace enabled?
2889         beq.l           _fpsp_done
2890         bra.l           _real_trace
2891
2892 #########################################################################
2893 iea_fmovm_ctrl:
2894
2895         bsr.l           fmovm_ctrl              # load ctrl regs
2896
2897 iea_fmovm_exit:
2898         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
2899         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
2900         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2901
2902         btst            &0x7,EXC_SR(%a6)        # is trace on?
2903         bne.b           iea_fmovm_trace         # yes
2904
2905         mov.l           EXC_EXTWPTR(%a6),EXC_PC(%a6) # set Next PC
2906
2907         unlk            %a6                     # unravel the frame
2908
2909         bra.l           _fpsp_done              # exit to os
2910
2911 #
2912 # The control reg instruction that took an "Unimplemented Effective Address"
2913 # exception was being traced. The "Current PC" for the trace frame is the
2914 # PC stacked for Unimp EA. The "Next PC" is in EXC_EXTWPTR.
2915 # After fixing the stack frame, jump to _real_trace().
2916 #
2917 #                UNIMP EA FRAME            TRACE FRAME
2918 #               *****************       *****************
2919 #               * 0x0 *  0x0f0  *       *    Current    *
2920 #               *****************       *      PC       *
2921 #               *    Current    *       *****************
2922 #               *      PC       *       * 0x2 *  0x024  *
2923 #               *****************       *****************
2924 #               *      SR       *       *     Next      *
2925 #               *****************       *      PC       *
2926 #                                       *****************
2927 #                                       *      SR       *
2928 #                                       *****************
2929 # this ain't a pretty solution, but it works:
2930 # -restore a6 (not with unlk)
2931 # -shift stack frame down over where old a6 used to be
2932 # -add LOCAL_SIZE to stack pointer
2933 iea_fmovm_trace:
2934         mov.l           (%a6),%a6               # restore frame pointer
2935         mov.w           EXC_SR+LOCAL_SIZE(%sp),0x0+LOCAL_SIZE(%sp)
2936         mov.l           EXC_PC+LOCAL_SIZE(%sp),0x8+LOCAL_SIZE(%sp)
2937         mov.l           EXC_EXTWPTR+LOCAL_SIZE(%sp),0x2+LOCAL_SIZE(%sp)
2938         mov.w           &0x2024,0x6+LOCAL_SIZE(%sp) # stk fmt = 0x2; voff = 0x024
2939         add.l           &LOCAL_SIZE,%sp         # clear stack frame
2940
2941         bra.l           _real_trace
2942
2943 #########################################################################
2944 # The FPU is disabled and so we should really have taken the "Line
2945 # F Emulator" exception. So, here we create an 8-word stack frame
2946 # from our 4-word stack frame. This means we must calculate the length
2947 # the faulting instruction to get the "next PC". This is trivial for
2948 # immediate operands but requires some extra work for fmovm dynamic
2949 # which can use most addressing modes.
2950 iea_disabled:
2951         mov.l           (%sp)+,%d0              # restore d0
2952
2953         link            %a6,&-LOCAL_SIZE        # init stack frame
2954
2955         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2956
2957 # PC of instruction that took the exception is the PC in the frame
2958         mov.l           EXC_PC(%a6),EXC_EXTWPTR(%a6)
2959         mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
2960         addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
2961         bsr.l           _imem_read_long         # fetch the instruction words
2962         mov.l           %d0,EXC_OPWORD(%a6)     # store OPWORD and EXTWORD
2963
2964         tst.w           %d0                     # is instr fmovm?
2965         bmi.b           iea_dis_fmovm           # yes
2966 # instruction is using an extended precision immediate operand. Therefore,
2967 # the total instruction length is 16 bytes.
2968 iea_dis_immed:
2969         mov.l           &0x10,%d0               # 16 bytes of instruction
2970         bra.b           iea_dis_cont
2971 iea_dis_fmovm:
2972         btst            &0xe,%d0                # is instr fmovm ctrl
2973         bne.b           iea_dis_fmovm_data      # no
2974 # the instruction is a fmovm.l with 2 or 3 registers.
2975         bfextu          %d0{&19:&3},%d1
2976         mov.l           &0xc,%d0
2977         cmpi.b          %d1,&0x7                # move all regs?
2978         bne.b           iea_dis_cont
2979         addq.l          &0x4,%d0
2980         bra.b           iea_dis_cont
2981 # the instruction is an fmovm.x dynamic which can use many addressing
2982 # modes and thus can have several different total instruction lengths.
2983 # call fmovm_calc_ea which will go through the ea calc process and,
2984 # as a by-product, will tell us how long the instruction is.
2985 iea_dis_fmovm_data:
2986         clr.l           %d0
2987         bsr.l           fmovm_calc_ea
2988         mov.l           EXC_EXTWPTR(%a6),%d0
2989         sub.l           EXC_PC(%a6),%d0
2990 iea_dis_cont:
2991         mov.w           %d0,EXC_VOFF(%a6)       # store stack shift value
2992
2993         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2994
2995         unlk            %a6
2996
2997 # here, we actually create the 8-word frame from the 4-word frame,
2998 # with the "next PC" as additional info.
2999 # the <ea> field is let as undefined.
3000         subq.l          &0x8,%sp                # make room for new stack
3001         mov.l           %d0,-(%sp)              # save d0
3002         mov.w           0xc(%sp),0x4(%sp)       # move SR
3003         mov.l           0xe(%sp),0x6(%sp)       # move Current PC
3004         clr.l           %d0
3005         mov.w           0x12(%sp),%d0
3006         mov.l           0x6(%sp),0x10(%sp)      # move Current PC
3007         add.l           %d0,0x6(%sp)            # make Next PC
3008         mov.w           &0x402c,0xa(%sp)        # insert offset,frame format
3009         mov.l           (%sp)+,%d0              # restore d0
3010
3011         bra.l           _real_fpu_disabled
3012
3013 ##########
3014
3015 iea_iacc:
3016         movc            %pcr,%d0
3017         btst            &0x1,%d0
3018         bne.b           iea_iacc_cont
3019         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
3020         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1 on stack
3021 iea_iacc_cont:
3022         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3023
3024         unlk            %a6
3025
3026         subq.w          &0x8,%sp                # make stack frame bigger
3027         mov.l           0x8(%sp),(%sp)          # store SR,hi(PC)
3028         mov.w           0xc(%sp),0x4(%sp)       # store lo(PC)
3029         mov.w           &0x4008,0x6(%sp)        # store voff
3030         mov.l           0x2(%sp),0x8(%sp)       # store ea
3031         mov.l           &0x09428001,0xc(%sp)    # store fslw
3032
3033 iea_acc_done:
3034         btst            &0x5,(%sp)              # user or supervisor mode?
3035         beq.b           iea_acc_done2           # user
3036         bset            &0x2,0xd(%sp)           # set supervisor TM bit
3037
3038 iea_acc_done2:
3039         bra.l           _real_access
3040
3041 iea_dacc:
3042         lea             -LOCAL_SIZE(%a6),%sp
3043
3044         movc            %pcr,%d1
3045         btst            &0x1,%d1
3046         bne.b           iea_dacc_cont
3047         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1 on stack
3048         fmovm.l         LOCAL_SIZE+USER_FPCR(%sp),%fpcr,%fpsr,%fpiar # restore ctrl regs
3049 iea_dacc_cont:
3050         mov.l           (%a6),%a6
3051
3052         mov.l           0x4+LOCAL_SIZE(%sp),-0x8+0x4+LOCAL_SIZE(%sp)
3053         mov.w           0x8+LOCAL_SIZE(%sp),-0x8+0x8+LOCAL_SIZE(%sp)
3054         mov.w           &0x4008,-0x8+0xa+LOCAL_SIZE(%sp)
3055         mov.l           %a0,-0x8+0xc+LOCAL_SIZE(%sp)
3056         mov.w           %d0,-0x8+0x10+LOCAL_SIZE(%sp)
3057         mov.w           &0x0001,-0x8+0x12+LOCAL_SIZE(%sp)
3058
3059         movm.l          LOCAL_SIZE+EXC_DREGS(%sp),&0x0303 # restore d0-d1/a0-a1
3060         add.w           &LOCAL_SIZE-0x4,%sp
3061
3062         bra.b           iea_acc_done
3063
3064 #########################################################################
3065 # XDEF **************************************************************** #
3066 #       _fpsp_operr(): 060FPSP entry point for FP Operr exception.      #
3067 #                                                                       #
3068 #       This handler should be the first code executed upon taking the  #
3069 #       FP Operand Error exception in an operating system.              #
3070 #                                                                       #
3071 # XREF **************************************************************** #
3072 #       _imem_read_long() - read instruction longword                   #
3073 #       fix_skewed_ops() - adjust src operand in fsave frame            #
3074 #       _real_operr() - "callout" to operating system operr handler     #
3075 #       _dmem_write_{byte,word,long}() - store data to mem (opclass 3)  #
3076 #       store_dreg_{b,w,l}() - store data to data regfile (opclass 3)   #
3077 #       facc_out_{b,w,l}() - store to memory took access error (opcl 3) #
3078 #                                                                       #
3079 # INPUT *************************************************************** #
3080 #       - The system stack contains the FP Operr exception frame        #
3081 #       - The fsave frame contains the source operand                   #
3082 #                                                                       #
3083 # OUTPUT ************************************************************** #
3084 #       No access error:                                                #
3085 #       - The system stack is unchanged                                 #
3086 #       - The fsave frame contains the adjusted src op for opclass 0,2  #
3087 #                                                                       #
3088 # ALGORITHM *********************************************************** #
3089 #       In a system where the FP Operr exception is enabled, the goal   #
3090 # is to get to the handler specified at _real_operr(). But, on the 060, #
3091 # for opclass zero and two instruction taking this exception, the       #
3092 # input operand in the fsave frame may be incorrect for some cases      #
3093 # and needs to be corrected. This handler calls fix_skewed_ops() to     #
3094 # do just this and then exits through _real_operr().                    #
3095 #       For opclass 3 instructions, the 060 doesn't store the default   #
3096 # operr result out to memory or data register file as it should.        #
3097 # This code must emulate the move out before finally exiting through    #
3098 # _real_inex(). The move out, if to memory, is performed using          #
3099 # _mem_write() "callout" routines that may return a failing result.     #
3100 # In this special case, the handler must exit through facc_out()        #
3101 # which creates an access error stack frame from the current operr      #
3102 # stack frame.                                                          #
3103 #                                                                       #
3104 #########################################################################
3105
3106         global          _fpsp_operr
3107 _fpsp_operr:
3108
3109         link.w          %a6,&-LOCAL_SIZE        # init stack frame
3110
3111         fsave           FP_SRC(%a6)             # grab the "busy" frame
3112
3113         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3114         fmovm.l         %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
3115         fmovm.x         &0xc0,EXC_FPREGS(%a6)   # save fp0-fp1 on stack
3116
3117 # the FPIAR holds the "current PC" of the faulting instruction
3118         mov.l           USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
3119
3120         mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
3121         addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
3122         bsr.l           _imem_read_long         # fetch the instruction words
3123         mov.l           %d0,EXC_OPWORD(%a6)
3124
3125 ##############################################################################
3126
3127         btst            &13,%d0                 # is instr an fmove out?
3128         bne.b           foperr_out              # fmove out
3129
3130
3131 # here, we simply see if the operand in the fsave frame needs to be "unskewed".
3132 # this would be the case for opclass two operations with a source infinity or
3133 # denorm operand in the sgl or dbl format. NANs also become skewed, but can't
3134 # cause an operr so we don't need to check for them here.
3135         lea             FP_SRC(%a6),%a0         # pass: ptr to src op
3136         bsr.l           fix_skewed_ops          # fix src op
3137
3138 foperr_exit:
3139         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
3140         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
3141         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3142
3143         frestore        FP_SRC(%a6)
3144
3145         unlk            %a6
3146         bra.l           _real_operr
3147
3148 ########################################################################
3149
3150 #
3151 # the hardware does not save the default result to memory on enabled
3152 # operand error exceptions. we do this here before passing control to
3153 # the user operand error handler.
3154 #
3155 # byte, word, and long destination format operations can pass
3156 # through here. we simply need to test the sign of the src
3157 # operand and save the appropriate minimum or maximum integer value
3158 # to the effective address as pointed to by the stacked effective address.
3159 #
3160 # although packed opclass three operations can take operand error
3161 # exceptions, they won't pass through here since they are caught
3162 # first by the unsupported data format exception handler. that handler
3163 # sends them directly to _real_operr() if necessary.
3164 #
3165 foperr_out:
3166
3167         mov.w           FP_SRC_EX(%a6),%d1      # fetch exponent
3168         andi.w          &0x7fff,%d1
3169         cmpi.w          %d1,&0x7fff
3170         bne.b           foperr_out_not_qnan
3171 # the operand is either an infinity or a QNAN.
3172         tst.l           FP_SRC_LO(%a6)
3173         bne.b           foperr_out_qnan
3174         mov.l           FP_SRC_HI(%a6),%d1
3175         andi.l          &0x7fffffff,%d1
3176         beq.b           foperr_out_not_qnan
3177 foperr_out_qnan:
3178         mov.l           FP_SRC_HI(%a6),L_SCR1(%a6)
3179         bra.b           foperr_out_jmp
3180
3181 foperr_out_not_qnan:
3182         mov.l           &0x7fffffff,%d1
3183         tst.b           FP_SRC_EX(%a6)
3184         bpl.b           foperr_out_not_qnan2
3185         addq.l          &0x1,%d1
3186 foperr_out_not_qnan2:
3187         mov.l           %d1,L_SCR1(%a6)
3188
3189 foperr_out_jmp:
3190         bfextu          %d0{&19:&3},%d0         # extract dst format field
3191         mov.b           1+EXC_OPWORD(%a6),%d1   # extract <ea> mode,reg
3192         mov.w           (tbl_operr.b,%pc,%d0.w*2),%a0
3193         jmp             (tbl_operr.b,%pc,%a0)
3194
3195 tbl_operr:
3196         short           foperr_out_l - tbl_operr # long word integer
3197         short           tbl_operr    - tbl_operr # sgl prec shouldn't happen
3198         short           tbl_operr    - tbl_operr # ext prec shouldn't happen
3199         short           foperr_exit  - tbl_operr # packed won't enter here
3200         short           foperr_out_w - tbl_operr # word integer
3201         short           tbl_operr    - tbl_operr # dbl prec shouldn't happen
3202         short           foperr_out_b - tbl_operr # byte integer
3203         short           tbl_operr    - tbl_operr # packed won't enter here
3204
3205 foperr_out_b:
3206         mov.b           L_SCR1(%a6),%d0         # load positive default result
3207         cmpi.b          %d1,&0x7                # is <ea> mode a data reg?
3208         ble.b           foperr_out_b_save_dn    # yes
3209         mov.l           EXC_EA(%a6),%a0         # pass: <ea> of default result
3210         bsr.l           _dmem_write_byte        # write the default result
3211
3212         tst.l           %d1                     # did dstore fail?
3213         bne.l           facc_out_b              # yes
3214
3215         bra.w           foperr_exit
3216 foperr_out_b_save_dn:
3217         andi.w          &0x0007,%d1
3218         bsr.l           store_dreg_b            # store result to regfile
3219         bra.w           foperr_exit
3220
3221 foperr_out_w:
3222         mov.w           L_SCR1(%a6),%d0         # load positive default result
3223         cmpi.b          %d1,&0x7                # is <ea> mode a data reg?
3224         ble.b           foperr_out_w_save_dn    # yes
3225         mov.l           EXC_EA(%a6),%a0         # pass: <ea> of default result
3226         bsr.l           _dmem_write_word        # write the default result
3227
3228         tst.l           %d1                     # did dstore fail?
3229         bne.l           facc_out_w              # yes
3230
3231         bra.w           foperr_exit
3232 foperr_out_w_save_dn:
3233         andi.w          &0x0007,%d1
3234         bsr.l           store_dreg_w            # store result to regfile
3235         bra.w           foperr_exit
3236
3237 foperr_out_l:
3238         mov.l           L_SCR1(%a6),%d0         # load positive default result
3239         cmpi.b          %d1,&0x7                # is <ea> mode a data reg?
3240         ble.b           foperr_out_l_save_dn    # yes
3241         mov.l           EXC_EA(%a6),%a0         # pass: <ea> of default result
3242         bsr.l           _dmem_write_long        # write the default result
3243
3244         tst.l           %d1                     # did dstore fail?
3245         bne.l           facc_out_l              # yes
3246
3247         bra.w           foperr_exit
3248 foperr_out_l_save_dn:
3249         andi.w          &0x0007,%d1
3250         bsr.l           store_dreg_l            # store result to regfile
3251         bra.w           foperr_exit
3252
3253 #########################################################################
3254 # XDEF **************************************************************** #
3255 #       _fpsp_snan(): 060FPSP entry point for FP SNAN exception.        #
3256 #                                                                       #
3257 #       This handler should be the first code executed upon taking the  #
3258 #       FP Signalling NAN exception in an operating system.             #
3259 #                                                                       #
3260 # XREF **************************************************************** #
3261 #       _imem_read_long() - read instruction longword                   #
3262 #       fix_skewed_ops() - adjust src operand in fsave frame            #
3263 #       _real_snan() - "callout" to operating system SNAN handler       #
3264 #       _dmem_write_{byte,word,long}() - store data to mem (opclass 3)  #
3265 #       store_dreg_{b,w,l}() - store data to data regfile (opclass 3)   #
3266 #       facc_out_{b,w,l,d,x}() - store to mem took acc error (opcl 3)   #
3267 #       _calc_ea_fout() - fix An if <ea> is -() or ()+; also get <ea>   #
3268 #                                                                       #
3269 # INPUT *************************************************************** #
3270 #       - The system stack contains the FP SNAN exception frame         #
3271 #       - The fsave frame contains the source operand                   #
3272 #                                                                       #
3273 # OUTPUT ************************************************************** #
3274 #       No access error:                                                #
3275 #       - The system stack is unchanged                                 #
3276 #       - The fsave frame contains the adjusted src op for opclass 0,2  #
3277 #                                                                       #
3278 # ALGORITHM *********************************************************** #
3279 #       In a system where the FP SNAN exception is enabled, the goal    #
3280 # is to get to the handler specified at _real_snan(). But, on the 060,  #
3281 # for opclass zero and two instructions taking this exception, the      #
3282 # input operand in the fsave frame may be incorrect for some cases      #
3283 # and needs to be corrected. This handler calls fix_skewed_ops() to     #
3284 # do just this and then exits through _real_snan().                     #
3285 #       For opclass 3 instructions, the 060 doesn't store the default   #
3286 # SNAN result out to memory or data register file as it should.         #
3287 # This code must emulate the move out before finally exiting through    #
3288 # _real_snan(). The move out, if to memory, is performed using          #
3289 # _mem_write() "callout" routines that may return a failing result.     #
3290 # In this special case, the handler must exit through facc_out()        #
3291 # which creates an access error stack frame from the current SNAN       #
3292 # stack frame.                                                          #
3293 #       For the case of an extended precision opclass 3 instruction,    #
3294 # if the effective addressing mode was -() or ()+, then the address     #
3295 # register must get updated by calling _calc_ea_fout(). If the <ea>     #
3296 # was -(a7) from supervisor mode, then the exception frame currently    #
3297 # on the system stack must be carefully moved "down" to make room       #
3298 # for the operand being moved.                                          #
3299 #                                                                       #
3300 #########################################################################
3301
3302         global          _fpsp_snan
3303 _fpsp_snan:
3304
3305         link.w          %a6,&-LOCAL_SIZE        # init stack frame
3306
3307         fsave           FP_SRC(%a6)             # grab the "busy" frame
3308
3309         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3310         fmovm.l         %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
3311         fmovm.x         &0xc0,EXC_FPREGS(%a6)   # save fp0-fp1 on stack
3312
3313 # the FPIAR holds the "current PC" of the faulting instruction
3314         mov.l           USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
3315
3316         mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
3317         addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
3318         bsr.l           _imem_read_long         # fetch the instruction words
3319         mov.l           %d0,EXC_OPWORD(%a6)
3320
3321 ##############################################################################
3322
3323         btst            &13,%d0                 # is instr an fmove out?
3324         bne.w           fsnan_out               # fmove out
3325
3326
3327 # here, we simply see if the operand in the fsave frame needs to be "unskewed".
3328 # this would be the case for opclass two operations with a source infinity or
3329 # denorm operand in the sgl or dbl format. NANs also become skewed and must be
3330 # fixed here.
3331         lea             FP_SRC(%a6),%a0         # pass: ptr to src op
3332         bsr.l           fix_skewed_ops          # fix src op
3333
3334 fsnan_exit:
3335         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
3336         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
3337         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3338
3339         frestore        FP_SRC(%a6)
3340
3341         unlk            %a6
3342         bra.l           _real_snan
3343
3344 ########################################################################
3345
3346 #
3347 # the hardware does not save the default result to memory on enabled
3348 # snan exceptions. we do this here before passing control to
3349 # the user snan handler.
3350 #
3351 # byte, word, long, and packed destination format operations can pass
3352 # through here. since packed format operations already were handled by
3353 # fpsp_unsupp(), then we need to do nothing else for them here.
3354 # for byte, word, and long, we simply need to test the sign of the src
3355 # operand and save the appropriate minimum or maximum integer value
3356 # to the effective address as pointed to by the stacked effective address.
3357 #
3358 fsnan_out:
3359
3360         bfextu          %d0{&19:&3},%d0         # extract dst format field
3361         mov.b           1+EXC_OPWORD(%a6),%d1   # extract <ea> mode,reg
3362         mov.w           (tbl_snan.b,%pc,%d0.w*2),%a0
3363         jmp             (tbl_snan.b,%pc,%a0)
3364
3365 tbl_snan:
3366         short           fsnan_out_l - tbl_snan # long word integer
3367         short           fsnan_out_s - tbl_snan # sgl prec shouldn't happen
3368         short           fsnan_out_x - tbl_snan # ext prec shouldn't happen
3369         short           tbl_snan    - tbl_snan # packed needs no help
3370         short           fsnan_out_w - tbl_snan # word integer
3371         short           fsnan_out_d - tbl_snan # dbl prec shouldn't happen
3372         short           fsnan_out_b - tbl_snan # byte integer
3373         short           tbl_snan    - tbl_snan # packed needs no help
3374
3375 fsnan_out_b:
3376         mov.b           FP_SRC_HI(%a6),%d0      # load upper byte of SNAN
3377         bset            &6,%d0                  # set SNAN bit
3378         cmpi.b          %d1,&0x7                # is <ea> mode a data reg?
3379         ble.b           fsnan_out_b_dn          # yes
3380         mov.l           EXC_EA(%a6),%a0         # pass: <ea> of default result
3381         bsr.l           _dmem_write_byte        # write the default result
3382
3383         tst.l           %d1                     # did dstore fail?
3384         bne.l           facc_out_b              # yes
3385
3386         bra.w           fsnan_exit
3387 fsnan_out_b_dn:
3388         andi.w          &0x0007,%d1
3389         bsr.l           store_dreg_b            # store result to regfile
3390         bra.w           fsnan_exit
3391
3392 fsnan_out_w:
3393         mov.w           FP_SRC_HI(%a6),%d0      # load upper word of SNAN
3394         bset            &14,%d0                 # set SNAN bit
3395         cmpi.b          %d1,&0x7                # is <ea> mode a data reg?
3396         ble.b           fsnan_out_w_dn          # yes
3397         mov.l           EXC_EA(%a6),%a0         # pass: <ea> of default result
3398         bsr.l           _dmem_write_word        # write the default result
3399
3400         tst.l           %d1                     # did dstore fail?
3401         bne.l           facc_out_w              # yes
3402
3403         bra.w           fsnan_exit
3404 fsnan_out_w_dn:
3405         andi.w          &0x0007,%d1
3406         bsr.l           store_dreg_w            # store result to regfile
3407         bra.w           fsnan_exit
3408
3409 fsnan_out_l:
3410         mov.l           FP_SRC_HI(%a6),%d0      # load upper longword of SNAN
3411         bset            &30,%d0                 # set SNAN bit
3412         cmpi.b          %d1,&0x7                # is <ea> mode a data reg?
3413         ble.b           fsnan_out_l_dn          # yes
3414         mov.l           EXC_EA(%a6),%a0         # pass: <ea> of default result
3415         bsr.l           _dmem_write_long        # write the default result
3416
3417         tst.l           %d1                     # did dstore fail?
3418         bne.l           facc_out_l              # yes
3419
3420         bra.w           fsnan_exit
3421 fsnan_out_l_dn:
3422         andi.w          &0x0007,%d1
3423         bsr.l           store_dreg_l            # store result to regfile
3424         bra.w           fsnan_exit
3425
3426 fsnan_out_s:
3427         cmpi.b          %d1,&0x7                # is <ea> mode a data reg?
3428         ble.b           fsnan_out_d_dn          # yes
3429         mov.l           FP_SRC_EX(%a6),%d0      # fetch SNAN sign
3430         andi.l          &0x80000000,%d0         # keep sign
3431         ori.l           &0x7fc00000,%d0         # insert new exponent,SNAN bit
3432         mov.l           FP_SRC_HI(%a6),%d1      # load mantissa
3433         lsr.l           &0x8,%d1                # shift mantissa for sgl
3434         or.l            %d1,%d0                 # create sgl SNAN
3435         mov.l           EXC_EA(%a6),%a0         # pass: <ea> of default result
3436         bsr.l           _dmem_write_long        # write the default result
3437
3438         tst.l           %d1                     # did dstore fail?
3439         bne.l           facc_out_l              # yes
3440
3441         bra.w           fsnan_exit
3442 fsnan_out_d_dn:
3443         mov.l           FP_SRC_EX(%a6),%d0      # fetch SNAN sign
3444         andi.l          &0x80000000,%d0         # keep sign
3445         ori.l           &0x7fc00000,%d0         # insert new exponent,SNAN bit
3446         mov.l           %d1,-(%sp)
3447         mov.l           FP_SRC_HI(%a6),%d1      # load mantissa
3448         lsr.l           &0x8,%d1                # shift mantissa for sgl
3449         or.l            %d1,%d0                 # create sgl SNAN
3450         mov.l           (%sp)+,%d1
3451         andi.w          &0x0007,%d1
3452         bsr.l           store_dreg_l            # store result to regfile
3453         bra.w           fsnan_exit
3454
3455 fsnan_out_d:
3456         mov.l           FP_SRC_EX(%a6),%d0      # fetch SNAN sign
3457         andi.l          &0x80000000,%d0         # keep sign
3458         ori.l           &0x7ff80000,%d0         # insert new exponent,SNAN bit
3459         mov.l           FP_SRC_HI(%a6),%d1      # load hi mantissa
3460         mov.l           %d0,FP_SCR0_EX(%a6)     # store to temp space
3461         mov.l           &11,%d0                 # load shift amt
3462         lsr.l           %d0,%d1
3463         or.l            %d1,FP_SCR0_EX(%a6)     # create dbl hi
3464         mov.l           FP_SRC_HI(%a6),%d1      # load hi mantissa
3465         andi.l          &0x000007ff,%d1
3466         ror.l           %d0,%d1
3467         mov.l           %d1,FP_SCR0_HI(%a6)     # store to temp space
3468         mov.l           FP_SRC_LO(%a6),%d1      # load lo mantissa
3469         lsr.l           %d0,%d1
3470         or.l            %d1,FP_SCR0_HI(%a6)     # create dbl lo
3471         lea             FP_SCR0(%a6),%a0        # pass: ptr to operand
3472         mov.l           EXC_EA(%a6),%a1         # pass: dst addr
3473         movq.l          &0x8,%d0                # pass: size of 8 bytes
3474         bsr.l           _dmem_write             # write the default result
3475
3476         tst.l           %d1                     # did dstore fail?
3477         bne.l           facc_out_d              # yes
3478
3479         bra.w           fsnan_exit
3480
3481 # for extended precision, if the addressing mode is pre-decrement or
3482 # post-increment, then the address register did not get updated.
3483 # in addition, for pre-decrement, the stacked <ea> is incorrect.
3484 fsnan_out_x:
3485         clr.b           SPCOND_FLG(%a6)         # clear special case flag
3486
3487         mov.w           FP_SRC_EX(%a6),FP_SCR0_EX(%a6)
3488         clr.w           2+FP_SCR0(%a6)
3489         mov.l           FP_SRC_HI(%a6),%d0
3490         bset            &30,%d0
3491         mov.l           %d0,FP_SCR0_HI(%a6)
3492         mov.l           FP_SRC_LO(%a6),FP_SCR0_LO(%a6)
3493
3494         btst            &0x5,EXC_SR(%a6)        # supervisor mode exception?
3495         bne.b           fsnan_out_x_s           # yes
3496
3497         mov.l           %usp,%a0                # fetch user stack pointer
3498         mov.l           %a0,EXC_A7(%a6)         # save on stack for calc_ea()
3499         mov.l           (%a6),EXC_A6(%a6)
3500
3501         bsr.l           _calc_ea_fout           # find the correct ea,update An
3502         mov.l           %a0,%a1
3503         mov.l           %a0,EXC_EA(%a6)         # stack correct <ea>
3504
3505         mov.l           EXC_A7(%a6),%a0
3506         mov.l           %a0,%usp                # restore user stack pointer
3507         mov.l           EXC_A6(%a6),(%a6)
3508
3509 fsnan_out_x_save:
3510         lea             FP_SCR0(%a6),%a0        # pass: ptr to operand
3511         movq.l          &0xc,%d0                # pass: size of extended
3512         bsr.l           _dmem_write             # write the default result
3513
3514         tst.l           %d1                     # did dstore fail?
3515         bne.l           facc_out_x              # yes
3516
3517         bra.w           fsnan_exit
3518
3519 fsnan_out_x_s:
3520         mov.l           (%a6),EXC_A6(%a6)
3521
3522         bsr.l           _calc_ea_fout           # find the correct ea,update An
3523         mov.l           %a0,%a1
3524         mov.l           %a0,EXC_EA(%a6)         # stack correct <ea>
3525
3526         mov.l           EXC_A6(%a6),(%a6)
3527
3528         cmpi.b          SPCOND_FLG(%a6),&mda7_flg # is <ea> mode -(a7)?
3529         bne.b           fsnan_out_x_save        # no
3530
3531 # the operation was "fmove.x SNAN,-(a7)" from supervisor mode.
3532         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
3533         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
3534         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3535
3536         frestore        FP_SRC(%a6)
3537
3538         mov.l           EXC_A6(%a6),%a6         # restore frame pointer
3539
3540         mov.l           LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
3541         mov.l           LOCAL_SIZE+EXC_PC+0x2(%sp),LOCAL_SIZE+EXC_PC+0x2-0xc(%sp)
3542         mov.l           LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
3543
3544         mov.l           LOCAL_SIZE+FP_SCR0_EX(%sp),LOCAL_SIZE+EXC_SR(%sp)
3545         mov.l           LOCAL_SIZE+FP_SCR0_HI(%sp),LOCAL_SIZE+EXC_PC+0x2(%sp)
3546         mov.l           LOCAL_SIZE+FP_SCR0_LO(%sp),LOCAL_SIZE+EXC_EA(%sp)
3547
3548         add.l           &LOCAL_SIZE-0x8,%sp
3549
3550         bra.l           _real_snan
3551
3552 #########################################################################
3553 # XDEF **************************************************************** #
3554 #       _fpsp_inex(): 060FPSP entry point for FP Inexact exception.     #
3555 #                                                                       #
3556 #       This handler should be the first code executed upon taking the  #
3557 #       FP Inexact exception in an operating system.                    #
3558 #                                                                       #
3559 # XREF **************************************************************** #
3560 #       _imem_read_long() - read instruction longword                   #
3561 #       fix_skewed_ops() - adjust src operand in fsave frame            #
3562 #       set_tag_x() - determine optype of src/dst operands              #
3563 #       store_fpreg() - store opclass 0 or 2 result to FP regfile       #
3564 #       unnorm_fix() - change UNNORM operands to NORM or ZERO           #
3565 #       load_fpn2() - load dst operand from FP regfile                  #
3566 #       smovcr() - emulate an "fmovcr" instruction                      #
3567 #       fout() - emulate an opclass 3 instruction                       #
3568 #       tbl_unsupp - add of table of emulation routines for opclass 0,2 #
3569 #       _real_inex() - "callout" to operating system inexact handler    #
3570 #                                                                       #
3571 # INPUT *************************************************************** #
3572 #       - The system stack contains the FP Inexact exception frame      #
3573 #       - The fsave frame contains the source operand                   #
3574 #                                                                       #
3575 # OUTPUT ************************************************************** #
3576 #       - The system stack is unchanged                                 #
3577 #       - The fsave frame contains the adjusted src op for opclass 0,2  #
3578 #                                                                       #
3579 # ALGORITHM *********************************************************** #
3580 #       In a system where the FP Inexact exception is enabled, the goal #
3581 # is to get to the handler specified at _real_inex(). But, on the 060,  #
3582 # for opclass zero and two instruction taking this exception, the       #
3583 # hardware doesn't store the correct result to the destination FP       #
3584 # register as did the '040 and '881/2. This handler must emulate the    #
3585 # instruction in order to get this value and then store it to the       #
3586 # correct register before calling _real_inex().                         #
3587 #       For opclass 3 instructions, the 060 doesn't store the default   #
3588 # inexact result out to memory or data register file as it should.      #
3589 # This code must emulate the move out by calling fout() before finally  #
3590 # exiting through _real_inex().                                         #
3591 #                                                                       #
3592 #########################################################################
3593
3594         global          _fpsp_inex
3595 _fpsp_inex:
3596
3597         link.w          %a6,&-LOCAL_SIZE        # init stack frame
3598
3599         fsave           FP_SRC(%a6)             # grab the "busy" frame
3600
3601         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3602         fmovm.l         %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
3603         fmovm.x         &0xc0,EXC_FPREGS(%a6)   # save fp0-fp1 on stack
3604
3605 # the FPIAR holds the "current PC" of the faulting instruction
3606         mov.l           USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
3607
3608         mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
3609         addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
3610         bsr.l           _imem_read_long         # fetch the instruction words
3611         mov.l           %d0,EXC_OPWORD(%a6)
3612
3613 ##############################################################################
3614
3615         btst            &13,%d0                 # is instr an fmove out?
3616         bne.w           finex_out               # fmove out
3617
3618
3619 # the hardware, for "fabs" and "fneg" w/ a long source format, puts the
3620 # longword integer directly into the upper longword of the mantissa along
3621 # w/ an exponent value of 0x401e. we convert this to extended precision here.
3622         bfextu          %d0{&19:&3},%d0         # fetch instr size
3623         bne.b           finex_cont              # instr size is not long
3624         cmpi.w          FP_SRC_EX(%a6),&0x401e  # is exponent 0x401e?
3625         bne.b           finex_cont              # no
3626         fmov.l          &0x0,%fpcr
3627         fmov.l          FP_SRC_HI(%a6),%fp0     # load integer src
3628         fmov.x          %fp0,FP_SRC(%a6)        # store integer as extended precision
3629         mov.w           &0xe001,0x2+FP_SRC(%a6)
3630
3631 finex_cont:
3632         lea             FP_SRC(%a6),%a0         # pass: ptr to src op
3633         bsr.l           fix_skewed_ops          # fix src op
3634
3635 # Here, we zero the ccode and exception byte field since we're going to
3636 # emulate the whole instruction. Notice, though, that we don't kill the
3637 # INEX1 bit. This is because a packed op has long since been converted
3638 # to extended before arriving here. Therefore, we need to retain the
3639 # INEX1 bit from when the operand was first converted.
3640         andi.l          &0x00ff01ff,USER_FPSR(%a6) # zero all but accured field
3641
3642         fmov.l          &0x0,%fpcr              # zero current control regs
3643         fmov.l          &0x0,%fpsr
3644
3645         bfextu          EXC_EXTWORD(%a6){&0:&6},%d1 # extract upper 6 of cmdreg
3646         cmpi.b          %d1,&0x17               # is op an fmovecr?
3647         beq.w           finex_fmovcr            # yes
3648
3649         lea             FP_SRC(%a6),%a0         # pass: ptr to src op
3650         bsr.l           set_tag_x               # tag the operand type
3651         mov.b           %d0,STAG(%a6)           # maybe NORM,DENORM
3652
3653 # bits four and five of the fp extension word separate the monadic and dyadic
3654 # operations that can pass through fpsp_inex(). remember that fcmp and ftst
3655 # will never take this exception, but fsincos will.
3656         btst            &0x5,1+EXC_CMDREG(%a6)  # is operation monadic or dyadic?
3657         beq.b           finex_extract           # monadic
3658
3659         btst            &0x4,1+EXC_CMDREG(%a6)  # is operation an fsincos?
3660         bne.b           finex_extract           # yes
3661
3662         bfextu          EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
3663         bsr.l           load_fpn2               # load dst into FP_DST
3664
3665         lea             FP_DST(%a6),%a0         # pass: ptr to dst op
3666         bsr.l           set_tag_x               # tag the operand type
3667         cmpi.b          %d0,&UNNORM             # is operand an UNNORM?
3668         bne.b           finex_op2_done          # no
3669         bsr.l           unnorm_fix              # yes; convert to NORM,DENORM,or ZERO
3670 finex_op2_done:
3671         mov.b           %d0,DTAG(%a6)           # save dst optype tag
3672
3673 finex_extract:
3674         clr.l           %d0
3675         mov.b           FPCR_MODE(%a6),%d0      # pass rnd prec/mode
3676
3677         mov.b           1+EXC_CMDREG(%a6),%d1
3678         andi.w          &0x007f,%d1             # extract extension
3679
3680         lea             FP_SRC(%a6),%a0
3681         lea             FP_DST(%a6),%a1
3682
3683         mov.l           (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
3684         jsr             (tbl_unsupp.l,%pc,%d1.l*1)
3685
3686 # the operation has been emulated. the result is in fp0.
3687 finex_save:
3688         bfextu          EXC_CMDREG(%a6){&6:&3},%d0
3689         bsr.l           store_fpreg
3690
3691 finex_exit:
3692         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
3693         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
3694         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3695
3696         frestore        FP_SRC(%a6)
3697
3698         unlk            %a6
3699         bra.l           _real_inex
3700
3701 finex_fmovcr:
3702         clr.l           %d0
3703         mov.b           FPCR_MODE(%a6),%d0      # pass rnd prec,mode
3704         mov.b           1+EXC_CMDREG(%a6),%d1
3705         andi.l          &0x0000007f,%d1         # pass rom offset
3706         bsr.l           smovcr
3707         bra.b           finex_save
3708
3709 ########################################################################
3710
3711 #
3712 # the hardware does not save the default result to memory on enabled
3713 # inexact exceptions. we do this here before passing control to
3714 # the user inexact handler.
3715 #
3716 # byte, word, and long destination format operations can pass
3717 # through here. so can double and single precision.
3718 # although packed opclass three operations can take inexact
3719 # exceptions, they won't pass through here since they are caught
3720 # first by the unsupported data format exception handler. that handler
3721 # sends them directly to _real_inex() if necessary.
3722 #
3723 finex_out:
3724
3725         mov.b           &NORM,STAG(%a6)         # src is a NORM
3726
3727         clr.l           %d0
3728         mov.b           FPCR_MODE(%a6),%d0      # pass rnd prec,mode
3729
3730         andi.l          &0xffff00ff,USER_FPSR(%a6) # zero exception field
3731
3732         lea             FP_SRC(%a6),%a0         # pass ptr to src operand
3733
3734         bsr.l           fout                    # store the default result
3735
3736         bra.b           finex_exit
3737
3738 #########################################################################
3739 # XDEF **************************************************************** #
3740 #       _fpsp_dz(): 060FPSP entry point for FP DZ exception.            #
3741 #                                                                       #
3742 #       This handler should be the first code executed upon taking      #
3743 #       the FP DZ exception in an operating system.                     #
3744 #                                                                       #
3745 # XREF **************************************************************** #
3746 #       _imem_read_long() - read instruction longword from memory       #
3747 #       fix_skewed_ops() - adjust fsave operand                         #
3748 #       _real_dz() - "callout" exit point from FP DZ handler            #
3749 #                                                                       #
3750 # INPUT *************************************************************** #
3751 #       - The system stack contains the FP DZ exception stack.          #
3752 #       - The fsave frame contains the source operand.                  #
3753 #                                                                       #
3754 # OUTPUT ************************************************************** #
3755 #       - The system stack contains the FP DZ exception stack.          #
3756 #       - The fsave frame contains the adjusted source operand.         #
3757 #                                                                       #
3758 # ALGORITHM *********************************************************** #
3759 #       In a system where the DZ exception is enabled, the goal is to   #
3760 # get to the handler specified at _real_dz(). But, on the 060, when the #
3761 # exception is taken, the input operand in the fsave state frame may    #
3762 # be incorrect for some cases and need to be adjusted. So, this package #
3763 # adjusts the operand using fix_skewed_ops() and then branches to       #
3764 # _real_dz().                                                           #
3765 #                                                                       #
3766 #########################################################################
3767
3768         global          _fpsp_dz
3769 _fpsp_dz:
3770
3771         link.w          %a6,&-LOCAL_SIZE        # init stack frame
3772
3773         fsave           FP_SRC(%a6)             # grab the "busy" frame
3774
3775         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3776         fmovm.l         %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
3777         fmovm.x         &0xc0,EXC_FPREGS(%a6)   # save fp0-fp1 on stack
3778
3779 # the FPIAR holds the "current PC" of the faulting instruction
3780         mov.l           USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
3781
3782         mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
3783         addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
3784         bsr.l           _imem_read_long         # fetch the instruction words
3785         mov.l           %d0,EXC_OPWORD(%a6)
3786
3787 ##############################################################################
3788
3789
3790 # here, we simply see if the operand in the fsave frame needs to be "unskewed".
3791 # this would be the case for opclass two operations with a source zero
3792 # in the sgl or dbl format.
3793         lea             FP_SRC(%a6),%a0         # pass: ptr to src op
3794         bsr.l           fix_skewed_ops          # fix src op
3795
3796 fdz_exit:
3797         fmovm.x         EXC_FPREGS(%a6),&0xc0   # restore fp0-fp1
3798         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
3799         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3800
3801         frestore        FP_SRC(%a6)
3802
3803         unlk            %a6
3804         bra.l           _real_dz
3805
3806 #########################################################################
3807 # XDEF **************************************************************** #
3808 #       _fpsp_fline(): 060FPSP entry point for "Line F emulator" exc.   #
3809 #                                                                       #
3810 #       This handler should be the first code executed upon taking the  #
3811 #       "Line F Emulator" exception in an operating system.             #
3812 #                                                                       #
3813 # XREF **************************************************************** #
3814 #       _fpsp_unimp() - handle "FP Unimplemented" exceptions            #
3815 #       _real_fpu_disabled() - handle "FPU disabled" exceptions         #
3816 #       _real_fline() - handle "FLINE" exceptions                       #
3817 #       _imem_read_long() - read instruction longword                   #
3818 #                                                                       #
3819 # INPUT *************************************************************** #
3820 #       - The system stack contains a "Line F Emulator" exception       #
3821 #         stack frame.                                                  #
3822 #                                                                       #
3823 # OUTPUT ************************************************************** #
3824 #       - The system stack is unchanged                                 #
3825 #                                                                       #
3826 # ALGORITHM *********************************************************** #
3827 #       When a "Line F Emulator" exception occurs, there are 3 possible #
3828 # exception types, denoted by the exception stack frame format number:  #
3829 #       (1) FPU unimplemented instruction (6 word stack frame)          #
3830 #       (2) FPU disabled (8 word stack frame)                           #
3831 #       (3) Line F (4 word stack frame)                                 #
3832 #                                                                       #
3833 #       This module determines which and forks the flow off to the      #
3834 # appropriate "callout" (for "disabled" and "Line F") or to the         #
3835 # correct emulation code (for "FPU unimplemented").                     #
3836 #       This code also must check for "fmovecr" instructions w/ a       #
3837 # non-zero <ea> field. These may get flagged as "Line F" but should     #
3838 # really be flagged as "FPU Unimplemented". (This is a "feature" on     #
3839 # the '060.                                                             #
3840 #                                                                       #
3841 #########################################################################
3842
3843         global          _fpsp_fline
3844 _fpsp_fline:
3845
3846 # check to see if this exception is a "FP Unimplemented Instruction"
3847 # exception. if so, branch directly to that handler's entry point.
3848         cmpi.w          0x6(%sp),&0x202c
3849         beq.l           _fpsp_unimp
3850
3851 # check to see if the FPU is disabled. if so, jump to the OS entry
3852 # point for that condition.
3853         cmpi.w          0x6(%sp),&0x402c
3854         beq.l           _real_fpu_disabled
3855
3856 # the exception was an "F-Line Illegal" exception. we check to see
3857 # if the F-Line instruction is an "fmovecr" w/ a non-zero <ea>. if
3858 # so, convert the F-Line exception stack frame to an FP Unimplemented
3859 # Instruction exception stack frame else branch to the OS entry
3860 # point for the F-Line exception handler.
3861         link.w          %a6,&-LOCAL_SIZE        # init stack frame
3862
3863         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3864
3865         mov.l           EXC_PC(%a6),EXC_EXTWPTR(%a6)
3866         mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
3867         addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
3868         bsr.l           _imem_read_long         # fetch instruction words
3869
3870         bfextu          %d0{&0:&10},%d1         # is it an fmovecr?
3871         cmpi.w          %d1,&0x03c8
3872         bne.b           fline_fline             # no
3873
3874         bfextu          %d0{&16:&6},%d1         # is it an fmovecr?
3875         cmpi.b          %d1,&0x17
3876         bne.b           fline_fline             # no
3877
3878 # it's an fmovecr w/ a non-zero <ea> that has entered through
3879 # the F-Line Illegal exception.
3880 # so, we need to convert the F-Line exception stack frame into an
3881 # FP Unimplemented Instruction stack frame and jump to that entry
3882 # point.
3883 #
3884 # but, if the FPU is disabled, then we need to jump to the FPU diabled
3885 # entry point.
3886         movc            %pcr,%d0
3887         btst            &0x1,%d0
3888         beq.b           fline_fmovcr
3889
3890         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3891
3892         unlk            %a6
3893
3894         sub.l           &0x8,%sp                # make room for "Next PC", <ea>
3895         mov.w           0x8(%sp),(%sp)
3896         mov.l           0xa(%sp),0x2(%sp)       # move "Current PC"
3897         mov.w           &0x402c,0x6(%sp)
3898         mov.l           0x2(%sp),0xc(%sp)
3899         addq.l          &0x4,0x2(%sp)           # set "Next PC"
3900
3901         bra.l           _real_fpu_disabled
3902
3903 fline_fmovcr:
3904         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3905
3906         unlk            %a6
3907
3908         fmov.l          0x2(%sp),%fpiar         # set current PC
3909         addq.l          &0x4,0x2(%sp)           # set Next PC
3910
3911         mov.l           (%sp),-(%sp)
3912         mov.l           0x8(%sp),0x4(%sp)
3913         mov.b           &0x20,0x6(%sp)
3914
3915         bra.l           _fpsp_unimp
3916
3917 fline_fline:
3918         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3919
3920         unlk            %a6
3921
3922         bra.l           _real_fline
3923
3924 #########################################################################
3925 # XDEF **************************************************************** #
3926 #       _fpsp_unimp(): 060FPSP entry point for FP "Unimplemented        #
3927 #                      Instruction" exception.                          #
3928 #                                                                       #
3929 #       This handler should be the first code executed upon taking the  #
3930 #       FP Unimplemented Instruction exception in an operating system.  #
3931 #                                                                       #
3932 # XREF **************************************************************** #
3933 #       _imem_read_{word,long}() - read instruction word/longword       #
3934 #       load_fop() - load src/dst ops from memory and/or FP regfile     #
3935 #       store_fpreg() - store opclass 0 or 2 result to FP regfile       #
3936 #       tbl_trans - addr of table of emulation routines for trnscndls   #
3937 #       _real_access() - "callout" for access error exception           #
3938 #       _fpsp_done() - "callout" for exit; work all done                #
3939 #       _real_trace() - "callout" for Trace enabled exception           #
3940 #       smovcr() - emulate "fmovecr" instruction                        #
3941 #       funimp_skew() - adjust fsave src ops to "incorrect" value       #
3942 #       _ftrapcc() - emulate an "ftrapcc" instruction                   #
3943 #       _fdbcc() - emulate an "fdbcc" instruction                       #
3944 #       _fscc() - emulate an "fscc" instruction                         #
3945 #       _real_trap() - "callout" for Trap exception                     #
3946 #       _real_bsun() - "callout" for enabled Bsun exception             #
3947 #                                                                       #
3948 # INPUT *************************************************************** #
3949 #       - The system stack contains the "Unimplemented Instr" stk frame #
3950 #                                                                       #
3951 # OUTPUT ************************************************************** #
3952 #       If access error:                                                #
3953 #       - The system stack is changed to an access error stack frame    #
3954 #       If Trace exception enabled:                                     #
3955 #       - The system stack is changed to a Trace exception stack frame  #
3956 #       Else: (normal case)                                             #
3957 #       - Correct result has been stored as appropriate                 #
3958 #                                                                       #
3959 # ALGORITHM *********************************************************** #
3960 #       There are two main cases of instructions that may enter here to #
3961 # be emulated: (1) the FPgen instructions, most of which were also      #
3962 # unimplemented on the 040, and (2) "ftrapcc", "fscc", and "fdbcc".     #
3963 #       For the first set, this handler calls the routine load_fop()    #
3964 # to load the source and destination (for dyadic) operands to be used   #
3965 # for instruction emulation. The correct emulation routine is then      #
3966 # chosen by decoding the instruction type and indexing into an          #
3967 # emulation subroutine index table. After emulation returns, this       #
3968 # handler checks to see if an exception should occur as a result of the #
3969 # FP instruction emulation. If so, then an FP exception of the correct  #
3970 # type is inserted into the FPU state frame using the "frestore"        #
3971 # instruction before exiting through _fpsp_done(). In either the        #
3972 # exceptional or non-exceptional cases, we must check to see if the     #
3973 # Trace exception is enabled. If so, then we must create a Trace        #
3974 # exception frame from the current exception frame and exit through     #
3975 # _real_trace().                                                        #
3976 #       For "fdbcc", "ftrapcc", and "fscc", the emulation subroutines   #
3977 # _fdbcc(), _ftrapcc(), and _fscc() respectively are used. All three    #
3978 # may flag that a BSUN exception should be taken. If so, then the       #
3979 # current exception stack frame is converted into a BSUN exception      #
3980 # stack frame and an exit is made through _real_bsun(). If the          #
3981 # instruction was "ftrapcc" and a Trap exception should result, a Trap  #
3982 # exception stack frame is created from the current frame and an exit   #
3983 # is made through _real_trap(). If a Trace exception is pending, then   #
3984 # a Trace exception frame is created from the current frame and a jump  #
3985 # is made to _real_trace(). Finally, if none of these conditions exist, #
3986 # then the handler exits though the callout _fpsp_done().               #
3987 #                                                                       #
3988 #       In any of the above scenarios, if a _mem_read() or _mem_write() #
3989 # "callout" returns a failing value, then an access error stack frame   #
3990 # is created from the current stack frame and an exit is made through   #
3991 # _real_access().                                                       #
3992 #                                                                       #
3993 #########################################################################
3994
3995 #
3996 # FP UNIMPLEMENTED INSTRUCTION STACK FRAME:
3997 #
3998 #       *****************
3999 #       *               * => <ea> of fp unimp instr.
4000 #       -      EA       -
4001 #       *               *
4002 #       *****************
4003 #       * 0x2 *  0x02c  * => frame format and vector offset(vector #11)
4004 #       *****************
4005 #       *               *
4006 #       -    Next PC    - => PC of instr to execute after exc handling
4007 #       *               *
4008 #       *****************
4009 #       *      SR       * => SR at the time the exception was taken
4010 #       *****************
4011 #
4012 # Note: the !NULL bit does not get set in the fsave frame when the
4013 # machine encounters an fp unimp exception. Therefore, it must be set
4014 # before leaving this handler.
4015 #
4016         global          _fpsp_unimp
4017 _fpsp_unimp:
4018
4019         link.w          %a6,&-LOCAL_SIZE        # init stack frame
4020
4021         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4022         fmovm.l         %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
4023         fmovm.x         &0xc0,EXC_FPREGS(%a6)   # save fp0-fp1
4024
4025         btst            &0x5,EXC_SR(%a6)        # user mode exception?
4026         bne.b           funimp_s                # no; supervisor mode
4027
4028 # save the value of the user stack pointer onto the stack frame
4029 funimp_u:
4030         mov.l           %usp,%a0                # fetch user stack pointer
4031         mov.l           %a0,EXC_A7(%a6)         # store in stack frame
4032         bra.b           funimp_cont
4033
4034 # store the value of the supervisor stack pointer BEFORE the exc occurred.
4035 # old_sp is address just above stacked effective address.
4036 funimp_s:
4037         lea             4+EXC_EA(%a6),%a0       # load old a7'
4038         mov.l           %a0,EXC_A7(%a6)         # store a7'
4039         mov.l           %a0,OLD_A7(%a6)         # make a copy
4040
4041 funimp_cont:
4042
4043 # the FPIAR holds the "current PC" of the faulting instruction.
4044         mov.l           USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
4045
4046         mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
4047         addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
4048         bsr.l           _imem_read_long         # fetch the instruction words
4049         mov.l           %d0,EXC_OPWORD(%a6)
4050
4051 ############################################################################
4052
4053         fmov.l          &0x0,%fpcr              # clear FPCR
4054         fmov.l          &0x0,%fpsr              # clear FPSR
4055
4056         clr.b           SPCOND_FLG(%a6)         # clear "special case" flag
4057
4058 # Divide the fp instructions into 8 types based on the TYPE field in
4059 # bits 6-8 of the opword(classes 6,7 are undefined).
4060 # (for the '060, only two types  can take this exception)
4061 #       bftst           %d0{&7:&3}              # test TYPE
4062         btst            &22,%d0                 # type 0 or 1 ?
4063         bne.w           funimp_misc             # type 1
4064
4065 #########################################
4066 # TYPE == 0: General instructions       #
4067 #########################################
4068 funimp_gen:
4069
4070         clr.b           STORE_FLG(%a6)          # clear "store result" flag
4071
4072 # clear the ccode byte and exception status byte
4073         andi.l          &0x00ff00ff,USER_FPSR(%a6)
4074
4075         bfextu          %d0{&16:&6},%d1         # extract upper 6 of cmdreg
4076         cmpi.b          %d1,&0x17               # is op an fmovecr?
4077         beq.w           funimp_fmovcr           # yes
4078
4079 funimp_gen_op:
4080         bsr.l           _load_fop               # load
4081
4082         clr.l           %d0
4083         mov.b           FPCR_MODE(%a6),%d0      # fetch rnd mode
4084
4085         mov.b           1+EXC_CMDREG(%a6),%d1
4086         andi.w          &0x003f,%d1             # extract extension bits
4087         lsl.w           &0x3,%d1                # shift right 3 bits
4088         or.b            STAG(%a6),%d1           # insert src optag bits
4089
4090         lea             FP_DST(%a6),%a1         # pass dst ptr in a1
4091         lea             FP_SRC(%a6),%a0         # pass src ptr in a0
4092
4093         mov.w           (tbl_trans.w,%pc,%d1.w*2),%d1
4094         jsr             (tbl_trans.w,%pc,%d1.w*1) # emulate
4095
4096 funimp_fsave:
4097         mov.b           FPCR_ENABLE(%a6),%d0    # fetch exceptions enabled
4098         bne.w           funimp_ena              # some are enabled
4099
4100 funimp_store:
4101         bfextu          EXC_CMDREG(%a6){&6:&3},%d0 # fetch Dn
4102         bsr.l           store_fpreg             # store result to fp regfile
4103
4104 funimp_gen_exit:
4105         fmovm.x         EXC_FP0(%a6),&0xc0      # restore fp0-fp1
4106         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
4107         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4108
4109 funimp_gen_exit_cmp:
4110         cmpi.b          SPCOND_FLG(%a6),&mia7_flg # was the ea mode (sp)+ ?
4111         beq.b           funimp_gen_exit_a7      # yes
4112
4113         cmpi.b          SPCOND_FLG(%a6),&mda7_flg # was the ea mode -(sp) ?
4114         beq.b           funimp_gen_exit_a7      # yes
4115
4116 funimp_gen_exit_cont:
4117         unlk            %a6
4118
4119 funimp_gen_exit_cont2:
4120         btst            &0x7,(%sp)              # is trace on?
4121         beq.l           _fpsp_done              # no
4122
4123 # this catches a problem with the case where an exception will be re-inserted
4124 # into the machine. the frestore has already been executed...so, the fmov.l
4125 # alone of the control register would trigger an unwanted exception.
4126 # until I feel like fixing this, we'll sidestep the exception.
4127         fsave           -(%sp)
4128         fmov.l          %fpiar,0x14(%sp)        # "Current PC" is in FPIAR
4129         frestore        (%sp)+
4130         mov.w           &0x2024,0x6(%sp)        # stk fmt = 0x2; voff = 0x24
4131         bra.l           _real_trace
4132
4133 funimp_gen_exit_a7:
4134         btst            &0x5,EXC_SR(%a6)        # supervisor or user mode?
4135         bne.b           funimp_gen_exit_a7_s    # supervisor
4136
4137         mov.l           %a0,-(%sp)
4138         mov.l           EXC_A7(%a6),%a0
4139         mov.l           %a0,%usp
4140         mov.l           (%sp)+,%a0
4141         bra.b           funimp_gen_exit_cont
4142
4143 # if the instruction was executed from supervisor mode and the addressing
4144 # mode was (a7)+, then the stack frame for the rte must be shifted "up"
4145 # "n" bytes where "n" is the size of the src operand type.
4146 # f<op>.{b,w,l,s,d,x,p}
4147 funimp_gen_exit_a7_s:
4148         mov.l           %d0,-(%sp)              # save d0
4149         mov.l           EXC_A7(%a6),%d0         # load new a7'
4150         sub.l           OLD_A7(%a6),%d0         # subtract old a7'
4151         mov.l           0x2+EXC_PC(%a6),(0x2+EXC_PC,%a6,%d0) # shift stack frame
4152         mov.l           EXC_SR(%a6),(EXC_SR,%a6,%d0) # shift stack frame
4153         mov.w           %d0,EXC_SR(%a6)         # store incr number
4154         mov.l           (%sp)+,%d0              # restore d0
4155
4156         unlk            %a6
4157
4158         add.w           (%sp),%sp               # stack frame shifted
4159         bra.b           funimp_gen_exit_cont2
4160
4161 ######################
4162 # fmovecr.x #ccc,fpn #
4163 ######################
4164 funimp_fmovcr:
4165         clr.l           %d0
4166         mov.b           FPCR_MODE(%a6),%d0
4167         mov.b           1+EXC_CMDREG(%a6),%d1
4168         andi.l          &0x0000007f,%d1         # pass rom offset in d1
4169         bsr.l           smovcr
4170         bra.w           funimp_fsave
4171
4172 #########################################################################
4173
4174 #
4175 # the user has enabled some exceptions. we figure not to see this too
4176 # often so that's why it gets lower priority.
4177 #
4178 funimp_ena:
4179
4180 # was an exception set that was also enabled?
4181         and.b           FPSR_EXCEPT(%a6),%d0    # keep only ones enabled and set
4182         bfffo           %d0{&24:&8},%d0         # find highest priority exception
4183         bne.b           funimp_exc              # at least one was set
4184
4185 # no exception that was enabled was set BUT if we got an exact overflow
4186 # and overflow wasn't enabled but inexact was (yech!) then this is
4187 # an inexact exception; otherwise, return to normal non-exception flow.
4188         btst            &ovfl_bit,FPSR_EXCEPT(%a6) # did overflow occur?
4189         beq.w           funimp_store            # no; return to normal flow
4190
4191 # the overflow w/ exact result happened but was inexact set in the FPCR?
4192 funimp_ovfl:
4193         btst            &inex2_bit,FPCR_ENABLE(%a6) # is inexact enabled?
4194         beq.w           funimp_store            # no; return to normal flow
4195         bra.b           funimp_exc_ovfl         # yes
4196
4197 # some exception happened that was actually enabled.
4198 # we'll insert this new exception into the FPU and then return.
4199 funimp_exc:
4200         subi.l          &24,%d0                 # fix offset to be 0-8
4201         cmpi.b          %d0,&0x6                # is exception INEX?
4202         bne.b           funimp_exc_force        # no
4203
4204 # the enabled exception was inexact. so, if it occurs with an overflow
4205 # or underflow that was disabled, then we have to force an overflow or
4206 # underflow frame. the eventual overflow or underflow handler will see that
4207 # it's actually an inexact and act appropriately. this is the only easy
4208 # way to have the EXOP available for the enabled inexact handler when
4209 # a disabled overflow or underflow has also happened.
4210         btst            &ovfl_bit,FPSR_EXCEPT(%a6) # did overflow occur?
4211         bne.b           funimp_exc_ovfl         # yes
4212         btst            &unfl_bit,FPSR_EXCEPT(%a6) # did underflow occur?
4213         bne.b           funimp_exc_unfl         # yes
4214
4215 # force the fsave exception status bits to signal an exception of the
4216 # appropriate type. don't forget to "skew" the source operand in case we
4217 # "unskewed" the one the hardware initially gave us.
4218 funimp_exc_force:
4219         mov.l           %d0,-(%sp)              # save d0
4220         bsr.l           funimp_skew             # check for special case
4221         mov.l           (%sp)+,%d0              # restore d0
4222         mov.w           (tbl_funimp_except.b,%pc,%d0.w*2),2+FP_SRC(%a6)
4223         bra.b           funimp_gen_exit2        # exit with frestore
4224
4225 tbl_funimp_except:
4226         short           0xe002, 0xe006, 0xe004, 0xe005
4227         short           0xe003, 0xe002, 0xe001, 0xe001
4228
4229 # insert an overflow frame
4230 funimp_exc_ovfl:
4231         bsr.l           funimp_skew             # check for special case
4232         mov.w           &0xe005,2+FP_SRC(%a6)
4233         bra.b           funimp_gen_exit2
4234
4235 # insert an underflow frame
4236 funimp_exc_unfl:
4237         bsr.l           funimp_skew             # check for special case
4238         mov.w           &0xe003,2+FP_SRC(%a6)
4239
4240 # this is the general exit point for an enabled exception that will be
4241 # restored into the machine for the instruction just emulated.
4242 funimp_gen_exit2:
4243         fmovm.x         EXC_FP0(%a6),&0xc0      # restore fp0-fp1
4244         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
4245         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4246
4247         frestore        FP_SRC(%a6)             # insert exceptional status
4248
4249         bra.w           funimp_gen_exit_cmp
4250
4251 ############################################################################
4252
4253 #
4254 # TYPE == 1: FDB<cc>, FS<cc>, FTRAP<cc>
4255 #
4256 # These instructions were implemented on the '881/2 and '040 in hardware but
4257 # are emulated in software on the '060.
4258 #
4259 funimp_misc:
4260         bfextu          %d0{&10:&3},%d1         # extract mode field
4261         cmpi.b          %d1,&0x1                # is it an fdb<cc>?
4262         beq.w           funimp_fdbcc            # yes
4263         cmpi.b          %d1,&0x7                # is it an fs<cc>?
4264         bne.w           funimp_fscc             # yes
4265         bfextu          %d0{&13:&3},%d1
4266         cmpi.b          %d1,&0x2                # is it an fs<cc>?
4267         blt.w           funimp_fscc             # yes
4268
4269 #########################
4270 # ftrap<cc>             #
4271 # ftrap<cc>.w #<data>   #
4272 # ftrap<cc>.l #<data>   #
4273 #########################
4274 funimp_ftrapcc:
4275
4276         bsr.l           _ftrapcc                # FTRAP<cc>()
4277
4278         cmpi.b          SPCOND_FLG(%a6),&fbsun_flg # is enabled bsun occurring?
4279         beq.w           funimp_bsun             # yes
4280
4281         cmpi.b          SPCOND_FLG(%a6),&ftrapcc_flg # should a trap occur?
4282         bne.w           funimp_done             # no
4283
4284 #        FP UNIMP FRAME            TRAP  FRAME
4285 #       *****************       *****************
4286 #       **    <EA>     **       **  Current PC **
4287 #       *****************       *****************
4288 #       * 0x2 *  0x02c  *       * 0x2 *  0x01c  *
4289 #       *****************       *****************
4290 #       **   Next PC   **       **   Next PC   **
4291 #       *****************       *****************
4292 #       *      SR       *       *      SR       *
4293 #       *****************       *****************
4294 #           (6 words)               (6 words)
4295 #
4296 # the ftrapcc instruction should take a trap. so, here we must create a
4297 # trap stack frame from an unimplemented fp instruction stack frame and
4298 # jump to the user supplied entry point for the trap exception
4299 funimp_ftrapcc_tp:
4300         mov.l           USER_FPIAR(%a6),EXC_EA(%a6) # Address = Current PC
4301         mov.w           &0x201c,EXC_VOFF(%a6)   # Vector Offset = 0x01c
4302
4303         fmovm.x         EXC_FP0(%a6),&0xc0      # restore fp0-fp1
4304         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
4305         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4306
4307         unlk            %a6
4308         bra.l           _real_trap
4309
4310 #########################
4311 # fdb<cc> Dn,<label>    #
4312 #########################
4313 funimp_fdbcc:
4314
4315         mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
4316         addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
4317         bsr.l           _imem_read_word         # read displacement
4318
4319         tst.l           %d1                     # did ifetch fail?
4320         bne.w           funimp_iacc             # yes
4321
4322         ext.l           %d0                     # sign extend displacement
4323
4324         bsr.l           _fdbcc                  # FDB<cc>()
4325
4326         cmpi.b          SPCOND_FLG(%a6),&fbsun_flg # is enabled bsun occurring?
4327         beq.w           funimp_bsun
4328
4329         bra.w           funimp_done             # branch to finish
4330
4331 #################
4332 # fs<cc>.b <ea> #
4333 #################
4334 funimp_fscc:
4335
4336         bsr.l           _fscc                   # FS<cc>()
4337
4338 # I am assuming here that an "fs<cc>.b -(An)" or "fs<cc>.b (An)+" instruction
4339 # does not need to update "An" before taking a bsun exception.
4340         cmpi.b          SPCOND_FLG(%a6),&fbsun_flg # is enabled bsun occurring?
4341         beq.w           funimp_bsun
4342
4343         btst            &0x5,EXC_SR(%a6)        # yes; is it a user mode exception?
4344         bne.b           funimp_fscc_s           # no
4345
4346 funimp_fscc_u:
4347         mov.l           EXC_A7(%a6),%a0         # yes; set new USP
4348         mov.l           %a0,%usp
4349         bra.w           funimp_done             # branch to finish
4350
4351 # remember, I'm assuming that post-increment is bogus...(it IS!!!)
4352 # so, the least significant WORD of the stacked effective address got
4353 # overwritten by the "fs<cc> -(An)". We must shift the stack frame "down"
4354 # so that the rte will work correctly without destroying the result.
4355 # even though the operation size is byte, the stack ptr is decr by 2.
4356 #
4357 # remember, also, this instruction may be traced.
4358 funimp_fscc_s:
4359         cmpi.b          SPCOND_FLG(%a6),&mda7_flg # was a7 modified?
4360         bne.w           funimp_done             # no
4361
4362         fmovm.x         EXC_FP0(%a6),&0xc0      # restore fp0-fp1
4363         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
4364         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4365
4366         unlk            %a6
4367
4368         btst            &0x7,(%sp)              # is trace enabled?
4369         bne.b           funimp_fscc_s_trace     # yes
4370
4371         subq.l          &0x2,%sp
4372         mov.l           0x2(%sp),(%sp)          # shift SR,hi(PC) "down"
4373         mov.l           0x6(%sp),0x4(%sp)       # shift lo(PC),voff "down"
4374         bra.l           _fpsp_done
4375
4376 funimp_fscc_s_trace:
4377         subq.l          &0x2,%sp
4378         mov.l           0x2(%sp),(%sp)          # shift SR,hi(PC) "down"
4379         mov.w           0x6(%sp),0x4(%sp)       # shift lo(PC)
4380         mov.w           &0x2024,0x6(%sp)        # fmt/voff = $2024
4381         fmov.l          %fpiar,0x8(%sp)         # insert "current PC"
4382
4383         bra.l           _real_trace
4384
4385 #
4386 # The ftrap<cc>, fs<cc>, or fdb<cc> is to take an enabled bsun. we must convert
4387 # the fp unimplemented instruction exception stack frame into a bsun stack frame,
4388 # restore a bsun exception into the machine, and branch to the user
4389 # supplied bsun hook.
4390 #
4391 #        FP UNIMP FRAME            BSUN FRAME
4392 #       *****************       *****************
4393 #       **    <EA>     **       * 0x0 * 0x0c0   *
4394 #       *****************       *****************
4395 #       * 0x2 *  0x02c  *       ** Current PC  **
4396 #       *****************       *****************
4397 #       **   Next PC   **       *      SR       *
4398 #       *****************       *****************
4399 #       *      SR       *           (4 words)
4400 #       *****************
4401 #           (6 words)
4402 #
4403 funimp_bsun:
4404         mov.w           &0x00c0,2+EXC_EA(%a6)   # Fmt = 0x0; Vector Offset = 0x0c0
4405         mov.l           USER_FPIAR(%a6),EXC_VOFF(%a6) # PC = Current PC
4406         mov.w           EXC_SR(%a6),2+EXC_PC(%a6) # shift SR "up"
4407
4408         mov.w           &0xe000,2+FP_SRC(%a6)   # bsun exception enabled
4409
4410         fmovm.x         EXC_FP0(%a6),&0xc0      # restore fp0-fp1
4411         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
4412         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4413
4414         frestore        FP_SRC(%a6)             # restore bsun exception
4415
4416         unlk            %a6
4417
4418         addq.l          &0x4,%sp                # erase sludge
4419
4420         bra.l           _real_bsun              # branch to user bsun hook
4421
4422 #
4423 # all ftrapcc/fscc/fdbcc processing has been completed. unwind the stack frame
4424 # and return.
4425 #
4426 # as usual, we have to check for trace mode being on here. since instructions
4427 # modifying the supervisor stack frame don't pass through here, this is a
4428 # relatively easy task.
4429 #
4430 funimp_done:
4431         fmovm.x         EXC_FP0(%a6),&0xc0      # restore fp0-fp1
4432         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
4433         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4434
4435         unlk            %a6
4436
4437         btst            &0x7,(%sp)              # is trace enabled?
4438         bne.b           funimp_trace            # yes
4439
4440         bra.l           _fpsp_done
4441
4442 #        FP UNIMP FRAME           TRACE  FRAME
4443 #       *****************       *****************
4444 #       **    <EA>     **       **  Current PC **
4445 #       *****************       *****************
4446 #       * 0x2 *  0x02c  *       * 0x2 *  0x024  *
4447 #       *****************       *****************
4448 #       **   Next PC   **       **   Next PC   **
4449 #       *****************       *****************
4450 #       *      SR       *       *      SR       *
4451 #       *****************       *****************
4452 #           (6 words)               (6 words)
4453 #
4454 # the fscc instruction should take a trace trap. so, here we must create a
4455 # trace stack frame from an unimplemented fp instruction stack frame and
4456 # jump to the user supplied entry point for the trace exception
4457 funimp_trace:
4458         fmov.l          %fpiar,0x8(%sp)         # current PC is in fpiar
4459         mov.b           &0x24,0x7(%sp)          # vector offset = 0x024
4460
4461         bra.l           _real_trace
4462
4463 ################################################################
4464
4465         global          tbl_trans
4466         swbeg           &0x1c0
4467 tbl_trans:
4468         short           tbl_trans - tbl_trans   # $00-0 fmovecr all
4469         short           tbl_trans - tbl_trans   # $00-1 fmovecr all
4470         short           tbl_trans - tbl_trans   # $00-2 fmovecr all
4471         short           tbl_trans - tbl_trans   # $00-3 fmovecr all
4472         short           tbl_trans - tbl_trans   # $00-4 fmovecr all
4473         short           tbl_trans - tbl_trans   # $00-5 fmovecr all
4474         short           tbl_trans - tbl_trans   # $00-6 fmovecr all
4475         short           tbl_trans - tbl_trans   # $00-7 fmovecr all
4476
4477         short           tbl_trans - tbl_trans   # $01-0 fint norm
4478         short           tbl_trans - tbl_trans   # $01-1 fint zero
4479         short           tbl_trans - tbl_trans   # $01-2 fint inf
4480         short           tbl_trans - tbl_trans   # $01-3 fint qnan
4481         short           tbl_trans - tbl_trans   # $01-5 fint denorm
4482         short           tbl_trans - tbl_trans   # $01-4 fint snan
4483         short           tbl_trans - tbl_trans   # $01-6 fint unnorm
4484         short           tbl_trans - tbl_trans   # $01-7 ERROR
4485
4486         short           ssinh    - tbl_trans    # $02-0 fsinh norm
4487         short           src_zero - tbl_trans    # $02-1 fsinh zero
4488         short           src_inf  - tbl_trans    # $02-2 fsinh inf
4489         short           src_qnan - tbl_trans    # $02-3 fsinh qnan
4490         short           ssinhd   - tbl_trans    # $02-5 fsinh denorm
4491         short           src_snan - tbl_trans    # $02-4 fsinh snan
4492         short           tbl_trans - tbl_trans   # $02-6 fsinh unnorm
4493         short           tbl_trans - tbl_trans   # $02-7 ERROR
4494
4495         short           tbl_trans - tbl_trans   # $03-0 fintrz norm
4496         short           tbl_trans - tbl_trans   # $03-1 fintrz zero
4497         short           tbl_trans - tbl_trans   # $03-2 fintrz inf
4498         short           tbl_trans - tbl_trans   # $03-3 fintrz qnan
4499         short           tbl_trans - tbl_trans   # $03-5 fintrz denorm
4500         short           tbl_trans - tbl_trans   # $03-4 fintrz snan
4501         short           tbl_trans - tbl_trans   # $03-6 fintrz unnorm
4502         short           tbl_trans - tbl_trans   # $03-7 ERROR
4503
4504         short           tbl_trans - tbl_trans   # $04-0 fsqrt norm
4505         short           tbl_trans - tbl_trans   # $04-1 fsqrt zero
4506         short           tbl_trans - tbl_trans   # $04-2 fsqrt inf
4507         short           tbl_trans - tbl_trans   # $04-3 fsqrt qnan
4508         short           tbl_trans - tbl_trans   # $04-5 fsqrt denorm
4509         short           tbl_trans - tbl_trans   # $04-4 fsqrt snan
4510         short           tbl_trans - tbl_trans   # $04-6 fsqrt unnorm
4511         short           tbl_trans - tbl_trans   # $04-7 ERROR
4512
4513         short           tbl_trans - tbl_trans   # $05-0 ERROR
4514         short           tbl_trans - tbl_trans   # $05-1 ERROR
4515         short           tbl_trans - tbl_trans   # $05-2 ERROR
4516         short           tbl_trans - tbl_trans   # $05-3 ERROR
4517         short           tbl_trans - tbl_trans   # $05-4 ERROR
4518         short           tbl_trans - tbl_trans   # $05-5 ERROR
4519         short           tbl_trans - tbl_trans   # $05-6 ERROR
4520         short           tbl_trans - tbl_trans   # $05-7 ERROR
4521
4522         short           slognp1  - tbl_trans    # $06-0 flognp1 norm
4523         short           src_zero - tbl_trans    # $06-1 flognp1 zero
4524         short           sopr_inf - tbl_trans    # $06-2 flognp1 inf
4525         short           src_qnan - tbl_trans    # $06-3 flognp1 qnan
4526         short           slognp1d - tbl_trans    # $06-5 flognp1 denorm
4527         short           src_snan - tbl_trans    # $06-4 flognp1 snan
4528         short           tbl_trans - tbl_trans   # $06-6 flognp1 unnorm
4529         short           tbl_trans - tbl_trans   # $06-7 ERROR
4530
4531         short           tbl_trans - tbl_trans   # $07-0 ERROR
4532         short           tbl_trans - tbl_trans   # $07-1 ERROR
4533         short           tbl_trans - tbl_trans   # $07-2 ERROR
4534         short           tbl_trans - tbl_trans   # $07-3 ERROR
4535         short           tbl_trans - tbl_trans   # $07-4 ERROR
4536         short           tbl_trans - tbl_trans   # $07-5 ERROR
4537         short           tbl_trans - tbl_trans   # $07-6 ERROR
4538         short           tbl_trans - tbl_trans   # $07-7 ERROR
4539
4540         short           setoxm1  - tbl_trans    # $08-0 fetoxm1 norm
4541         short           src_zero - tbl_trans    # $08-1 fetoxm1 zero
4542         short           setoxm1i - tbl_trans    # $08-2 fetoxm1 inf
4543         short           src_qnan - tbl_trans    # $08-3 fetoxm1 qnan
4544         short           setoxm1d - tbl_trans    # $08-5 fetoxm1 denorm
4545         short           src_snan - tbl_trans    # $08-4 fetoxm1 snan
4546         short           tbl_trans - tbl_trans   # $08-6 fetoxm1 unnorm
4547         short           tbl_trans - tbl_trans   # $08-7 ERROR
4548
4549         short           stanh    - tbl_trans    # $09-0 ftanh norm
4550         short           src_zero - tbl_trans    # $09-1 ftanh zero
4551         short           src_one  - tbl_trans    # $09-2 ftanh inf
4552         short           src_qnan - tbl_trans    # $09-3 ftanh qnan
4553         short           stanhd   - tbl_trans    # $09-5 ftanh denorm
4554         short           src_snan - tbl_trans    # $09-4 ftanh snan
4555         short           tbl_trans - tbl_trans   # $09-6 ftanh unnorm
4556         short           tbl_trans - tbl_trans   # $09-7 ERROR
4557
4558         short           satan    - tbl_trans    # $0a-0 fatan norm
4559         short           src_zero - tbl_trans    # $0a-1 fatan zero
4560         short           spi_2    - tbl_trans    # $0a-2 fatan inf
4561         short           src_qnan - tbl_trans    # $0a-3 fatan qnan
4562         short           satand   - tbl_trans    # $0a-5 fatan denorm
4563         short           src_snan - tbl_trans    # $0a-4 fatan snan
4564         short           tbl_trans - tbl_trans   # $0a-6 fatan unnorm
4565         short           tbl_trans - tbl_trans   # $0a-7 ERROR
4566
4567         short           tbl_trans - tbl_trans   # $0b-0 ERROR
4568         short           tbl_trans - tbl_trans   # $0b-1 ERROR
4569         short           tbl_trans - tbl_trans   # $0b-2 ERROR
4570         short           tbl_trans - tbl_trans   # $0b-3 ERROR
4571         short           tbl_trans - tbl_trans   # $0b-4 ERROR
4572         short           tbl_trans - tbl_trans   # $0b-5 ERROR
4573         short           tbl_trans - tbl_trans   # $0b-6 ERROR
4574         short           tbl_trans - tbl_trans   # $0b-7 ERROR
4575
4576         short           sasin    - tbl_trans    # $0c-0 fasin norm
4577         short           src_zero - tbl_trans    # $0c-1 fasin zero
4578         short           t_operr  - tbl_trans    # $0c-2 fasin inf
4579         short           src_qnan - tbl_trans    # $0c-3 fasin qnan
4580         short           sasind   - tbl_trans    # $0c-5 fasin denorm
4581         short           src_snan - tbl_trans    # $0c-4 fasin snan
4582         short           tbl_trans - tbl_trans   # $0c-6 fasin unnorm
4583         short           tbl_trans - tbl_trans   # $0c-7 ERROR
4584
4585         short           satanh   - tbl_trans    # $0d-0 fatanh norm
4586         short           src_zero - tbl_trans    # $0d-1 fatanh zero
4587         short           t_operr  - tbl_trans    # $0d-2 fatanh inf
4588         short           src_qnan - tbl_trans    # $0d-3 fatanh qnan
4589         short           satanhd  - tbl_trans    # $0d-5 fatanh denorm
4590         short           src_snan - tbl_trans    # $0d-4 fatanh snan
4591         short           tbl_trans - tbl_trans   # $0d-6 fatanh unnorm
4592         short           tbl_trans - tbl_trans   # $0d-7 ERROR
4593
4594         short           ssin     - tbl_trans    # $0e-0 fsin norm
4595         short           src_zero - tbl_trans    # $0e-1 fsin zero
4596         short           t_operr  - tbl_trans    # $0e-2 fsin inf
4597         short           src_qnan - tbl_trans    # $0e-3 fsin qnan
4598         short           ssind    - tbl_trans    # $0e-5 fsin denorm
4599         short           src_snan - tbl_trans    # $0e-4 fsin snan
4600         short           tbl_trans - tbl_trans   # $0e-6 fsin unnorm
4601         short           tbl_trans - tbl_trans   # $0e-7 ERROR
4602
4603         short           stan     - tbl_trans    # $0f-0 ftan norm
4604         short           src_zero - tbl_trans    # $0f-1 ftan zero
4605         short           t_operr  - tbl_trans    # $0f-2 ftan inf
4606         short           src_qnan - tbl_trans    # $0f-3 ftan qnan
4607         short           stand    - tbl_trans    # $0f-5 ftan denorm
4608         short           src_snan - tbl_trans    # $0f-4 ftan snan
4609         short           tbl_trans - tbl_trans   # $0f-6 ftan unnorm
4610         short           tbl_trans - tbl_trans   # $0f-7 ERROR
4611
4612         short           setox    - tbl_trans    # $10-0 fetox norm
4613         short           ld_pone  - tbl_trans    # $10-1 fetox zero
4614         short           szr_inf  - tbl_trans    # $10-2 fetox inf
4615         short           src_qnan - tbl_trans    # $10-3 fetox qnan
4616         short           setoxd   - tbl_trans    # $10-5 fetox denorm
4617         short           src_snan - tbl_trans    # $10-4 fetox snan
4618         short           tbl_trans - tbl_trans   # $10-6 fetox unnorm
4619         short           tbl_trans - tbl_trans   # $10-7 ERROR
4620
4621         short           stwotox  - tbl_trans    # $11-0 ftwotox norm
4622         short           ld_pone  - tbl_trans    # $11-1 ftwotox zero
4623         short           szr_inf  - tbl_trans    # $11-2 ftwotox inf
4624         short           src_qnan - tbl_trans    # $11-3 ftwotox qnan
4625         short           stwotoxd - tbl_trans    # $11-5 ftwotox denorm
4626         short           src_snan - tbl_trans    # $11-4 ftwotox snan
4627         short           tbl_trans - tbl_trans   # $11-6 ftwotox unnorm
4628         short           tbl_trans - tbl_trans   # $11-7 ERROR
4629
4630         short           stentox  - tbl_trans    # $12-0 ftentox norm
4631         short           ld_pone  - tbl_trans    # $12-1 ftentox zero
4632         short           szr_inf  - tbl_trans    # $12-2 ftentox inf
4633         short           src_qnan - tbl_trans    # $12-3 ftentox qnan
4634         short           stentoxd - tbl_trans    # $12-5 ftentox denorm
4635         short           src_snan - tbl_trans    # $12-4 ftentox snan
4636         short           tbl_trans - tbl_trans   # $12-6 ftentox unnorm
4637         short           tbl_trans - tbl_trans   # $12-7 ERROR
4638
4639         short           tbl_trans - tbl_trans   # $13-0 ERROR
4640         short           tbl_trans - tbl_trans   # $13-1 ERROR
4641         short           tbl_trans - tbl_trans   # $13-2 ERROR
4642         short           tbl_trans - tbl_trans   # $13-3 ERROR
4643         short           tbl_trans - tbl_trans   # $13-4 ERROR
4644         short           tbl_trans - tbl_trans   # $13-5 ERROR
4645         short           tbl_trans - tbl_trans   # $13-6 ERROR
4646         short           tbl_trans - tbl_trans   # $13-7 ERROR
4647
4648         short           slogn    - tbl_trans    # $14-0 flogn norm
4649         short           t_dz2    - tbl_trans    # $14-1 flogn zero
4650         short           sopr_inf - tbl_trans    # $14-2 flogn inf
4651         short           src_qnan - tbl_trans    # $14-3 flogn qnan
4652         short           slognd   - tbl_trans    # $14-5 flogn denorm
4653         short           src_snan - tbl_trans    # $14-4 flogn snan
4654         short           tbl_trans - tbl_trans   # $14-6 flogn unnorm
4655         short           tbl_trans - tbl_trans   # $14-7 ERROR
4656
4657         short           slog10   - tbl_trans    # $15-0 flog10 norm
4658         short           t_dz2    - tbl_trans    # $15-1 flog10 zero
4659         short           sopr_inf - tbl_trans    # $15-2 flog10 inf
4660         short           src_qnan - tbl_trans    # $15-3 flog10 qnan
4661         short           slog10d  - tbl_trans    # $15-5 flog10 denorm
4662         short           src_snan - tbl_trans    # $15-4 flog10 snan
4663         short           tbl_trans - tbl_trans   # $15-6 flog10 unnorm
4664         short           tbl_trans - tbl_trans   # $15-7 ERROR
4665
4666         short           slog2    - tbl_trans    # $16-0 flog2 norm
4667         short           t_dz2    - tbl_trans    # $16-1 flog2 zero
4668         short           sopr_inf - tbl_trans    # $16-2 flog2 inf
4669         short           src_qnan - tbl_trans    # $16-3 flog2 qnan
4670         short           slog2d   - tbl_trans    # $16-5 flog2 denorm
4671         short           src_snan - tbl_trans    # $16-4 flog2 snan
4672         short           tbl_trans - tbl_trans   # $16-6 flog2 unnorm
4673         short           tbl_trans - tbl_trans   # $16-7 ERROR
4674
4675         short           tbl_trans - tbl_trans   # $17-0 ERROR
4676         short           tbl_trans - tbl_trans   # $17-1 ERROR
4677         short           tbl_trans - tbl_trans   # $17-2 ERROR
4678         short           tbl_trans - tbl_trans   # $17-3 ERROR
4679         short           tbl_trans - tbl_trans   # $17-4 ERROR
4680         short           tbl_trans - tbl_trans   # $17-5 ERROR
4681         short           tbl_trans - tbl_trans   # $17-6 ERROR
4682         short           tbl_trans - tbl_trans   # $17-7 ERROR
4683
4684         short           tbl_trans - tbl_trans   # $18-0 fabs norm
4685         short           tbl_trans - tbl_trans   # $18-1 fabs zero
4686         short           tbl_trans - tbl_trans   # $18-2 fabs inf
4687         short           tbl_trans - tbl_trans   # $18-3 fabs qnan
4688         short           tbl_trans - tbl_trans   # $18-5 fabs denorm
4689         short           tbl_trans - tbl_trans   # $18-4 fabs snan
4690         short           tbl_trans - tbl_trans   # $18-6 fabs unnorm
4691         short           tbl_trans - tbl_trans   # $18-7 ERROR
4692
4693         short           scosh    - tbl_trans    # $19-0 fcosh norm
4694         short           ld_pone  - tbl_trans    # $19-1 fcosh zero
4695         short           ld_pinf  - tbl_trans    # $19-2 fcosh inf
4696         short           src_qnan - tbl_trans    # $19-3 fcosh qnan
4697         short           scoshd   - tbl_trans    # $19-5 fcosh denorm
4698         short           src_snan - tbl_trans    # $19-4 fcosh snan
4699         short           tbl_trans - tbl_trans   # $19-6 fcosh unnorm
4700         short           tbl_trans - tbl_trans   # $19-7 ERROR
4701
4702         short           tbl_trans - tbl_trans   # $1a-0 fneg norm
4703         short           tbl_trans - tbl_trans   # $1a-1 fneg zero
4704         short           tbl_trans - tbl_trans   # $1a-2 fneg inf
4705         short           tbl_trans - tbl_trans   # $1a-3 fneg qnan
4706         short           tbl_trans - tbl_trans   # $1a-5 fneg denorm
4707         short           tbl_trans - tbl_trans   # $1a-4 fneg snan
4708         short           tbl_trans - tbl_trans   # $1a-6 fneg unnorm
4709         short           tbl_trans - tbl_trans   # $1a-7 ERROR
4710
4711         short           tbl_trans - tbl_trans   # $1b-0 ERROR
4712         short           tbl_trans - tbl_trans   # $1b-1 ERROR
4713         short           tbl_trans - tbl_trans   # $1b-2 ERROR
4714         short           tbl_trans - tbl_trans   # $1b-3 ERROR
4715         short           tbl_trans - tbl_trans   # $1b-4 ERROR
4716         short           tbl_trans - tbl_trans   # $1b-5 ERROR
4717         short           tbl_trans - tbl_trans   # $1b-6 ERROR
4718         short           tbl_trans - tbl_trans   # $1b-7 ERROR
4719
4720         short           sacos    - tbl_trans    # $1c-0 facos norm
4721         short           ld_ppi2  - tbl_trans    # $1c-1 facos zero
4722         short           t_operr  - tbl_trans    # $1c-2 facos inf
4723         short           src_qnan - tbl_trans    # $1c-3 facos qnan
4724         short           sacosd   - tbl_trans    # $1c-5 facos denorm
4725         short           src_snan - tbl_trans    # $1c-4 facos snan
4726         short           tbl_trans - tbl_trans   # $1c-6 facos unnorm
4727         short           tbl_trans - tbl_trans   # $1c-7 ERROR
4728
4729         short           scos     - tbl_trans    # $1d-0 fcos norm
4730         short           ld_pone  - tbl_trans    # $1d-1 fcos zero
4731         short           t_operr  - tbl_trans    # $1d-2 fcos inf
4732         short           src_qnan - tbl_trans    # $1d-3 fcos qnan
4733         short           scosd    - tbl_trans    # $1d-5 fcos denorm
4734         short           src_snan - tbl_trans    # $1d-4 fcos snan
4735         short           tbl_trans - tbl_trans   # $1d-6 fcos unnorm
4736         short           tbl_trans - tbl_trans   # $1d-7 ERROR
4737
4738         short           sgetexp  - tbl_trans    # $1e-0 fgetexp norm
4739         short           src_zero - tbl_trans    # $1e-1 fgetexp zero
4740         short           t_operr  - tbl_trans    # $1e-2 fgetexp inf
4741         short           src_qnan - tbl_trans    # $1e-3 fgetexp qnan
4742         short           sgetexpd - tbl_trans    # $1e-5 fgetexp denorm
4743         short           src_snan - tbl_trans    # $1e-4 fgetexp snan
4744         short           tbl_trans - tbl_trans   # $1e-6 fgetexp unnorm
4745         short           tbl_trans - tbl_trans   # $1e-7 ERROR
4746
4747         short           sgetman  - tbl_trans    # $1f-0 fgetman norm
4748         short           src_zero - tbl_trans    # $1f-1 fgetman zero
4749         short           t_operr  - tbl_trans    # $1f-2 fgetman inf
4750         short           src_qnan - tbl_trans    # $1f-3 fgetman qnan
4751         short           sgetmand - tbl_trans    # $1f-5 fgetman denorm
4752         short           src_snan - tbl_trans    # $1f-4 fgetman snan
4753         short           tbl_trans - tbl_trans   # $1f-6 fgetman unnorm
4754         short           tbl_trans - tbl_trans   # $1f-7 ERROR
4755
4756         short           tbl_trans - tbl_trans   # $20-0 fdiv norm
4757         short           tbl_trans - tbl_trans   # $20-1 fdiv zero
4758         short           tbl_trans - tbl_trans   # $20-2 fdiv inf
4759         short           tbl_trans - tbl_trans   # $20-3 fdiv qnan
4760         short           tbl_trans - tbl_trans   # $20-5 fdiv denorm
4761         short           tbl_trans - tbl_trans   # $20-4 fdiv snan
4762         short           tbl_trans - tbl_trans   # $20-6 fdiv unnorm
4763         short           tbl_trans - tbl_trans   # $20-7 ERROR
4764
4765         short           smod_snorm - tbl_trans  # $21-0 fmod norm
4766         short           smod_szero - tbl_trans  # $21-1 fmod zero
4767         short           smod_sinf - tbl_trans   # $21-2 fmod inf
4768         short           sop_sqnan - tbl_trans   # $21-3 fmod qnan
4769         short           smod_sdnrm - tbl_trans  # $21-5 fmod denorm
4770         short           sop_ssnan - tbl_trans   # $21-4 fmod snan
4771         short           tbl_trans - tbl_trans   # $21-6 fmod unnorm
4772         short           tbl_trans - tbl_trans   # $21-7 ERROR
4773
4774         short           tbl_trans - tbl_trans   # $22-0 fadd norm
4775         short           tbl_trans - tbl_trans   # $22-1 fadd zero
4776         short           tbl_trans - tbl_trans   # $22-2 fadd inf
4777         short           tbl_trans - tbl_trans   # $22-3 fadd qnan
4778         short           tbl_trans - tbl_trans   # $22-5 fadd denorm
4779         short           tbl_trans - tbl_trans   # $22-4 fadd snan
4780         short           tbl_trans - tbl_trans   # $22-6 fadd unnorm
4781         short           tbl_trans - tbl_trans   # $22-7 ERROR
4782
4783         short           tbl_trans - tbl_trans   # $23-0 fmul norm
4784         short           tbl_trans - tbl_trans   # $23-1 fmul zero
4785         short           tbl_trans - tbl_trans   # $23-2 fmul inf
4786         short           tbl_trans - tbl_trans   # $23-3 fmul qnan
4787         short           tbl_trans - tbl_trans   # $23-5 fmul denorm
4788         short           tbl_trans - tbl_trans   # $23-4 fmul snan
4789         short           tbl_trans - tbl_trans   # $23-6 fmul unnorm
4790         short           tbl_trans - tbl_trans   # $23-7 ERROR
4791
4792         short           tbl_trans - tbl_trans   # $24-0 fsgldiv norm
4793         short           tbl_trans - tbl_trans   # $24-1 fsgldiv zero
4794         short           tbl_trans - tbl_trans   # $24-2 fsgldiv inf
4795         short           tbl_trans - tbl_trans   # $24-3 fsgldiv qnan
4796         short           tbl_trans - tbl_trans   # $24-5 fsgldiv denorm
4797         short           tbl_trans - tbl_trans   # $24-4 fsgldiv snan
4798         short           tbl_trans - tbl_trans   # $24-6 fsgldiv unnorm
4799         short           tbl_trans - tbl_trans   # $24-7 ERROR
4800
4801         short           srem_snorm - tbl_trans  # $25-0 frem norm
4802         short           srem_szero - tbl_trans  # $25-1 frem zero
4803         short           srem_sinf - tbl_trans   # $25-2 frem inf
4804         short           sop_sqnan - tbl_trans   # $25-3 frem qnan
4805         short           srem_sdnrm - tbl_trans  # $25-5 frem denorm
4806         short           sop_ssnan - tbl_trans   # $25-4 frem snan
4807         short           tbl_trans - tbl_trans   # $25-6 frem unnorm
4808         short           tbl_trans - tbl_trans   # $25-7 ERROR
4809
4810         short           sscale_snorm - tbl_trans # $26-0 fscale norm
4811         short           sscale_szero - tbl_trans # $26-1 fscale zero
4812         short           sscale_sinf - tbl_trans # $26-2 fscale inf
4813         short           sop_sqnan - tbl_trans   # $26-3 fscale qnan
4814         short           sscale_sdnrm - tbl_trans # $26-5 fscale denorm
4815         short           sop_ssnan - tbl_trans   # $26-4 fscale snan
4816         short           tbl_trans - tbl_trans   # $26-6 fscale unnorm
4817         short           tbl_trans - tbl_trans   # $26-7 ERROR
4818
4819         short           tbl_trans - tbl_trans   # $27-0 fsglmul norm
4820         short           tbl_trans - tbl_trans   # $27-1 fsglmul zero
4821         short           tbl_trans - tbl_trans   # $27-2 fsglmul inf
4822         short           tbl_trans - tbl_trans   # $27-3 fsglmul qnan
4823         short           tbl_trans - tbl_trans   # $27-5 fsglmul denorm
4824         short           tbl_trans - tbl_trans   # $27-4 fsglmul snan
4825         short           tbl_trans - tbl_trans   # $27-6 fsglmul unnorm
4826         short           tbl_trans - tbl_trans   # $27-7 ERROR
4827
4828         short           tbl_trans - tbl_trans   # $28-0 fsub norm
4829         short           tbl_trans - tbl_trans   # $28-1 fsub zero
4830         short           tbl_trans - tbl_trans   # $28-2 fsub inf
4831         short           tbl_trans - tbl_trans   # $28-3 fsub qnan
4832         short           tbl_trans - tbl_trans   # $28-5 fsub denorm
4833         short           tbl_trans - tbl_trans   # $28-4 fsub snan
4834         short           tbl_trans - tbl_trans   # $28-6 fsub unnorm
4835         short           tbl_trans - tbl_trans   # $28-7 ERROR
4836
4837         short           tbl_trans - tbl_trans   # $29-0 ERROR
4838         short           tbl_trans - tbl_trans   # $29-1 ERROR
4839         short           tbl_trans - tbl_trans   # $29-2 ERROR
4840         short           tbl_trans - tbl_trans   # $29-3 ERROR
4841         short           tbl_trans - tbl_trans   # $29-4 ERROR
4842         short           tbl_trans - tbl_trans   # $29-5 ERROR
4843         short           tbl_trans - tbl_trans   # $29-6 ERROR
4844         short           tbl_trans - tbl_trans   # $29-7 ERROR
4845
4846         short           tbl_trans - tbl_trans   # $2a-0 ERROR
4847         short           tbl_trans - tbl_trans   # $2a-1 ERROR
4848         short           tbl_trans - tbl_trans   # $2a-2 ERROR
4849         short           tbl_trans - tbl_trans   # $2a-3 ERROR
4850         short           tbl_trans - tbl_trans   # $2a-4 ERROR
4851         short           tbl_trans - tbl_trans   # $2a-5 ERROR
4852         short           tbl_trans - tbl_trans   # $2a-6 ERROR
4853         short           tbl_trans - tbl_trans   # $2a-7 ERROR
4854
4855         short           tbl_trans - tbl_trans   # $2b-0 ERROR
4856         short           tbl_trans - tbl_trans   # $2b-1 ERROR
4857         short           tbl_trans - tbl_trans   # $2b-2 ERROR
4858         short           tbl_trans - tbl_trans   # $2b-3 ERROR
4859         short           tbl_trans - tbl_trans   # $2b-4 ERROR
4860         short           tbl_trans - tbl_trans   # $2b-5 ERROR
4861         short           tbl_trans - tbl_trans   # $2b-6 ERROR
4862         short           tbl_trans - tbl_trans   # $2b-7 ERROR
4863
4864         short           tbl_trans - tbl_trans   # $2c-0 ERROR
4865         short           tbl_trans - tbl_trans   # $2c-1 ERROR
4866         short           tbl_trans - tbl_trans   # $2c-2 ERROR
4867         short           tbl_trans - tbl_trans   # $2c-3 ERROR
4868         short           tbl_trans - tbl_trans   # $2c-4 ERROR
4869         short           tbl_trans - tbl_trans   # $2c-5 ERROR
4870         short           tbl_trans - tbl_trans   # $2c-6 ERROR
4871         short           tbl_trans - tbl_trans   # $2c-7 ERROR
4872
4873         short           tbl_trans - tbl_trans   # $2d-0 ERROR
4874         short           tbl_trans - tbl_trans   # $2d-1 ERROR
4875         short           tbl_trans - tbl_trans   # $2d-2 ERROR
4876         short           tbl_trans - tbl_trans   # $2d-3 ERROR
4877         short           tbl_trans - tbl_trans   # $2d-4 ERROR
4878         short           tbl_trans - tbl_trans   # $2d-5 ERROR
4879         short           tbl_trans - tbl_trans   # $2d-6 ERROR
4880         short           tbl_trans - tbl_trans   # $2d-7 ERROR
4881
4882         short           tbl_trans - tbl_trans   # $2e-0 ERROR
4883         short           tbl_trans - tbl_trans   # $2e-1 ERROR
4884         short           tbl_trans - tbl_trans   # $2e-2 ERROR
4885         short           tbl_trans - tbl_trans   # $2e-3 ERROR
4886         short           tbl_trans - tbl_trans   # $2e-4 ERROR
4887         short           tbl_trans - tbl_trans   # $2e-5 ERROR
4888         short           tbl_trans - tbl_trans   # $2e-6 ERROR
4889         short           tbl_trans - tbl_trans   # $2e-7 ERROR
4890
4891         short           tbl_trans - tbl_trans   # $2f-0 ERROR
4892         short           tbl_trans - tbl_trans   # $2f-1 ERROR
4893         short           tbl_trans - tbl_trans   # $2f-2 ERROR
4894         short           tbl_trans - tbl_trans   # $2f-3 ERROR
4895         short           tbl_trans - tbl_trans   # $2f-4 ERROR
4896         short           tbl_trans - tbl_trans   # $2f-5 ERROR
4897         short           tbl_trans - tbl_trans   # $2f-6 ERROR
4898         short           tbl_trans - tbl_trans   # $2f-7 ERROR
4899
4900         short           ssincos  - tbl_trans    # $30-0 fsincos norm
4901         short           ssincosz - tbl_trans    # $30-1 fsincos zero
4902         short           ssincosi - tbl_trans    # $30-2 fsincos inf
4903         short           ssincosqnan - tbl_trans # $30-3 fsincos qnan
4904         short           ssincosd - tbl_trans    # $30-5 fsincos denorm
4905         short           ssincossnan - tbl_trans # $30-4 fsincos snan
4906         short           tbl_trans - tbl_trans   # $30-6 fsincos unnorm
4907         short           tbl_trans - tbl_trans   # $30-7 ERROR
4908
4909         short           ssincos  - tbl_trans    # $31-0 fsincos norm
4910         short           ssincosz - tbl_trans    # $31-1 fsincos zero
4911         short           ssincosi - tbl_trans    # $31-2 fsincos inf
4912         short           ssincosqnan - tbl_trans # $31-3 fsincos qnan
4913         short           ssincosd - tbl_trans    # $31-5 fsincos denorm
4914         short           ssincossnan - tbl_trans # $31-4 fsincos snan
4915         short           tbl_trans - tbl_trans   # $31-6 fsincos unnorm
4916         short           tbl_trans - tbl_trans   # $31-7 ERROR
4917
4918         short           ssincos  - tbl_trans    # $32-0 fsincos norm
4919         short           ssincosz - tbl_trans    # $32-1 fsincos zero
4920         short           ssincosi - tbl_trans    # $32-2 fsincos inf
4921         short           ssincosqnan - tbl_trans # $32-3 fsincos qnan
4922         short           ssincosd - tbl_trans    # $32-5 fsincos denorm
4923         short           ssincossnan - tbl_trans # $32-4 fsincos snan
4924         short           tbl_trans - tbl_trans   # $32-6 fsincos unnorm
4925         short           tbl_trans - tbl_trans   # $32-7 ERROR
4926
4927         short           ssincos  - tbl_trans    # $33-0 fsincos norm
4928         short           ssincosz - tbl_trans    # $33-1 fsincos zero
4929         short           ssincosi - tbl_trans    # $33-2 fsincos inf
4930         short           ssincosqnan - tbl_trans # $33-3 fsincos qnan
4931         short           ssincosd - tbl_trans    # $33-5 fsincos denorm
4932         short           ssincossnan - tbl_trans # $33-4 fsincos snan
4933         short           tbl_trans - tbl_trans   # $33-6 fsincos unnorm
4934         short           tbl_trans - tbl_trans   # $33-7 ERROR
4935
4936         short           ssincos  - tbl_trans    # $34-0 fsincos norm
4937         short           ssincosz - tbl_trans    # $34-1 fsincos zero
4938         short           ssincosi - tbl_trans    # $34-2 fsincos inf
4939         short           ssincosqnan - tbl_trans # $34-3 fsincos qnan
4940         short           ssincosd - tbl_trans    # $34-5 fsincos denorm
4941         short           ssincossnan - tbl_trans # $34-4 fsincos snan
4942         short           tbl_trans - tbl_trans   # $34-6 fsincos unnorm
4943         short           tbl_trans - tbl_trans   # $34-7 ERROR
4944
4945         short          &