//===----------------------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 }