root/arch/m68k/fpsp040/do_func.S

/* [previous][next][first][last][top][bottom][index][help] */
   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         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
  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

/* [previous][next][first][last][top][bottom][index][help] */