brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.9 KiB · aa4d404 Raw
277 lines · plain
1//===-- addsf3.S - Adds two single precision floating pointer numbers-----===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the __addsf3 (single precision floating pointer number10// addition with the IEEE-754 default rounding (to nearest, ties to even)11// function for the ARM Thumb1 ISA.12//13//===----------------------------------------------------------------------===//14 15#include "../assembly.h"16#define significandBits 2317#define typeWidth 3218 19	.syntax unified20	.text21  .thumb22  .p2align 223 24DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_fadd, __addsf3)25 26DEFINE_COMPILERRT_THUMB_FUNCTION(__addsf3)27  push {r4, r5, r6, r7, lr}28  // Get the absolute value of a and b.29  lsls r2, r0, #130  lsls r3, r1, #131  lsrs r2, r2, #1  // aAbs32  beq  LOCAL_LABEL(a_zero_nan_inf)33  lsrs r3, r3, #1  // bAbs34  beq  LOCAL_LABEL(zero_nan_inf)35 36  // Detect if a or b is infinity or Nan.37  lsrs r6, r2, #(significandBits)38  lsrs r7, r3, #(significandBits)39  cmp  r6, #0xFF40  beq  LOCAL_LABEL(zero_nan_inf)41  cmp  r7, #0xFF42  beq  LOCAL_LABEL(zero_nan_inf)43 44  // Swap Rep and Abs so that a and aAbs has the larger absolute value.45  cmp r2, r346  bhs LOCAL_LABEL(no_swap)47  movs r4, r048  movs r5, r249  movs r0, r150  movs r2, r351  movs r1, r452  movs r3, r553LOCAL_LABEL(no_swap):54 55  // Get the significands and shift them to give us round, guard and sticky.56  lsls r4, r0, #(typeWidth - significandBits)57  lsrs r4, r4, #(typeWidth - significandBits - 3) // aSignificand << 358  lsls r5, r1, #(typeWidth - significandBits)59  lsrs r5, r5, #(typeWidth - significandBits - 3) // bSignificand << 360 61  // Get the implicitBit.62  movs r6, #163  lsls r6, r6, #(significandBits + 3)64 65  // Get aExponent and set implicit bit if necessary.66  lsrs r2, r2, #(significandBits)67  beq LOCAL_LABEL(a_done_implicit_bit)68  orrs r4, r669LOCAL_LABEL(a_done_implicit_bit):70 71  // Get bExponent and set implicit bit if necessary.72  lsrs r3, r3, #(significandBits)73  beq LOCAL_LABEL(b_done_implicit_bit)74  orrs r5, r675LOCAL_LABEL(b_done_implicit_bit):76 77  // Get the difference in exponents.78  subs r6, r2, r379  beq LOCAL_LABEL(done_align)80 81  // If b is denormal, then a must be normal as align > 0, and we only need to82  // right shift bSignificand by (align - 1) bits.83  cmp  r3, #084  bne  1f85  subs r6, r6, #1861:87 88  // No longer needs bExponent. r3 is dead here.89  // Set sticky bits of b: sticky = bSignificand << (typeWidth - align).90  movs r3, #(typeWidth)91  subs r3, r3, r692  movs r7, r593  lsls r7, r394  beq 1f95  movs r7, #1961:97 98  // bSignificand = bSignificand >> align | sticky;99  lsrs r5, r6100  orrs r5, r7101  bne LOCAL_LABEL(done_align)102  movs r5, #1 //  sticky; b is known to be non-zero.103 104LOCAL_LABEL(done_align):105  // isSubtraction = (aRep ^ bRep) >> 31;106  movs r7, r0107  eors r7, r1108  lsrs r7, #31109  bne LOCAL_LABEL(do_substraction)110 111  // Same sign, do Addition.112 113  // aSignificand += bSignificand;114  adds r4, r4, r5115 116  // Check carry bit.117  movs r6, #1118  lsls r6, r6, #(significandBits + 3 + 1)119  movs r7, r4120  ands r7, r6121  beq LOCAL_LABEL(form_result)122  // If the addition carried up, we need to right-shift the result and123  // adjust the exponent.124  movs r7, r4125  movs r6, #1126  ands r7, r6 // sticky = aSignificand & 1;127  lsrs r4, #1128  orrs r4, r7  // result Significand129  adds r2, #1  // result Exponent130  // If we have overflowed the type, return +/- infinity.131  cmp  r2, 0xFF132  beq  LOCAL_LABEL(ret_inf)133 134LOCAL_LABEL(form_result):135  // Shift the sign, exponent and significand into place.136  lsrs r0, #(typeWidth - 1)137  lsls r0, #(typeWidth - 1) // Get Sign.138  lsls r2, #(significandBits)139  orrs r0, r2140  movs r1, r4141  lsls r4, #(typeWidth - significandBits - 3)142  lsrs r4, #(typeWidth - significandBits)143  orrs r0, r4144 145  // Final rounding.  The result may overflow to infinity, but that is the146  // correct result in that case.147  // roundGuardSticky = aSignificand & 0x7;148  movs r2, #0x7149  ands r1, r2150  // if (roundGuardSticky > 0x4) result++;151 152  cmp r1, #0x4153  blt LOCAL_LABEL(done_round)154  beq 1f155  adds r0, #1156  pop {r4, r5, r6, r7, pc}1571:158 159  // if (roundGuardSticky == 0x4) result += result & 1;160  movs r1, r0161  lsrs r1, #1162  bcc  LOCAL_LABEL(done_round)163  adds r0, r0, #1164LOCAL_LABEL(done_round):165  pop {r4, r5, r6, r7, pc}166 167LOCAL_LABEL(do_substraction):168  subs r4, r4, r5 // aSignificand -= bSignificand;169  beq  LOCAL_LABEL(ret_zero)170  movs r6, r4171  cmp  r2, 0172  beq  LOCAL_LABEL(form_result) // if a's exp is 0, no need to normalize.173  // If partial cancellation occured, we need to left-shift the result174  // and adjust the exponent:175  lsrs r6, r6, #(significandBits + 3)176  bne LOCAL_LABEL(form_result)177 178  push {r0, r1, r2, r3}179  movs r0, r4180  bl   SYMBOL_NAME(__clzsi2)181  movs r5, r0182  pop {r0, r1, r2, r3}183  // shift = rep_clz(aSignificand) - rep_clz(implicitBit << 3);184  subs r5, r5, #(typeWidth - significandBits - 3 - 1)185  // aSignificand <<= shift; aExponent -= shift;186  lsls r4, r5187  subs  r2, r2, r5188  bgt LOCAL_LABEL(form_result)189 190  // Do normalization if aExponent <= 0.191  movs r6, #1192  subs r6, r6, r2 // 1 - aExponent;193  movs r2, #0 // aExponent = 0;194  movs r3, #(typeWidth) // bExponent is dead.195  subs r3, r3, r6196  movs r7, r4197  lsls r7, r3  // stickyBit = (bool)(aSignificant << (typeWidth - align))198  beq 1f199  movs r7, #12001:201  lsrs r4, r6 // aSignificand >> shift202  orrs r4, r7203  b LOCAL_LABEL(form_result)204 205LOCAL_LABEL(ret_zero):206  movs r0, #0207  pop {r4, r5, r6, r7, pc}208 209 210LOCAL_LABEL(a_zero_nan_inf):211  lsrs r3, r3, #1212 213LOCAL_LABEL(zero_nan_inf):214  // Here  r2 has aAbs, r3 has bAbs215  movs r4, #0xFF216  lsls r4, r4, #(significandBits) // Make +inf.217 218  cmp r2, r4219  bhi LOCAL_LABEL(a_is_nan)220  cmp r3, r4221  bhi LOCAL_LABEL(b_is_nan)222 223  cmp r2, r4224  bne LOCAL_LABEL(a_is_rational)225  // aAbs is INF.226  eors r1, r0 // aRep ^ bRep.227  movs r6, #1228  lsls r6, r6, #(typeWidth - 1) // get sign mask.229  cmp r1, r6 // if they only differ on sign bit, it's -INF + INF230  beq LOCAL_LABEL(a_is_nan)231  pop {r4, r5, r6, r7, pc}232 233LOCAL_LABEL(a_is_rational):234  cmp r3, r4235  bne LOCAL_LABEL(b_is_rational)236  movs r0, r1237  pop {r4, r5, r6, r7, pc}238 239LOCAL_LABEL(b_is_rational):240  // either a or b or both are zero.241  adds r4, r2, r3242  beq  LOCAL_LABEL(both_zero)243  cmp r2, #0 // is absA 0 ?244  beq LOCAL_LABEL(ret_b)245  pop {r4, r5, r6, r7, pc}246 247LOCAL_LABEL(both_zero):248  ands r0, r1 // +0 + -0 = +0249  pop {r4, r5, r6, r7, pc}250 251LOCAL_LABEL(ret_b):252  movs r0, r1253 254LOCAL_LABEL(ret):255  pop {r4, r5, r6, r7, pc}256 257LOCAL_LABEL(b_is_nan):258  movs r0, r1259LOCAL_LABEL(a_is_nan):260  movs r1, #1261  lsls r1, r1, #(significandBits -1) // r1 is quiet bit.262  orrs r0, r1263  pop {r4, r5, r6, r7, pc}264 265LOCAL_LABEL(ret_inf):266  movs r4, #0xFF267  lsls r4, r4, #(significandBits)268  orrs r0, r4269  lsrs r0, r0, #(significandBits)270  lsls r0, r0, #(significandBits)271  pop {r4, r5, r6, r7, pc}272 273 274END_COMPILERRT_FUNCTION(__addsf3)275 276NO_EXEC_STACK_DIRECTIVE277