root/arch/m68k/fpsp040/do_func.S

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

/* [<][>][^][v][top][bottom][index][help] */