brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.2 KiB · 24b85d2 Raw
262 lines · plain
1//===-- comparesf2.S - Implement single-precision soft-float comparisons --===//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 following soft-fp_t comparison routines:10//11//   __eqsf2   __gesf2   __unordsf212//   __lesf2   __gtsf213//   __ltsf214//   __nesf215//16// The semantics of the routines grouped in each column are identical, so there17// is a single implementation for each, with multiple names.18//19// The routines behave as follows:20//21//   __lesf2(a,b) returns -1 if a < b22//                         0 if a == b23//                         1 if a > b24//                         1 if either a or b is NaN25//26//   __gesf2(a,b) returns -1 if a < b27//                         0 if a == b28//                         1 if a > b29//                        -1 if either a or b is NaN30//31//   __unordsf2(a,b) returns 0 if both a and b are numbers32//                           1 if either a or b is NaN33//34// Note that __lesf2( ) and __gesf2( ) are identical except in their handling of35// NaN values.36//37//===----------------------------------------------------------------------===//38 39#include "../assembly.h"40 41    .syntax unified42    .text43    DEFINE_CODE_STATE44 45    .macro COMPARESF2_FUNCTION_BODY handle_nan:req46#if defined(COMPILER_RT_ARMHF_TARGET)47    vmov r0, s048    vmov r1, s149#endif50    // Make copies of a and b with the sign bit shifted off the top.  These will51    // be used to detect zeros and NaNs.52#if defined(USE_THUMB_1)53    push    {r6, lr}54    lsls    r2,         r0, #155    lsls    r3,         r1, #156#else57    mov     r2,         r0, lsl #158    mov     r3,         r1, lsl #159#endif60 61    // We do the comparison in three stages (ignoring NaN values for the time62    // being).  First, we orr the absolute values of a and b; this sets the Z63    // flag if both a and b are zero (of either sign).  The shift of r3 doesn't64    // effect this at all, but it *does* make sure that the C flag is clear for65    // the subsequent operations.66#if defined(USE_THUMB_1)67    lsrs    r6,     r3, #168    orrs    r6,     r269#else70    orrs    r12,    r2, r3, lsr #171#endif72    // Next, we check if a and b have the same or different signs.  If they have73    // opposite signs, this eor will set the N flag.74#if defined(USE_THUMB_1)75    beq     1f76    movs    r6,     r077    eors    r6,     r1781:79#else80    it ne81    eorsne  r12,    r0, r182#endif83 84    // If a and b are equal (either both zeros or bit identical; again, we're85    // ignoring NaNs for now), this subtract will zero out r0.  If they have the86    // same sign, the flags are updated as they would be for a comparison of the87    // absolute values of a and b.88#if defined(USE_THUMB_1)89    bmi     1f90    subs    r0,     r2, r3911:92#else93    it pl94    subspl  r0,     r2, r395#endif96 97    // If a is smaller in magnitude than b and both have the same sign, place98    // the negation of the sign of b in r0.  Thus, if both are negative and99    // a > b, this sets r0 to 0; if both are positive and a < b, this sets100    // r0 to -1.101    //102    // This is also done if a and b have opposite signs and are not both zero,103    // because in that case the subtract was not performed and the C flag is104    // still clear from the shift argument in orrs; if a is positive and b105    // negative, this places 0 in r0; if a is negative and b positive, -1 is106    // placed in r0.107#if defined(USE_THUMB_1)108    bhs     1f109    // Here if a and b have the same sign and absA < absB, the result is thus110    // b < 0 ? 1 : -1. Same if a and b have the opposite sign (ignoring Nan).111    movs    r0,         #1112    lsrs    r1,         #31113    bne     LOCAL_LABEL(CHECK_NAN\@)114    negs    r0,         r0115    b       LOCAL_LABEL(CHECK_NAN\@)1161:117#else118    it lo119    mvnlo   r0,         r1, asr #31120#endif121 122    // If a is greater in magnitude than b and both have the same sign, place123    // the sign of b in r0.  Thus, if both are negative and a < b, -1 is placed124    // in r0, which is the desired result.  Conversely, if both are positive125    // and a > b, zero is placed in r0.126#if defined(USE_THUMB_1)127    bls     1f128    // Here both have the same sign and absA > absB.129    movs    r0,         #1130    lsrs    r1,         #31131    beq     LOCAL_LABEL(CHECK_NAN\@)132    negs    r0, r01331:134#else135    it hi136    movhi   r0,         r1, asr #31137#endif138 139    // If you've been keeping track, at this point r0 contains -1 if a < b and140    // 0 if a >= b.  All that remains to be done is to set it to 1 if a > b.141    // If a == b, then the Z flag is set, so we can get the correct final value142    // into r0 by simply or'ing with 1 if Z is clear.143    // For Thumb-1, r0 contains -1 if a < b, 0 if a > b and 0 if a == b.144#if !defined(USE_THUMB_1)145    it ne146    orrne   r0,     r0, #1147#endif148 149    // Finally, we need to deal with NaNs.  If either argument is NaN, replace150    // the value in r0 with 1.151#if defined(USE_THUMB_1)152LOCAL_LABEL(CHECK_NAN\@):153    movs    r6,         #0xff154    lsls    r6,         #24155    cmp     r2,         r6156    bhi     1f157    cmp     r3,         r61581:159    bls     2f160    \handle_nan1612:162    pop     {r6, pc}163#else164    cmp     r2,         #0xff000000165    ite ls166    cmpls   r3,         #0xff000000167    \handle_nan168    JMP(lr)169#endif170    .endm171 172@ int __eqsf2(float a, float b)173 174    .p2align 2175DEFINE_COMPILERRT_FUNCTION(__eqsf2)176 177    .macro __eqsf2_handle_nan178#if defined(USE_THUMB_1)179    movs    r0,         #1180#else181    movhi   r0,         #1182#endif183    .endm184 185COMPARESF2_FUNCTION_BODY __eqsf2_handle_nan186 187END_COMPILERRT_FUNCTION(__eqsf2)188 189DEFINE_COMPILERRT_FUNCTION_ALIAS(__lesf2, __eqsf2)190DEFINE_COMPILERRT_FUNCTION_ALIAS(__ltsf2, __eqsf2)191DEFINE_COMPILERRT_FUNCTION_ALIAS(__nesf2, __eqsf2)192 193#if defined(__ELF__)194// Alias for libgcc compatibility195DEFINE_COMPILERRT_FUNCTION_ALIAS(__cmpsf2, __lesf2)196#endif197 198@ int __gtsf2(float a, float b)199 200    .p2align 2201DEFINE_COMPILERRT_FUNCTION(__gtsf2)202 203    .macro __gtsf2_handle_nan204#if defined(USE_THUMB_1)205    movs    r0,         #1206    negs    r0,         r0207#else208    movhi   r0,         #-1209#endif210    .endm211 212COMPARESF2_FUNCTION_BODY __gtsf2_handle_nan213 214END_COMPILERRT_FUNCTION(__gtsf2)215 216DEFINE_COMPILERRT_FUNCTION_ALIAS(__gesf2, __gtsf2)217 218@ int __unordsf2(float a, float b)219 220    .p2align 2221DEFINE_COMPILERRT_FUNCTION(__unordsf2)222 223#if defined(COMPILER_RT_ARMHF_TARGET)224    vmov    r0,         s0225    vmov    r1,         s1226#endif227    // Return 1 for NaN values, 0 otherwise.228    lsls    r2,         r0, #1229    lsls    r3,         r1, #1230    movs    r0,         #0231#if defined(USE_THUMB_1)232    movs    r1,         #0xff233    lsls    r1,         #24234    cmp     r2,         r1235    bhi     1f236    cmp     r3,         r12371:238    bls     2f239    movs    r0,         #12402:241#else242    cmp     r2,         #0xff000000243    ite ls244    cmpls   r3,         #0xff000000245    movhi   r0,         #1246#endif247    JMP(lr)248END_COMPILERRT_FUNCTION(__unordsf2)249 250#if defined(COMPILER_RT_ARMHF_TARGET)251DEFINE_COMPILERRT_FUNCTION(__aeabi_fcmpun)252	vmov s0, r0253	vmov s1, r1254	b SYMBOL_NAME(__unordsf2)255END_COMPILERRT_FUNCTION(__aeabi_fcmpun)256#else257DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_fcmpun, __unordsf2)258#endif259 260NO_EXEC_STACK_DIRECTIVE261 262