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