root/arch/m68k/fpsp040/scale.S

/* [<][>][^][v][top][bottom][index][help] */
   1 |
   2 |       scale.sa 3.3 7/30/91
   3 |
   4 |       The entry point sSCALE computes the destination operand
   5 |       scaled by the source operand.  If the absolute value of
   6 |       the source operand is (>= 2^14) an overflow or underflow
   7 |       is returned.
   8 |
   9 |       The entry point sscale is called from do_func to emulate
  10 |       the fscale unimplemented instruction.
  11 |
  12 |       Input: Double-extended destination operand in FPTEMP,
  13 |               double-extended source operand in ETEMP.
  14 |
  15 |       Output: The function returns scale(X,Y) to fp0.
  16 |
  17 |       Modifies: fp0.
  18 |
  19 |       Algorithm:
  20 |
  21 |               Copyright (C) Motorola, Inc. 1990
  22 |                       All Rights Reserved
  23 |
  24 |       For details on the license for this file, please see the
  25 |       file, README, in this same directory.
  26 
  27 |SCALE    idnt    2,1 | Motorola 040 Floating Point Software Package
  28 
  29         |section        8
  30 
  31 #include "fpsp.h"
  32 
  33         |xref   t_ovfl2
  34         |xref   t_unfl
  35         |xref   round
  36         |xref   t_resdnrm
  37 
  38 SRC_BNDS: .short        0x3fff,0x400c
  39 
  40 |
  41 | This entry point is used by the unimplemented instruction exception
  42 | handler.
  43 |
  44 |
  45 |
  46 |       FSCALE
  47 |
  48         .global sscale
  49 sscale:
  50         fmovel          #0,%fpcr                |clr user enabled exc
  51         clrl            %d1
  52         movew           FPTEMP(%a6),%d1 |get dest exponent
  53         smi             L_SCR1(%a6)     |use L_SCR1 to hold sign
  54         andil           #0x7fff,%d1     |strip sign
  55         movew           ETEMP(%a6),%d0  |check src bounds
  56         andiw           #0x7fff,%d0     |clr sign bit
  57         cmp2w           SRC_BNDS,%d0
  58         bccs            src_in
  59         cmpiw           #0x400c,%d0     |test for too large
  60         bge             src_out
  61 |
  62 | The source input is below 1, so we check for denormalized numbers
  63 | and set unfl.
  64 |
  65 src_small:
  66         moveb           DTAG(%a6),%d0
  67         andib           #0xe0,%d0
  68         tstb            %d0
  69         beqs            no_denorm
  70         st              STORE_FLG(%a6)  |dest already contains result
  71         orl             #unfl_mask,USER_FPSR(%a6) |set UNFL
  72 den_done:
  73         leal            FPTEMP(%a6),%a0
  74         bra             t_resdnrm
  75 no_denorm:
  76         fmovel          USER_FPCR(%a6),%FPCR
  77         fmovex          FPTEMP(%a6),%fp0        |simply return dest
  78         rts
  79 
  80 
  81 |
  82 | Source is within 2^14 range.  To perform the int operation,
  83 | move it to d0.
  84 |
  85 src_in:
  86         fmovex          ETEMP(%a6),%fp0 |move in src for int
  87         fmovel          #rz_mode,%fpcr  |force rz for src conversion
  88         fmovel          %fp0,%d0                |int src to d0
  89         fmovel          #0,%FPSR                |clr status from above
  90         tstw            ETEMP(%a6)      |check src sign
  91         blt             src_neg
  92 |
  93 | Source is positive.  Add the src to the dest exponent.
  94 | The result can be denormalized, if src = 0, or overflow,
  95 | if the result of the add sets a bit in the upper word.
  96 |
  97 src_pos:
  98         tstw            %d1             |check for denorm
  99         beq             dst_dnrm
 100         addl            %d0,%d1         |add src to dest exp
 101         beqs            denorm          |if zero, result is denorm
 102         cmpil           #0x7fff,%d1     |test for overflow
 103         bges            ovfl
 104         tstb            L_SCR1(%a6)
 105         beqs            spos_pos
 106         orw             #0x8000,%d1
 107 spos_pos:
 108         movew           %d1,FPTEMP(%a6) |result in FPTEMP
 109         fmovel          USER_FPCR(%a6),%FPCR
 110         fmovex          FPTEMP(%a6),%fp0        |write result to fp0
 111         rts
 112 ovfl:
 113         tstb            L_SCR1(%a6)
 114         beqs            sovl_pos
 115         orw             #0x8000,%d1
 116 sovl_pos:
 117         movew           FPTEMP(%a6),ETEMP(%a6)  |result in ETEMP
 118         movel           FPTEMP_HI(%a6),ETEMP_HI(%a6)
 119         movel           FPTEMP_LO(%a6),ETEMP_LO(%a6)
 120         bra             t_ovfl2
 121 
 122 denorm:
 123         tstb            L_SCR1(%a6)
 124         beqs            den_pos
 125         orw             #0x8000,%d1
 126 den_pos:
 127         tstl            FPTEMP_HI(%a6)  |check j bit
 128         blts            nden_exit       |if set, not denorm
 129         movew           %d1,ETEMP(%a6)  |input expected in ETEMP
 130         movel           FPTEMP_HI(%a6),ETEMP_HI(%a6)
 131         movel           FPTEMP_LO(%a6),ETEMP_LO(%a6)
 132         orl             #unfl_bit,USER_FPSR(%a6)        |set unfl
 133         leal            ETEMP(%a6),%a0
 134         bra             t_resdnrm
 135 nden_exit:
 136         movew           %d1,FPTEMP(%a6) |result in FPTEMP
 137         fmovel          USER_FPCR(%a6),%FPCR
 138         fmovex          FPTEMP(%a6),%fp0        |write result to fp0
 139         rts
 140 
 141 |
 142 | Source is negative.  Add the src to the dest exponent.
 143 | (The result exponent will be reduced).  The result can be
 144 | denormalized.
 145 |
 146 src_neg:
 147         addl            %d0,%d1         |add src to dest
 148         beqs            denorm          |if zero, result is denorm
 149         blts            fix_dnrm        |if negative, result is
 150 |                                       ;needing denormalization
 151         tstb            L_SCR1(%a6)
 152         beqs            sneg_pos
 153         orw             #0x8000,%d1
 154 sneg_pos:
 155         movew           %d1,FPTEMP(%a6) |result in FPTEMP
 156         fmovel          USER_FPCR(%a6),%FPCR
 157         fmovex          FPTEMP(%a6),%fp0        |write result to fp0
 158         rts
 159 
 160 
 161 |
 162 | The result exponent is below denorm value.  Test for catastrophic
 163 | underflow and force zero if true.  If not, try to shift the
 164 | mantissa right until a zero exponent exists.
 165 |
 166 fix_dnrm:
 167         cmpiw           #0xffc0,%d1     |lower bound for normalization
 168         blt             fix_unfl        |if lower, catastrophic unfl
 169         movew           %d1,%d0         |use d0 for exp
 170         movel           %d2,-(%a7)      |free d2 for norm
 171         movel           FPTEMP_HI(%a6),%d1
 172         movel           FPTEMP_LO(%a6),%d2
 173         clrl            L_SCR2(%a6)
 174 fix_loop:
 175         addw            #1,%d0          |drive d0 to 0
 176         lsrl            #1,%d1          |while shifting the
 177         roxrl           #1,%d2          |mantissa to the right
 178         bccs            no_carry
 179         st              L_SCR2(%a6)     |use L_SCR2 to capture inex
 180 no_carry:
 181         tstw            %d0             |it is finished when
 182         blts            fix_loop        |d0 is zero or the mantissa
 183         tstb            L_SCR2(%a6)
 184         beqs            tst_zero
 185         orl             #unfl_inx_mask,USER_FPSR(%a6)
 186 |                                       ;set unfl, aunfl, ainex
 187 |
 188 | Test for zero. If zero, simply use fmove to return +/- zero
 189 | to the fpu.
 190 |
 191 tst_zero:
 192         clrw            FPTEMP_EX(%a6)
 193         tstb            L_SCR1(%a6)     |test for sign
 194         beqs            tst_con
 195         orw             #0x8000,FPTEMP_EX(%a6) |set sign bit
 196 tst_con:
 197         movel           %d1,FPTEMP_HI(%a6)
 198         movel           %d2,FPTEMP_LO(%a6)
 199         movel           (%a7)+,%d2
 200         tstl            %d1
 201         bnes            not_zero
 202         tstl            FPTEMP_LO(%a6)
 203         bnes            not_zero
 204 |
 205 | Result is zero.  Check for rounding mode to set lsb.  If the
 206 | mode is rp, and the zero is positive, return smallest denorm.
 207 | If the mode is rm, and the zero is negative, return smallest
 208 | negative denorm.
 209 |
 210         btstb           #5,FPCR_MODE(%a6) |test if rm or rp
 211         beqs            no_dir
 212         btstb           #4,FPCR_MODE(%a6) |check which one
 213         beqs            zer_rm
 214 zer_rp:
 215         tstb            L_SCR1(%a6)     |check sign
 216         bnes            no_dir          |if set, neg op, no inc
 217         movel           #1,FPTEMP_LO(%a6) |set lsb
 218         bras            sm_dnrm
 219 zer_rm:
 220         tstb            L_SCR1(%a6)     |check sign
 221         beqs            no_dir          |if clr, neg op, no inc
 222         movel           #1,FPTEMP_LO(%a6) |set lsb
 223         orl             #neg_mask,USER_FPSR(%a6) |set N
 224         bras            sm_dnrm
 225 no_dir:
 226         fmovel          USER_FPCR(%a6),%FPCR
 227         fmovex          FPTEMP(%a6),%fp0        |use fmove to set cc's
 228         rts
 229 
 230 |
 231 | The rounding mode changed the zero to a smallest denorm. Call
 232 | t_resdnrm with exceptional operand in ETEMP.
 233 |
 234 sm_dnrm:
 235         movel           FPTEMP_EX(%a6),ETEMP_EX(%a6)
 236         movel           FPTEMP_HI(%a6),ETEMP_HI(%a6)
 237         movel           FPTEMP_LO(%a6),ETEMP_LO(%a6)
 238         leal            ETEMP(%a6),%a0
 239         bra             t_resdnrm
 240 
 241 |
 242 | Result is still denormalized.
 243 |
 244 not_zero:
 245         orl             #unfl_mask,USER_FPSR(%a6) |set unfl
 246         tstb            L_SCR1(%a6)     |check for sign
 247         beqs            fix_exit
 248         orl             #neg_mask,USER_FPSR(%a6) |set N
 249 fix_exit:
 250         bras            sm_dnrm
 251 
 252 
 253 |
 254 | The result has underflowed to zero. Return zero and set
 255 | unfl, aunfl, and ainex.
 256 |
 257 fix_unfl:
 258         orl             #unfl_inx_mask,USER_FPSR(%a6)
 259         btstb           #5,FPCR_MODE(%a6) |test if rm or rp
 260         beqs            no_dir2
 261         btstb           #4,FPCR_MODE(%a6) |check which one
 262         beqs            zer_rm2
 263 zer_rp2:
 264         tstb            L_SCR1(%a6)     |check sign
 265         bnes            no_dir2         |if set, neg op, no inc
 266         clrl            FPTEMP_EX(%a6)
 267         clrl            FPTEMP_HI(%a6)
 268         movel           #1,FPTEMP_LO(%a6) |set lsb
 269         bras            sm_dnrm         |return smallest denorm
 270 zer_rm2:
 271         tstb            L_SCR1(%a6)     |check sign
 272         beqs            no_dir2         |if clr, neg op, no inc
 273         movew           #0x8000,FPTEMP_EX(%a6)
 274         clrl            FPTEMP_HI(%a6)
 275         movel           #1,FPTEMP_LO(%a6) |set lsb
 276         orl             #neg_mask,USER_FPSR(%a6) |set N
 277         bra             sm_dnrm         |return smallest denorm
 278 
 279 no_dir2:
 280         tstb            L_SCR1(%a6)
 281         bges            pos_zero
 282 neg_zero:
 283         clrl            FP_SCR1(%a6)    |clear the exceptional operand
 284         clrl            FP_SCR1+4(%a6)  |for gen_except.
 285         clrl            FP_SCR1+8(%a6)
 286         fmoves          #0x80000000,%fp0
 287         rts
 288 pos_zero:
 289         clrl            FP_SCR1(%a6)    |clear the exceptional operand
 290         clrl            FP_SCR1+4(%a6)  |for gen_except.
 291         clrl            FP_SCR1+8(%a6)
 292         fmoves          #0x00000000,%fp0
 293         rts
 294 
 295 |
 296 | The destination is a denormalized number.  It must be handled
 297 | by first shifting the bits in the mantissa until it is normalized,
 298 | then adding the remainder of the source to the exponent.
 299 |
 300 dst_dnrm:
 301         moveml          %d2/%d3,-(%a7)
 302         movew           FPTEMP_EX(%a6),%d1
 303         movel           FPTEMP_HI(%a6),%d2
 304         movel           FPTEMP_LO(%a6),%d3
 305 dst_loop:
 306         tstl            %d2             |test for normalized result
 307         blts            dst_norm        |exit loop if so
 308         tstl            %d0             |otherwise, test shift count
 309         beqs            dst_fin         |if zero, shifting is done
 310         subil           #1,%d0          |dec src
 311         lsll            #1,%d3
 312         roxll           #1,%d2
 313         bras            dst_loop
 314 |
 315 | Destination became normalized.  Simply add the remaining
 316 | portion of the src to the exponent.
 317 |
 318 dst_norm:
 319         addw            %d0,%d1         |dst is normalized; add src
 320         tstb            L_SCR1(%a6)
 321         beqs            dnrm_pos
 322         orl             #0x8000,%d1
 323 dnrm_pos:
 324         movemw          %d1,FPTEMP_EX(%a6)
 325         moveml          %d2,FPTEMP_HI(%a6)
 326         moveml          %d3,FPTEMP_LO(%a6)
 327         fmovel          USER_FPCR(%a6),%FPCR
 328         fmovex          FPTEMP(%a6),%fp0
 329         moveml          (%a7)+,%d2/%d3
 330         rts
 331 
 332 |
 333 | Destination remained denormalized.  Call t_excdnrm with
 334 | exceptional operand in ETEMP.
 335 |
 336 dst_fin:
 337         tstb            L_SCR1(%a6)     |check for sign
 338         beqs            dst_exit
 339         orl             #neg_mask,USER_FPSR(%a6) |set N
 340         orl             #0x8000,%d1
 341 dst_exit:
 342         movemw          %d1,ETEMP_EX(%a6)
 343         moveml          %d2,ETEMP_HI(%a6)
 344         moveml          %d3,ETEMP_LO(%a6)
 345         orl             #unfl_mask,USER_FPSR(%a6) |set unfl
 346         moveml          (%a7)+,%d2/%d3
 347         leal            ETEMP(%a6),%a0
 348         bra             t_resdnrm
 349 
 350 |
 351 | Source is outside of 2^14 range.  Test the sign and branch
 352 | to the appropriate exception handler.
 353 |
 354 src_out:
 355         tstb            L_SCR1(%a6)
 356         beqs            scro_pos
 357         orl             #0x8000,%d1
 358 scro_pos:
 359         movel           FPTEMP_HI(%a6),ETEMP_HI(%a6)
 360         movel           FPTEMP_LO(%a6),ETEMP_LO(%a6)
 361         tstw            ETEMP(%a6)
 362         blts            res_neg
 363 res_pos:
 364         movew           %d1,ETEMP(%a6)  |result in ETEMP
 365         bra             t_ovfl2
 366 res_neg:
 367         movew           %d1,ETEMP(%a6)  |result in ETEMP
 368         leal            ETEMP(%a6),%a0
 369         bra             t_unfl
 370         |end

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