root/arch/m68k/fpsp040/scale.S

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

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