81f6a9856dceab8474ae99c7d9f062429841b16e
[linux-3.10.git] / arch / m68k / fpsp040 / do_func.S
1 |
2 |       do_func.sa 3.4 2/18/91
3 |
4 | Do_func performs the unimplemented operation.  The operation
5 | to be performed is determined from the lower 7 bits of the
6 | extension word (except in the case of fmovecr and fsincos).
7 | The opcode and tag bits form an index into a jump table in
8 | tbldo.sa.  Cases of zero, infinity and NaN are handled in
9 | do_func by forcing the default result.  Normalized and
10 | denormalized (there are no unnormalized numbers at this
11 | point) are passed onto the emulation code.
12 |
13 | CMDREG1B and STAG are extracted from the fsave frame
14 | and combined to form the table index.  The function called
15 | will start with a0 pointing to the ETEMP operand.  Dyadic
16 | functions can find FPTEMP at -12(a0).
17 |
18 | Called functions return their result in fp0.  Sincos returns
19 | sin(x) in fp0 and cos(x) in fp1.
20 |
21
22 |               Copyright (C) Motorola, Inc. 1990
23 |                       All Rights Reserved
24 |
25 |       THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
26 |       The copyright notice above does not evidence any
27 |       actual or intended publication of such source code.
28
29 DO_FUNC:        |idnt    2,1 | Motorola 040 Floating Point Software Package
30
31         |section        8
32
33 #include "fpsp.h"
34
35         |xref   t_dz2
36         |xref   t_operr
37         |xref   t_inx2
38         |xref   t_resdnrm
39         |xref   dst_nan
40         |xref   src_nan
41         |xref   nrm_set
42         |xref   sto_cos
43
44         |xref   tblpre
45         |xref   slognp1,slogn,slog10,slog2
46         |xref   slognd,slog10d,slog2d
47         |xref   smod,srem
48         |xref   sscale
49         |xref   smovcr
50
51 PONE:   .long   0x3fff0000,0x80000000,0x00000000        |+1
52 MONE:   .long   0xbfff0000,0x80000000,0x00000000        |-1
53 PZERO:  .long   0x00000000,0x00000000,0x00000000        |+0
54 MZERO:  .long   0x80000000,0x00000000,0x00000000        |-0
55 PINF:   .long   0x7fff0000,0x00000000,0x00000000        |+inf
56 MINF:   .long   0xffff0000,0x00000000,0x00000000        |-inf
57 QNAN:   .long   0x7fff0000,0xffffffff,0xffffffff        |non-signaling nan
58 PPIBY2:  .long  0x3FFF0000,0xC90FDAA2,0x2168C235        |+PI/2
59 MPIBY2:  .long  0xbFFF0000,0xC90FDAA2,0x2168C235        |-PI/2
60
61         .global do_func
62 do_func:
63         clrb    CU_ONLY(%a6)
64 |
65 | Check for fmovecr.  It does not follow the format of fp gen
66 | unimplemented instructions.  The test is on the upper 6 bits;
67 | if they are $17, the inst is fmovecr.  Call entry smovcr
68 | directly.
69 |
70         bfextu  CMDREG1B(%a6){#0:#6},%d0 |get opclass and src fields
71         cmpil   #0x17,%d0               |if op class and size fields are $17,
72 |                               ;it is FMOVECR; if not, continue
73         bnes    not_fmovecr
74         jmp     smovcr          |fmovecr; jmp directly to emulation
75
76 not_fmovecr:
77         movew   CMDREG1B(%a6),%d0
78         andl    #0x7F,%d0
79         cmpil   #0x38,%d0               |if the extension is >= $38,
80         bge     serror          |it is illegal
81         bfextu  STAG(%a6){#0:#3},%d1
82         lsll    #3,%d0          |make room for STAG
83         addl    %d1,%d0         |combine for final index into table
84         leal    tblpre,%a1      |start of monster jump table
85         movel   (%a1,%d0.w*4),%a1       |real target address
86         leal    ETEMP(%a6),%a0  |a0 is pointer to src op
87         movel   USER_FPCR(%a6),%d1
88         andl    #0xFF,%d1               | discard all but rounding mode/prec
89         fmovel  #0,%fpcr
90         jmp     (%a1)
91 |
92 |       ERROR
93 |
94         .global serror
95 serror:
96         st      STORE_FLG(%a6)
97         rts
98 |
99 | These routines load forced values into fp0.  They are called
100 | by index into tbldo.
101 |
102 | Load a signed zero to fp0 and set inex2/ainex
103 |
104         .global snzrinx
105 snzrinx:
106         btstb   #sign_bit,LOCAL_EX(%a0) |get sign of source operand
107         bnes    ld_mzinx        |if negative, branch
108         bsr     ld_pzero        |bsr so we can return and set inx
109         bra     t_inx2          |now, set the inx for the next inst
110 ld_mzinx:
111         bsr     ld_mzero        |if neg, load neg zero, return here
112         bra     t_inx2          |now, set the inx for the next inst
113 |
114 | Load a signed zero to fp0; do not set inex2/ainex
115 |
116         .global szero
117 szero:
118         btstb   #sign_bit,LOCAL_EX(%a0) |get sign of source operand
119         bne     ld_mzero        |if neg, load neg zero
120         bra     ld_pzero        |load positive zero
121 |
122 | Load a signed infinity to fp0; do not set inex2/ainex
123 |
124         .global sinf
125 sinf:
126         btstb   #sign_bit,LOCAL_EX(%a0) |get sign of source operand
127         bne     ld_minf                 |if negative branch
128         bra     ld_pinf
129 |
130 | Load a signed one to fp0; do not set inex2/ainex
131 |
132         .global sone
133 sone:
134         btstb   #sign_bit,LOCAL_EX(%a0) |check sign of source
135         bne     ld_mone
136         bra     ld_pone
137 |
138 | Load a signed pi/2 to fp0; do not set inex2/ainex
139 |
140         .global spi_2
141 spi_2:
142         btstb   #sign_bit,LOCAL_EX(%a0) |check sign of source
143         bne     ld_mpi2
144         bra     ld_ppi2
145 |
146 | Load either a +0 or +inf for plus/minus operand
147 |
148         .global szr_inf
149 szr_inf:
150         btstb   #sign_bit,LOCAL_EX(%a0) |check sign of source
151         bne     ld_pzero
152         bra     ld_pinf
153 |
154 | Result is either an operr or +inf for plus/minus operand
155 | [Used by slogn, slognp1, slog10, and slog2]
156 |
157         .global sopr_inf
158 sopr_inf:
159         btstb   #sign_bit,LOCAL_EX(%a0) |check sign of source
160         bne     t_operr
161         bra     ld_pinf
162 |
163 |       FLOGNP1
164 |
165         .global sslognp1
166 sslognp1:
167         fmovemx (%a0),%fp0-%fp0
168         fcmpb   #-1,%fp0
169         fbgt    slognp1
170         fbeq    t_dz2           |if = -1, divide by zero exception
171         fmovel  #0,%FPSR                |clr N flag
172         bra     t_operr         |take care of operands < -1
173 |
174 |       FETOXM1
175 |
176         .global setoxm1i
177 setoxm1i:
178         btstb   #sign_bit,LOCAL_EX(%a0) |check sign of source
179         bne     ld_mone
180         bra     ld_pinf
181 |
182 |       FLOGN
183 |
184 | Test for 1.0 as an input argument, returning +zero.  Also check
185 | the sign and return operr if negative.
186 |
187         .global sslogn
188 sslogn:
189         btstb   #sign_bit,LOCAL_EX(%a0)
190         bne     t_operr         |take care of operands < 0
191         cmpiw   #0x3fff,LOCAL_EX(%a0) |test for 1.0 input
192         bne     slogn
193         cmpil   #0x80000000,LOCAL_HI(%a0)
194         bne     slogn
195         tstl    LOCAL_LO(%a0)
196         bne     slogn
197         fmovex  PZERO,%fp0
198         rts
199
200         .global sslognd
201 sslognd:
202         btstb   #sign_bit,LOCAL_EX(%a0)
203         beq     slognd
204         bra     t_operr         |take care of operands < 0
205
206 |
207 |       FLOG10
208 |
209         .global sslog10
210 sslog10:
211         btstb   #sign_bit,LOCAL_EX(%a0)
212         bne     t_operr         |take care of operands < 0
213         cmpiw   #0x3fff,LOCAL_EX(%a0) |test for 1.0 input
214         bne     slog10
215         cmpil   #0x80000000,LOCAL_HI(%a0)
216         bne     slog10
217         tstl    LOCAL_LO(%a0)
218         bne     slog10
219         fmovex  PZERO,%fp0
220         rts
221
222         .global sslog10d
223 sslog10d:
224         btstb   #sign_bit,LOCAL_EX(%a0)
225         beq     slog10d
226         bra     t_operr         |take care of operands < 0
227
228 |
229 |       FLOG2
230 |
231         .global sslog2
232 sslog2:
233         btstb   #sign_bit,LOCAL_EX(%a0)
234         bne     t_operr         |take care of operands < 0
235         cmpiw   #0x3fff,LOCAL_EX(%a0) |test for 1.0 input
236         bne     slog2
237         cmpil   #0x80000000,LOCAL_HI(%a0)
238         bne     slog2
239         tstl    LOCAL_LO(%a0)
240         bne     slog2
241         fmovex  PZERO,%fp0
242         rts
243
244         .global sslog2d
245 sslog2d:
246         btstb   #sign_bit,LOCAL_EX(%a0)
247         beq     slog2d
248         bra     t_operr         |take care of operands < 0
249
250 |
251 |       FMOD
252 |
253 pmodt:
254 |                               ;$21 fmod
255 |                               ;dtag,stag
256         .long   smod            |  00,00  norm,norm = normal
257         .long   smod_oper       |  00,01  norm,zero = nan with operr
258         .long   smod_fpn        |  00,10  norm,inf  = fpn
259         .long   smod_snan       |  00,11  norm,nan  = nan
260         .long   smod_zro        |  01,00  zero,norm = +-zero
261         .long   smod_oper       |  01,01  zero,zero = nan with operr
262         .long   smod_zro        |  01,10  zero,inf  = +-zero
263         .long   smod_snan       |  01,11  zero,nan  = nan
264         .long   smod_oper       |  10,00  inf,norm  = nan with operr
265         .long   smod_oper       |  10,01  inf,zero  = nan with operr
266         .long   smod_oper       |  10,10  inf,inf   = nan with operr
267         .long   smod_snan       |  10,11  inf,nan   = nan
268         .long   smod_dnan       |  11,00  nan,norm  = nan
269         .long   smod_dnan       |  11,01  nan,zero  = nan
270         .long   smod_dnan       |  11,10  nan,inf   = nan
271         .long   smod_dnan       |  11,11  nan,nan   = nan
272
273         .global pmod
274 pmod:
275         clrb    FPSR_QBYTE(%a6) | clear quotient field
276         bfextu  STAG(%a6){#0:#3},%d0 |stag = d0
277         bfextu  DTAG(%a6){#0:#3},%d1 |dtag = d1
278
279 |
280 | Alias extended denorms to norms for the jump table.
281 |
282         bclrl   #2,%d0
283         bclrl   #2,%d1
284
285         lslb    #2,%d1
286         orb     %d0,%d1         |d1{3:2} = dtag, d1{1:0} = stag
287 |                               ;Tag values:
288 |                               ;00 = norm or denorm
289 |                               ;01 = zero
290 |                               ;10 = inf
291 |                               ;11 = nan
292         lea     pmodt,%a1
293         movel   (%a1,%d1.w*4),%a1
294         jmp     (%a1)
295
296 smod_snan:
297         bra     src_nan
298 smod_dnan:
299         bra     dst_nan
300 smod_oper:
301         bra     t_operr
302 smod_zro:
303         moveb   ETEMP(%a6),%d1  |get sign of src op
304         moveb   FPTEMP(%a6),%d0 |get sign of dst op
305         eorb    %d0,%d1         |get exor of sign bits
306         btstl   #7,%d1          |test for sign
307         beqs    smod_zsn        |if clr, do not set sign big
308         bsetb   #q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
309 smod_zsn:
310         btstl   #7,%d0          |test if + or -
311         beq     ld_pzero        |if pos then load +0
312         bra     ld_mzero        |else neg load -0
313
314 smod_fpn:
315         moveb   ETEMP(%a6),%d1  |get sign of src op
316         moveb   FPTEMP(%a6),%d0 |get sign of dst op
317         eorb    %d0,%d1         |get exor of sign bits
318         btstl   #7,%d1          |test for sign
319         beqs    smod_fsn        |if clr, do not set sign big
320         bsetb   #q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
321 smod_fsn:
322         tstb    DTAG(%a6)       |filter out denormal destination case
323         bpls    smod_nrm        |
324         leal    FPTEMP(%a6),%a0 |a0<- addr(FPTEMP)
325         bra     t_resdnrm       |force UNFL(but exact) result
326 smod_nrm:
327         fmovel USER_FPCR(%a6),%fpcr |use user's rmode and precision
328         fmovex FPTEMP(%a6),%fp0 |return dest to fp0
329         rts
330
331 |
332 |       FREM
333 |
334 premt:
335 |                               ;$25 frem
336 |                               ;dtag,stag
337         .long   srem            |  00,00  norm,norm = normal
338         .long   srem_oper       |  00,01  norm,zero = nan with operr
339         .long   srem_fpn        |  00,10  norm,inf  = fpn
340         .long   srem_snan       |  00,11  norm,nan  = nan
341         .long   srem_zro        |  01,00  zero,norm = +-zero
342         .long   srem_oper       |  01,01  zero,zero = nan with operr
343         .long   srem_zro        |  01,10  zero,inf  = +-zero
344         .long   srem_snan       |  01,11  zero,nan  = nan
345         .long   srem_oper       |  10,00  inf,norm  = nan with operr
346         .long   srem_oper       |  10,01  inf,zero  = nan with operr
347         .long   srem_oper       |  10,10  inf,inf   = nan with operr
348         .long   srem_snan       |  10,11  inf,nan   = nan
349         .long   srem_dnan       |  11,00  nan,norm  = nan
350         .long   srem_dnan       |  11,01  nan,zero  = nan
351         .long   srem_dnan       |  11,10  nan,inf   = nan
352         .long   srem_dnan       |  11,11  nan,nan   = nan
353
354         .global prem
355 prem:
356         clrb    FPSR_QBYTE(%a6)   |clear quotient field
357         bfextu  STAG(%a6){#0:#3},%d0 |stag = d0
358         bfextu  DTAG(%a6){#0:#3},%d1 |dtag = d1
359 |
360 | Alias extended denorms to norms for the jump table.
361 |
362         bclr    #2,%d0
363         bclr    #2,%d1
364
365         lslb    #2,%d1
366         orb     %d0,%d1         |d1{3:2} = dtag, d1{1:0} = stag
367 |                               ;Tag values:
368 |                               ;00 = norm or denorm
369 |                               ;01 = zero
370 |                               ;10 = inf
371 |                               ;11 = nan
372         lea     premt,%a1
373         movel   (%a1,%d1.w*4),%a1
374         jmp     (%a1)
375
376 srem_snan:
377         bra     src_nan
378 srem_dnan:
379         bra     dst_nan
380 srem_oper:
381         bra     t_operr
382 srem_zro:
383         moveb   ETEMP(%a6),%d1  |get sign of src op
384         moveb   FPTEMP(%a6),%d0 |get sign of dst op
385         eorb    %d0,%d1         |get exor of sign bits
386         btstl   #7,%d1          |test for sign
387         beqs    srem_zsn        |if clr, do not set sign big
388         bsetb   #q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
389 srem_zsn:
390         btstl   #7,%d0          |test if + or -
391         beq     ld_pzero        |if pos then load +0
392         bra     ld_mzero        |else neg load -0
393
394 srem_fpn:
395         moveb   ETEMP(%a6),%d1  |get sign of src op
396         moveb   FPTEMP(%a6),%d0 |get sign of dst op
397         eorb    %d0,%d1         |get exor of sign bits
398         btstl   #7,%d1          |test for sign
399         beqs    srem_fsn        |if clr, do not set sign big
400         bsetb   #q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
401 srem_fsn:
402         tstb    DTAG(%a6)       |filter out denormal destination case
403         bpls    srem_nrm        |
404         leal    FPTEMP(%a6),%a0 |a0<- addr(FPTEMP)
405         bra     t_resdnrm       |force UNFL(but exact) result
406 srem_nrm:
407         fmovel USER_FPCR(%a6),%fpcr |use user's rmode and precision
408         fmovex FPTEMP(%a6),%fp0 |return dest to fp0
409         rts
410 |
411 |       FSCALE
412 |
413 pscalet:
414 |                               ;$26 fscale
415 |                               ;dtag,stag
416         .long   sscale          |  00,00  norm,norm = result
417         .long   sscale          |  00,01  norm,zero = fpn
418         .long   scl_opr         |  00,10  norm,inf  = nan with operr
419         .long   scl_snan        |  00,11  norm,nan  = nan
420         .long   scl_zro         |  01,00  zero,norm = +-zero
421         .long   scl_zro         |  01,01  zero,zero = +-zero
422         .long   scl_opr         |  01,10  zero,inf  = nan with operr
423         .long   scl_snan        |  01,11  zero,nan  = nan
424         .long   scl_inf         |  10,00  inf,norm  = +-inf
425         .long   scl_inf         |  10,01  inf,zero  = +-inf
426         .long   scl_opr         |  10,10  inf,inf   = nan with operr
427         .long   scl_snan        |  10,11  inf,nan   = nan
428         .long   scl_dnan        |  11,00  nan,norm  = nan
429         .long   scl_dnan        |  11,01  nan,zero  = nan
430         .long   scl_dnan        |  11,10  nan,inf   = nan
431         .long   scl_dnan        |  11,11  nan,nan   = nan
432
433         .global pscale
434 pscale:
435         bfextu  STAG(%a6){#0:#3},%d0 |stag in d0
436         bfextu  DTAG(%a6){#0:#3},%d1 |dtag in d1
437         bclrl   #2,%d0          |alias  denorm into norm
438         bclrl   #2,%d1          |alias  denorm into norm
439         lslb    #2,%d1
440         orb     %d0,%d1         |d1{4:2} = dtag, d1{1:0} = stag
441 |                               ;dtag values     stag values:
442 |                               ;000 = norm      00 = norm
443 |                               ;001 = zero      01 = zero
444 |                               ;010 = inf       10 = inf
445 |                               ;011 = nan       11 = nan
446 |                               ;100 = dnrm
447 |
448 |
449         leal    pscalet,%a1     |load start of jump table
450         movel   (%a1,%d1.w*4),%a1       |load a1 with label depending on tag
451         jmp     (%a1)           |go to the routine
452
453 scl_opr:
454         bra     t_operr
455
456 scl_dnan:
457         bra     dst_nan
458
459 scl_zro:
460         btstb   #sign_bit,FPTEMP_EX(%a6)        |test if + or -
461         beq     ld_pzero                |if pos then load +0
462         bra     ld_mzero                |if neg then load -0
463 scl_inf:
464         btstb   #sign_bit,FPTEMP_EX(%a6)        |test if + or -
465         beq     ld_pinf                 |if pos then load +inf
466         bra     ld_minf                 |else neg load -inf
467 scl_snan:
468         bra     src_nan
469 |
470 |       FSINCOS
471 |
472         .global ssincosz
473 ssincosz:
474         btstb   #sign_bit,ETEMP(%a6)    |get sign
475         beqs    sincosp
476         fmovex  MZERO,%fp0
477         bras    sincoscom
478 sincosp:
479         fmovex PZERO,%fp0
480 sincoscom:
481         fmovemx PONE,%fp1-%fp1  |do not allow FPSR to be affected
482         bra     sto_cos         |store cosine result
483
484         .global ssincosi
485 ssincosi:
486         fmovex QNAN,%fp1        |load NAN
487         bsr     sto_cos         |store cosine result
488         fmovex QNAN,%fp0        |load NAN
489         bra     t_operr
490
491         .global ssincosnan
492 ssincosnan:
493         movel   ETEMP_EX(%a6),FP_SCR1(%a6)
494         movel   ETEMP_HI(%a6),FP_SCR1+4(%a6)
495         movel   ETEMP_LO(%a6),FP_SCR1+8(%a6)
496         bsetb   #signan_bit,FP_SCR1+4(%a6)
497         fmovemx FP_SCR1(%a6),%fp1-%fp1
498         bsr     sto_cos
499         bra     src_nan
500 |
501 | This code forces default values for the zero, inf, and nan cases
502 | in the transcendentals code.  The CC bits must be set in the
503 | stacked FPSR to be correctly reported.
504 |
505 |**Returns +PI/2
506         .global ld_ppi2
507 ld_ppi2:
508         fmovex PPIBY2,%fp0              |load +pi/2
509         bra     t_inx2                  |set inex2 exc
510
511 |**Returns -PI/2
512         .global ld_mpi2
513 ld_mpi2:
514         fmovex MPIBY2,%fp0              |load -pi/2
515         orl     #neg_mask,USER_FPSR(%a6)        |set N bit
516         bra     t_inx2                  |set inex2 exc
517
518 |**Returns +inf
519         .global ld_pinf
520 ld_pinf:
521         fmovex PINF,%fp0                |load +inf
522         orl     #inf_mask,USER_FPSR(%a6)        |set I bit
523         rts
524
525 |**Returns -inf
526         .global ld_minf
527 ld_minf:
528         fmovex MINF,%fp0                |load -inf
529         orl     #neg_mask+inf_mask,USER_FPSR(%a6)       |set N and I bits
530         rts
531
532 |**Returns +1
533         .global ld_pone
534 ld_pone:
535         fmovex PONE,%fp0                |load +1
536         rts
537
538 |**Returns -1
539         .global ld_mone
540 ld_mone:
541         fmovex MONE,%fp0                |load -1
542         orl     #neg_mask,USER_FPSR(%a6)        |set N bit
543         rts
544
545 |**Returns +0
546         .global ld_pzero
547 ld_pzero:
548         fmovex PZERO,%fp0               |load +0
549         orl     #z_mask,USER_FPSR(%a6)  |set Z bit
550         rts
551
552 |**Returns -0
553         .global ld_mzero
554 ld_mzero:
555         fmovex MZERO,%fp0               |load -0
556         orl     #neg_mask+z_mask,USER_FPSR(%a6) |set N and Z bits
557         rts
558
559         |end