1*0b57cec5SDimitry Andric//===----------------------Hexagon builtin routine ------------------------===// 2*0b57cec5SDimitry Andric// 3*0b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric// 7*0b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric#define A r1:0 10*0b57cec5SDimitry Andric#define B r3:2 11*0b57cec5SDimitry Andric#define ATMP r5:4 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric 14*0b57cec5SDimitry Andric#define Q6_ALIAS(TAG) .global __qdsp_##TAG ; .set __qdsp_##TAG, __hexagon_##TAG 15*0b57cec5SDimitry Andric#define END(TAG) .size TAG,.-TAG 16*0b57cec5SDimitry Andric 17*0b57cec5SDimitry Andric// Min and Max return A if B is NaN, or B if A is NaN 18*0b57cec5SDimitry Andric// Otherwise, they return the smaller or bigger value 19*0b57cec5SDimitry Andric// 20*0b57cec5SDimitry Andric// If values are equal, we want to favor -0.0 for min and +0.0 for max. 21*0b57cec5SDimitry Andric 22*0b57cec5SDimitry Andric// Compares always return false for NaN 23*0b57cec5SDimitry Andric// if (isnan(A)) A = B; if (A > B) A = B will only trigger at most one of those options. 24*0b57cec5SDimitry Andric 25*0b57cec5SDimitry Andric .text 26*0b57cec5SDimitry Andric .global __hexagon_mindf3 27*0b57cec5SDimitry Andric .global __hexagon_maxdf3 28*0b57cec5SDimitry Andric .global fmin 29*0b57cec5SDimitry Andric .type fmin,@function 30*0b57cec5SDimitry Andric .global fmax 31*0b57cec5SDimitry Andric .type fmax,@function 32*0b57cec5SDimitry Andric .type __hexagon_mindf3,@function 33*0b57cec5SDimitry Andric .type __hexagon_maxdf3,@function 34*0b57cec5SDimitry Andric Q6_ALIAS(mindf3) 35*0b57cec5SDimitry Andric Q6_ALIAS(maxdf3) 36*0b57cec5SDimitry Andric .p2align 5 37*0b57cec5SDimitry Andric__hexagon_mindf3: 38*0b57cec5SDimitry Andricfmin: 39*0b57cec5SDimitry Andric { 40*0b57cec5SDimitry Andric p0 = dfclass(A,#0x10) // If A is a number 41*0b57cec5SDimitry Andric p1 = dfcmp.gt(A,B) // AND B > A, don't swap 42*0b57cec5SDimitry Andric ATMP = A 43*0b57cec5SDimitry Andric } 44*0b57cec5SDimitry Andric { 45*0b57cec5SDimitry Andric if (p0) A = B // if A is NaN use B 46*0b57cec5SDimitry Andric if (p1) A = B // gt is always false if either is NaN 47*0b57cec5SDimitry Andric p2 = dfcmp.eq(A,B) // if A == B 48*0b57cec5SDimitry Andric if (!p2.new) jumpr:t r31 49*0b57cec5SDimitry Andric } 50*0b57cec5SDimitry Andric // A == B, return A|B to select -0.0 over 0.0 51*0b57cec5SDimitry Andric { 52*0b57cec5SDimitry Andric A = or(ATMP,B) 53*0b57cec5SDimitry Andric jumpr r31 54*0b57cec5SDimitry Andric } 55*0b57cec5SDimitry AndricEND(__hexagon_mindf3) 56*0b57cec5SDimitry Andric .falign 57*0b57cec5SDimitry Andric__hexagon_maxdf3: 58*0b57cec5SDimitry Andricfmax: 59*0b57cec5SDimitry Andric { 60*0b57cec5SDimitry Andric p0 = dfclass(A,#0x10) 61*0b57cec5SDimitry Andric p1 = dfcmp.gt(B,A) 62*0b57cec5SDimitry Andric ATMP = A 63*0b57cec5SDimitry Andric } 64*0b57cec5SDimitry Andric { 65*0b57cec5SDimitry Andric if (p0) A = B 66*0b57cec5SDimitry Andric if (p1) A = B 67*0b57cec5SDimitry Andric p2 = dfcmp.eq(A,B) 68*0b57cec5SDimitry Andric if (!p2.new) jumpr:t r31 69*0b57cec5SDimitry Andric } 70*0b57cec5SDimitry Andric // A == B, return A&B to select 0.0 over -0.0 71*0b57cec5SDimitry Andric { 72*0b57cec5SDimitry Andric A = and(ATMP,B) 73*0b57cec5SDimitry Andric jumpr r31 74*0b57cec5SDimitry Andric } 75*0b57cec5SDimitry AndricEND(__hexagon_maxdf3) 76