source: rtems/bsps/m68k/shared/fpsp/do_func.S @ d584269

5
Last change on this file since d584269 was 3cf2bf63, checked in by Sebastian Huber <sebastian.huber@…>, on 03/26/18 at 10:17:06

bsps/m68k: Move fpsp support to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 13.9 KB
Line 
1#include "fpsp-namespace.h"
2//
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.