1*0a6a1f1dSLionel Sambuc//===-- comparesf2.S - Implement single-precision soft-float comparisons --===// 2*0a6a1f1dSLionel Sambuc// 3*0a6a1f1dSLionel Sambuc// The LLVM Compiler Infrastructure 4*0a6a1f1dSLionel Sambuc// 5*0a6a1f1dSLionel Sambuc// This file is dual licensed under the MIT and the University of Illinois Open 6*0a6a1f1dSLionel Sambuc// Source Licenses. See LICENSE.TXT for details. 7*0a6a1f1dSLionel Sambuc// 8*0a6a1f1dSLionel Sambuc//===----------------------------------------------------------------------===// 9*0a6a1f1dSLionel Sambuc// 10*0a6a1f1dSLionel Sambuc// This file implements the following soft-fp_t comparison routines: 11*0a6a1f1dSLionel Sambuc// 12*0a6a1f1dSLionel Sambuc// __eqsf2 __gesf2 __unordsf2 13*0a6a1f1dSLionel Sambuc// __lesf2 __gtsf2 14*0a6a1f1dSLionel Sambuc// __ltsf2 15*0a6a1f1dSLionel Sambuc// __nesf2 16*0a6a1f1dSLionel Sambuc// 17*0a6a1f1dSLionel Sambuc// The semantics of the routines grouped in each column are identical, so there 18*0a6a1f1dSLionel Sambuc// is a single implementation for each, with multiple names. 19*0a6a1f1dSLionel Sambuc// 20*0a6a1f1dSLionel Sambuc// The routines behave as follows: 21*0a6a1f1dSLionel Sambuc// 22*0a6a1f1dSLionel Sambuc// __lesf2(a,b) returns -1 if a < b 23*0a6a1f1dSLionel Sambuc// 0 if a == b 24*0a6a1f1dSLionel Sambuc// 1 if a > b 25*0a6a1f1dSLionel Sambuc// 1 if either a or b is NaN 26*0a6a1f1dSLionel Sambuc// 27*0a6a1f1dSLionel Sambuc// __gesf2(a,b) returns -1 if a < b 28*0a6a1f1dSLionel Sambuc// 0 if a == b 29*0a6a1f1dSLionel Sambuc// 1 if a > b 30*0a6a1f1dSLionel Sambuc// -1 if either a or b is NaN 31*0a6a1f1dSLionel Sambuc// 32*0a6a1f1dSLionel Sambuc// __unordsf2(a,b) returns 0 if both a and b are numbers 33*0a6a1f1dSLionel Sambuc// 1 if either a or b is NaN 34*0a6a1f1dSLionel Sambuc// 35*0a6a1f1dSLionel Sambuc// Note that __lesf2( ) and __gesf2( ) are identical except in their handling of 36*0a6a1f1dSLionel Sambuc// NaN values. 37*0a6a1f1dSLionel Sambuc// 38*0a6a1f1dSLionel Sambuc//===----------------------------------------------------------------------===// 39*0a6a1f1dSLionel Sambuc 40*0a6a1f1dSLionel Sambuc#include "../assembly.h" 41*0a6a1f1dSLionel Sambuc.syntax unified 42*0a6a1f1dSLionel Sambuc 43*0a6a1f1dSLionel Sambuc.p2align 2 44*0a6a1f1dSLionel SambucDEFINE_COMPILERRT_FUNCTION(__eqsf2) 45*0a6a1f1dSLionel Sambuc // Make copies of a and b with the sign bit shifted off the top. These will 46*0a6a1f1dSLionel Sambuc // be used to detect zeros and NaNs. 47*0a6a1f1dSLionel Sambuc mov r2, r0, lsl #1 48*0a6a1f1dSLionel Sambuc mov r3, r1, lsl #1 49*0a6a1f1dSLionel Sambuc 50*0a6a1f1dSLionel Sambuc // We do the comparison in three stages (ignoring NaN values for the time 51*0a6a1f1dSLionel Sambuc // being). First, we orr the absolute values of a and b; this sets the Z 52*0a6a1f1dSLionel Sambuc // flag if both a and b are zero (of either sign). The shift of r3 doesn't 53*0a6a1f1dSLionel Sambuc // effect this at all, but it *does* make sure that the C flag is clear for 54*0a6a1f1dSLionel Sambuc // the subsequent operations. 55*0a6a1f1dSLionel Sambuc orrs r12, r2, r3, lsr #1 56*0a6a1f1dSLionel Sambuc 57*0a6a1f1dSLionel Sambuc // Next, we check if a and b have the same or different signs. If they have 58*0a6a1f1dSLionel Sambuc // opposite signs, this eor will set the N flag. 59*0a6a1f1dSLionel Sambuc it ne 60*0a6a1f1dSLionel Sambuc eorsne r12, r0, r1 61*0a6a1f1dSLionel Sambuc 62*0a6a1f1dSLionel Sambuc // If a and b are equal (either both zeros or bit identical; again, we're 63*0a6a1f1dSLionel Sambuc // ignoring NaNs for now), this subtract will zero out r0. If they have the 64*0a6a1f1dSLionel Sambuc // same sign, the flags are updated as they would be for a comparison of the 65*0a6a1f1dSLionel Sambuc // absolute values of a and b. 66*0a6a1f1dSLionel Sambuc it pl 67*0a6a1f1dSLionel Sambuc subspl r0, r2, r3 68*0a6a1f1dSLionel Sambuc 69*0a6a1f1dSLionel Sambuc // If a is smaller in magnitude than b and both have the same sign, place 70*0a6a1f1dSLionel Sambuc // the negation of the sign of b in r0. Thus, if both are negative and 71*0a6a1f1dSLionel Sambuc // a > b, this sets r0 to 0; if both are positive and a < b, this sets 72*0a6a1f1dSLionel Sambuc // r0 to -1. 73*0a6a1f1dSLionel Sambuc // 74*0a6a1f1dSLionel Sambuc // This is also done if a and b have opposite signs and are not both zero, 75*0a6a1f1dSLionel Sambuc // because in that case the subtract was not performed and the C flag is 76*0a6a1f1dSLionel Sambuc // still clear from the shift argument in orrs; if a is positive and b 77*0a6a1f1dSLionel Sambuc // negative, this places 0 in r0; if a is negative and b positive, -1 is 78*0a6a1f1dSLionel Sambuc // placed in r0. 79*0a6a1f1dSLionel Sambuc it lo 80*0a6a1f1dSLionel Sambuc mvnlo r0, r1, asr #31 81*0a6a1f1dSLionel Sambuc 82*0a6a1f1dSLionel Sambuc // If a is greater in magnitude than b and both have the same sign, place 83*0a6a1f1dSLionel Sambuc // the sign of b in r0. Thus, if both are negative and a < b, -1 is placed 84*0a6a1f1dSLionel Sambuc // in r0, which is the desired result. Conversely, if both are positive 85*0a6a1f1dSLionel Sambuc // and a > b, zero is placed in r0. 86*0a6a1f1dSLionel Sambuc it hi 87*0a6a1f1dSLionel Sambuc movhi r0, r1, asr #31 88*0a6a1f1dSLionel Sambuc 89*0a6a1f1dSLionel Sambuc // If you've been keeping track, at this point r0 contains -1 if a < b and 90*0a6a1f1dSLionel Sambuc // 0 if a >= b. All that remains to be done is to set it to 1 if a > b. 91*0a6a1f1dSLionel Sambuc // If a == b, then the Z flag is set, so we can get the correct final value 92*0a6a1f1dSLionel Sambuc // into r0 by simply or'ing with 1 if Z is clear. 93*0a6a1f1dSLionel Sambuc it ne 94*0a6a1f1dSLionel Sambuc orrne r0, r0, #1 95*0a6a1f1dSLionel Sambuc 96*0a6a1f1dSLionel Sambuc // Finally, we need to deal with NaNs. If either argument is NaN, replace 97*0a6a1f1dSLionel Sambuc // the value in r0 with 1. 98*0a6a1f1dSLionel Sambuc cmp r2, #0xff000000 99*0a6a1f1dSLionel Sambuc ite ls 100*0a6a1f1dSLionel Sambuc cmpls r3, #0xff000000 101*0a6a1f1dSLionel Sambuc movhi r0, #1 102*0a6a1f1dSLionel Sambuc JMP(lr) 103*0a6a1f1dSLionel SambucEND_COMPILERRT_FUNCTION(__eqsf2) 104*0a6a1f1dSLionel SambucDEFINE_COMPILERRT_FUNCTION_ALIAS(__lesf2, __eqsf2) 105*0a6a1f1dSLionel SambucDEFINE_COMPILERRT_FUNCTION_ALIAS(__ltsf2, __eqsf2) 106*0a6a1f1dSLionel SambucDEFINE_COMPILERRT_FUNCTION_ALIAS(__nesf2, __eqsf2) 107*0a6a1f1dSLionel Sambuc 108*0a6a1f1dSLionel Sambuc.p2align 2 109*0a6a1f1dSLionel SambucDEFINE_COMPILERRT_FUNCTION(__gtsf2) 110*0a6a1f1dSLionel Sambuc // Identical to the preceding except in that we return -1 for NaN values. 111*0a6a1f1dSLionel Sambuc // Given that the two paths share so much code, one might be tempted to 112*0a6a1f1dSLionel Sambuc // unify them; however, the extra code needed to do so makes the code size 113*0a6a1f1dSLionel Sambuc // to performance tradeoff very hard to justify for such small functions. 114*0a6a1f1dSLionel Sambuc mov r2, r0, lsl #1 115*0a6a1f1dSLionel Sambuc mov r3, r1, lsl #1 116*0a6a1f1dSLionel Sambuc orrs r12, r2, r3, lsr #1 117*0a6a1f1dSLionel Sambuc it ne 118*0a6a1f1dSLionel Sambuc eorsne r12, r0, r1 119*0a6a1f1dSLionel Sambuc it pl 120*0a6a1f1dSLionel Sambuc subspl r0, r2, r3 121*0a6a1f1dSLionel Sambuc it lo 122*0a6a1f1dSLionel Sambuc mvnlo r0, r1, asr #31 123*0a6a1f1dSLionel Sambuc it hi 124*0a6a1f1dSLionel Sambuc movhi r0, r1, asr #31 125*0a6a1f1dSLionel Sambuc it ne 126*0a6a1f1dSLionel Sambuc orrne r0, r0, #1 127*0a6a1f1dSLionel Sambuc cmp r2, #0xff000000 128*0a6a1f1dSLionel Sambuc ite ls 129*0a6a1f1dSLionel Sambuc cmpls r3, #0xff000000 130*0a6a1f1dSLionel Sambuc movhi r0, #-1 131*0a6a1f1dSLionel Sambuc JMP(lr) 132*0a6a1f1dSLionel SambucEND_COMPILERRT_FUNCTION(__gtsf2) 133*0a6a1f1dSLionel SambucDEFINE_COMPILERRT_FUNCTION_ALIAS(__gesf2, __gtsf2) 134*0a6a1f1dSLionel Sambuc 135*0a6a1f1dSLionel Sambuc.p2align 2 136*0a6a1f1dSLionel SambucDEFINE_COMPILERRT_FUNCTION(__unordsf2) 137*0a6a1f1dSLionel Sambuc // Return 1 for NaN values, 0 otherwise. 138*0a6a1f1dSLionel Sambuc mov r2, r0, lsl #1 139*0a6a1f1dSLionel Sambuc mov r3, r1, lsl #1 140*0a6a1f1dSLionel Sambuc mov r0, #0 141*0a6a1f1dSLionel Sambuc cmp r2, #0xff000000 142*0a6a1f1dSLionel Sambuc ite ls 143*0a6a1f1dSLionel Sambuc cmpls r3, #0xff000000 144*0a6a1f1dSLionel Sambuc movhi r0, #1 145*0a6a1f1dSLionel Sambuc JMP(lr) 146*0a6a1f1dSLionel SambucEND_COMPILERRT_FUNCTION(__unordsf2) 147*0a6a1f1dSLionel Sambuc 148*0a6a1f1dSLionel SambucDEFINE_AEABI_FUNCTION_ALIAS(__aeabi_fcmpun, __unordsf2) 149