//===----------------------Hexagon builtin routine ------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
/* ==================================================================== */
/* FUNCTIONS Optimized double floating point operators */
/* ==================================================================== */
/* c = dadd_asm(a, b) */
/* ==================================================================== *
fast2_QDOUBLE fast2_dadd(fast2_QDOUBLE a,fast2_QDOUBLE b) {
fast2_QDOUBLE c;
lint manta = a & MANTMASK;
int expa = Q6_R_sxth_R(a) ;
lint mantb = b & MANTMASK;
int expb = Q6_R_sxth_R(b) ;
int exp, expdiff, j, k, hi, lo, cn;
lint mant;
expdiff = (int) Q6_P_vabsdiffh_PP(a, b);
expdiff = Q6_R_sxth_R(expdiff) ;
if (expdiff > 63) { expdiff = 62;}
if (expa > expb) {
exp = expa + 1;
expa = 1;
expb = expdiff + 1;
} else {
exp = expb + 1;
expb = 1;
expa = expdiff + 1;
}
mant = (manta>>expa) + (mantb>>expb);
hi = (int) (mant>>32);
lo = (int) (mant);
k = Q6_R_normamt_R(hi);
if(hi == 0 || hi == -1) k = 31+Q6_R_normamt_R(lo);
mant = (mant << k);
cn = (mant == 0x8000000000000000LL);
exp = exp - k + cn;
if (mant == 0 || mant == -1) exp = 0x8001;
c = (mant & MANTMASK) | (((lint) exp) & EXP_MASK);
return(c);
}
* ==================================================================== */
.text
.global fast2_dadd_asm
.type fast2_dadd_asm, @function
fast2_dadd_asm:
#define manta R0
#define mantexpa R1:0
#define lmanta R1:0
#define mantb R2
#define mantexpb R3:2
#define lmantb R3:2
#define expa R4
#define expb R5
#define mantexpd R7:6
#define expd R6
#define exp R8
#define c63 R9
#define lmant R1:0
#define manth R1
#define mantl R0
#define minmin R11:10 // exactly 0x000000000000008001LL
#define minminl R10
#define k R4
#define ce P0
.falign
{
mantexpd = VABSDIFFH(mantexpa, mantexpb) //represented as 0x08001LL
c63 = #62
expa = SXTH(manta)
expb = SXTH(mantb)
} {
expd = SXTH(expd)
ce = CMP.GT(expa, expb);
if ( ce.new) exp = add(expa, #1)
if (!ce.new) exp = add(expb, #1)
} {
if ( ce) expa = #1
if (!ce) expb = #1
manta.L = #0
expd = MIN(expd, c63)
} {
if (!ce) expa = add(expd, #1)
if ( ce) expb = add(expd, #1)
mantb.L = #0
minmin = #0
} {
lmanta = ASR(lmanta, expa)
lmantb = ASR(lmantb, expb)
} {
lmant = add(lmanta, lmantb)
minminl.L = #0x8001
} {
k = clb(lmant)
c63 = #58
} {
k = add(k, #-1)
p0 = cmp.gt(k, c63)
} {
mantexpa = ASL(lmant, k)
exp = SUB(exp, k)
if(p0) jump .Ldenorma
} {
manta = insert(exp, #16, #0)
jumpr r31
}
.Ldenorma:
{
mantexpa = minmin
jumpr r31
}
/* =================================================================== *
fast2_QDOUBLE fast2_dsub(fast2_QDOUBLE a,fast2_QDOUBLE b) {
fast2_QDOUBLE c;
lint manta = a & MANTMASK;
int expa = Q6_R_sxth_R(a) ;
lint mantb = b & MANTMASK;
int expb = Q6_R_sxth_R(b) ;
int exp, expdiff, j, k;
lint mant;
expdiff = (int) Q6_P_vabsdiffh_PP(a, b);
expdiff = Q6_R_sxth_R(expdiff) ;
if (expdiff > 63) { expdiff = 62;}
if (expa > expb) {
exp = expa + 1;
expa = 1;
expb = expdiff + 1;
} else {
exp = expb + 1;
expb = 1;
expa = expdiff + 1;
}
mant = (manta>>expa) - (mantb>>expb);
k = Q6_R_clb_P(mant)-1;
mant = (mant << k);
exp = exp - k;
if (mant == 0 || mant == -1) exp = 0x8001;
c = (mant & MANTMASK) | (((lint) exp) & EXP_MASK);
return(c);
}
* ==================================================================== */
.text
.global fast2_dsub_asm
.type fast2_dsub_asm, @function
fast2_dsub_asm:
#define manta R0
#define mantexpa R1:0
#define lmanta R1:0
#define mantb R2
#define mantexpb R3:2
#define lmantb R3:2
#define expa R4
#define expb R5
#define mantexpd R7:6
#define expd R6
#define exp R8
#define c63 R9
#define lmant R1:0
#define manth R1
#define mantl R0
#define minmin R11:10 // exactly 0x000000000000008001LL
#define minminl R10
#define k R4
#define ce P0
.falign
{
mantexpd = VABSDIFFH(mantexpa, mantexpb) //represented as 0x08001LL
c63 = #62
expa = SXTH(manta)
expb = SXTH(mantb)
} {
expd = SXTH(expd)
ce = CMP.GT(expa, expb);
if ( ce.new) exp = add(expa, #1)
if (!ce.new) exp = add(expb, #1)
} {
if ( ce) expa = #1
if (!ce) expb = #1
manta.L = #0
expd = MIN(expd, c63)
} {
if (!ce) expa = add(expd, #1)
if ( ce) expb = add(expd, #1)
mantb.L = #0
minmin = #0
} {
lmanta = ASR(lmanta, expa)
lmantb = ASR(lmantb, expb)
} {
lmant = sub(lmanta, lmantb)
minminl.L = #0x8001
} {
k = clb(lmant)
c63 = #58
} {
k = add(k, #-1)
p0 = cmp.gt(k, c63)
} {
mantexpa = ASL(lmant, k)
exp = SUB(exp, k)
if(p0) jump .Ldenorm
} {
manta = insert(exp, #16, #0)
jumpr r31
}
.Ldenorm:
{
mantexpa = minmin
jumpr r31
}
/* ==================================================================== *
fast2_QDOUBLE fast2_dmpy(fast2_QDOUBLE a,fast2_QDOUBLE b) {
fast2_QDOUBLE c;
lint manta = a & MANTMASK;
int expa = Q6_R_sxth_R(a) ;
lint mantb = b & MANTMASK;
int expb = Q6_R_sxth_R(b) ;
int exp, k;
lint mant;
int hia, hib, hi, lo;
unsigned int loa, lob;
hia = (int)(a >> 32);
loa = Q6_R_extractu_RII((int)manta, 31, 1);
hib = (int)(b >> 32);
lob = Q6_R_extractu_RII((int)mantb, 31, 1);
mant = Q6_P_mpy_RR(hia, lob);
mant = Q6_P_mpyacc_RR(mant,hib, loa);
mant = (mant >> 30) + (Q6_P_mpy_RR(hia, hib)<<1);
hi = (int) (mant>>32);
k = Q6_R_normamt_R(hi);
mant = mant << k;
exp = expa + expb - k;
if (mant == 0 || mant == -1) exp = 0x8001;
c = (mant & MANTMASK) | (((lint) exp) & EXP_MASK);
return(c);
}
* ==================================================================== */
.text
.global fast2_dmpy_asm
.type fast2_dmpy_asm, @function
fast2_dmpy_asm:
#define mantal R0
#define mantah R1
#define mantexpa R1:0
#define mantbl R2
#define mantbh R3
#define mantexpb R3:2
#define expa R4
#define expb R5
#define c8001 R12
#define mantexpd R7:6
#define mantdh R7
#define exp R8
#define lmantc R11:10
#define kb R9
#define guard R11
#define mantal_ R12
#define mantbl_ R13
#define min R15:14
#define minh R15
.falign
{
mantbl_= lsr(mantbl, #16)
expb = sxth(mantbl)
expa = sxth(mantal)
mantal_= lsr(mantal, #16)
}
{
lmantc = mpy(mantah, mantbh)
mantexpd = mpy(mantah, mantbl_)
mantal.L = #0x0
min = #0
}
{
lmantc = add(lmantc, lmantc)
mantexpd+= mpy(mantbh, mantal_)
mantbl.L = #0x0
minh.H = #0x8000
}
{
mantexpd = asr(mantexpd, #15)
c8001.L = #0x8001
p1 = cmp.eq(mantexpa, mantexpb)
}
{
mantexpd = add(mantexpd, lmantc)
exp = add(expa, expb)
p2 = cmp.eq(mantexpa, min)
}
{
kb = clb(mantexpd)
mantexpb = abs(mantexpd)
guard = #58
}
{
p1 = and(p1, p2)
exp = sub(exp, kb)
kb = add(kb, #-1)
p0 = cmp.gt(kb, guard)
}
{
exp = add(exp, #1)
mantexpa = asl(mantexpd, kb)
if(p1) jump .Lsat //rarely happens
}
{
mantal = insert(exp,#16, #0)
if(!p0) jumpr r31
}
{
mantal = insert(c8001,#16, #0)
jumpr r31
}
.Lsat:
{
mantexpa = #-1
}
{
mantexpa = lsr(mantexpa, #1)
}
{
mantal = insert(exp,#16, #0)
jumpr r31
}
/* ==================================================================== *
int fast2_qd2f(fast2_QDOUBLE a) {
int exp;
long long int manta;
int ic, rnd, mantb;
manta = a>>32;
exp = Q6_R_sxth_R(a) ;
ic = 0x80000000 & manta;
manta = Q6_R_abs_R_sat(manta);
mantb = (manta + rnd)>>7;
rnd = 0x40
exp = (exp + 126);
if((manta & 0xff) == rnd) rnd = 0x00;
if((manta & 0x7fffffc0) == 0x7fffffc0) {
manta = 0x0; exp++;
} else {
manta= mantb & 0x007fffff;
}
exp = (exp << 23) & 0x7fffffc0;
ic = Q6_R_addacc_RR(ic, exp, manta);
return (ic);
}
* ==================================================================== */
.text
.global fast2_qd2f_asm
.type fast2_qd2f_asm, @function
fast2_qd2f_asm:
#define mantah R1
#define mantal R0
#define cff R0
#define mant R3
#define expo R4
#define rnd R5
#define mask R6
#define c07f R7
#define c80 R0
#define mantb R2
#define ic R0
.falign
{
mant = abs(mantah):sat
expo = sxth(mantal)
rnd = #0x40
mask.L = #0xffc0
}
{
cff = extractu(mant, #8, #0)
p2 = cmp.gt(expo, #126)
p3 = cmp.ge(expo, #-126)
mask.H = #0x7fff
}
{
p1 = cmp.eq(cff,#0x40)
if(p1.new) rnd = #0
expo = add(expo, #126)
if(!p3) jump .Lmin
}
{
p0 = bitsset(mant, mask)
c80.L = #0x0000
mantb = add(mant, rnd)
c07f = lsr(mask, #8)
}
{
if(p0) expo = add(expo, #1)
if(p0) mant = #0
mantb = lsr(mantb, #7)
c80.H = #0x8000
}
{
ic = and(c80, mantah)
mask &= asl(expo, #23)
if(!p0) mant = and(mantb, c07f)
if(p2) jump .Lmax
}
{
ic += add(mask, mant)
jumpr r31
}
.Lmax:
{
ic.L = #0xffff;
}
{
ic.H = #0x7f7f;
jumpr r31
}
.Lmin:
{
ic = #0x0
jumpr r31
}
/* ==================================================================== *
fast2_QDOUBLE fast2_f2qd(int ia) {
lint exp;
lint mant;
fast2_QDOUBLE c;
mant = ((ia << 7) | 0x40000000)&0x7fffff80 ;
if (ia & 0x80000000) mant = -mant;
exp = ((ia >> 23) & 0xFFLL) - 126;
c = (mant<<32) | Q6_R_zxth_R(exp);;
return(c);
}
* ==================================================================== */
.text
.global fast2_f2qd_asm
.type fast2_f2qd_asm, @function
fast2_f2qd_asm:
#define ia R0
#define mag R3
#define mantr R1
#define expr R0
#define zero R2
#define maxneg R5:4
#define maxnegl R4
.falign
{
mantr = asl(ia, #7)
p0 = tstbit(ia, #31)
maxneg = #0
mag = add(ia,ia)
}
{
mantr = setbit(mantr, #30)
expr= extractu(ia,#8,#23)
maxnegl.L = #0x8001
p1 = cmp.eq(mag, #0)
}
{
mantr= extractu(mantr, #31, #0)
expr= add(expr, #-126)
zero = #0
if(p1) jump .Lminqd
}
{
expr = zxth(expr)
if(p0) mantr= sub(zero, mantr)
jumpr r31
}
.Lminqd:
{
R1:0 = maxneg
jumpr r31
}