source: rtems/c/src/lib/libcpu/m68k/m68040/fpsp/do_func.S @ 5321250

4.104.114.84.95
Last change on this file since 5321250 was 54f440d, checked in by Joel Sherrill <joel.sherrill@…>, on 07/26/99 at 22:11:02

Patch from Charles-Antoine Gauthier <charles.gauthier@…>.
to address m68k-rtemself for the MVME167.

Here is the rtems patch I promissed you a long time ago to enable ELF
with m68k. The target name I selected is m68k-rtemself. It preserves the
m68k-rtems COFF target, and is parterned after the other ELF/COFF dual
targets.

The mvme167.cfg file causes the -qelf flag to be used during compilation
if the name of the compiler contains rtemself. This flag is used in the
bsp_specs file to select the elflinkcmds file rather than the linkcmds
file. The former is for ELF, the latter for COFF.

Some patches are required to the mc68040 FPSP code. Some of the
assembler files contain instructions that were rejected by the
m68k-rtemself-as assembler. This is a minor bug in the m68k ELF
assembler, I think.

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