source: rtems/c/src/lib/libcpu/m68k/m68040/fpsp/do_func.s @ 1d320bac

4.104.114.84.95
Last change on this file since 1d320bac was 1d320bac, checked in by Joel Sherrill <joel.sherrill@…>, on 07/09/97 at 23:41:20

This code was in the tree but not actually being compiled. There
were a number of minor problems which had to be fixed to get it
to compile including modifying the compile rule to handle C++ comments,
changing the syntax of the include statement, and getting rid of "%"
as part of register names.

  • Property mode set to 100644
File size: 13.9 KB
Line 
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
29DO_FUNC:        //idnt    2,1 | Motorola 040 Floating Point Software Package
30
31        |section        8
32
33#include "fpsp.defs"
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
51PONE:   .long   0x3fff0000,0x80000000,0x00000000        //+1
52MONE:   .long   0xbfff0000,0x80000000,0x00000000        //-1
53PZERO:  .long   0x00000000,0x00000000,0x00000000        //+0
54MZERO:  .long   0x80000000,0x00000000,0x00000000        //-0
55PINF:   .long   0x7fff0000,0x00000000,0x00000000        //+inf
56MINF:   .long   0xffff0000,0x00000000,0x00000000        //-inf
57QNAN:   .long   0x7fff0000,0xffffffff,0xffffffff        //non-signaling nan
58PPIBY2:  .long  0x3FFF0000,0xC90FDAA2,0x2168C235        //+PI/2
59MPIBY2:  .long  0xbFFF0000,0xC90FDAA2,0x2168C235        //-PI/2
60
61        .global do_func
62do_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
76not_fmovecr:
77        movew   CMDREG1B(%a6),%d0
78        andl    #0x7F,%d0
79        cmpil   #0x38,%d0               //if the extension is >= $38,
80        bges    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
95serror:
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
105snzrinx:
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
110ld_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
117szero:
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
125sinf:
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
133sone:
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
141spi_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
149szr_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
158sopr_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
166sslognp1:
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
177setoxm1i:
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
188sslogn:
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
201sslognd:
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
210sslog10:
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
223sslog10d:
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
232sslog2:
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
245sslog2d:
246        btstb   #sign_bit,LOCAL_EX(%a0)
247        beq     slog2d
248        bra     t_operr         //take care of operands < 0
249
250//
251//      FMOD
252//
253pmodt:
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
274pmod:
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
296smod_snan:
297        bra     src_nan
298smod_dnan:
299        bra     dst_nan
300smod_oper:
301        bra     t_operr
302smod_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
309smod_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       
314smod_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
321smod_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
326smod_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//
334premt:
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
355prem:
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       
376srem_snan:
377        bra     src_nan
378srem_dnan:
379        bra     dst_nan
380srem_oper:
381        bra     t_operr
382srem_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
389srem_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       
394srem_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
401srem_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
406srem_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//
413pscalet:
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
434pscale:
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
453scl_opr:
454        bra     t_operr
455
456scl_dnan:
457        bra     dst_nan
458
459scl_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
463scl_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
467scl_snan:
468        bra     src_nan
469//
470//      FSINCOS
471//
472        .global ssincosz
473ssincosz:
474        btstb   #sign_bit,ETEMP(%a6)    //get sign
475        beqs    sincosp
476        fmovex  MZERO,%fp0
477        bras    sincoscom
478sincosp:
479        fmovex PZERO,%fp0
480sincoscom:
481        fmovemx PONE,%fp1-%fp1  //do not allow FPSR to be affected
482        bra     sto_cos         //store cosine result
483
484        .global ssincosi
485ssincosi:
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
492ssincosnan:
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
507ld_ppi2:
508        fmovex PPIBY2,%fp0              //load +pi/2
509        bra     t_inx2                  //set inex2 exc
510
511//**Returns -PI/2
512        .global ld_mpi2
513ld_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
520ld_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
527ld_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
534ld_pone:
535        fmovex PONE,%fp0                //load +1
536        rts
537
538//**Returns -1
539        .global ld_mone
540ld_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
547ld_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
554ld_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
Note: See TracBrowser for help on using the repository browser.