345 lines
8.6 KiB
ArmAsm
345 lines
8.6 KiB
ArmAsm
//===----------------------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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
/* ==================================================================== *
|
|
|
|
fast2_QLDOUBLE fast2_ldadd(fast2_QLDOUBLE a,fast2_QLDOUBLE b) {
|
|
fast2_QLDOUBLE 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_ldadd_asm
|
|
.type fast2_ldadd_asm, @function
|
|
fast2_ldadd_asm:
|
|
#define manta R1:0
|
|
#define lmanta R1:0
|
|
#define mantb R3:2
|
|
#define lmantb R3:2
|
|
#define expa R4
|
|
#define expb R5
|
|
#define expd R6
|
|
#define exp R8
|
|
#define c63 R9
|
|
#define lmant R1:0
|
|
#define k R4
|
|
#define ce P0
|
|
#define zero R3:2
|
|
.falign
|
|
{
|
|
expa = memw(r29+#8)
|
|
expb = memw(r29+#24)
|
|
r7 = r0
|
|
}
|
|
{
|
|
expd = sub(expa, expb):sat
|
|
ce = CMP.GT(expa, expb);
|
|
if ( ce.new) exp = add(expa, #1)
|
|
if (!ce.new) exp = add(expb, #1)
|
|
} {
|
|
expd = abs(expd):sat
|
|
if ( ce) expa = #1
|
|
if (!ce) expb = #1
|
|
c63 = #62
|
|
} {
|
|
expd = MIN(expd, c63)
|
|
manta = memd(r29+#0)
|
|
mantb = memd(r29+#16)
|
|
} {
|
|
if (!ce) expa = add(expd, #1)
|
|
if ( ce) expb = add(expd, #1)
|
|
} {
|
|
lmanta = ASR(lmanta, expa)
|
|
lmantb = ASR(lmantb, expb)
|
|
} {
|
|
lmant = add(lmanta, lmantb)
|
|
zero = #0
|
|
} {
|
|
k = clb(lmant)
|
|
c63.L =#0x0001
|
|
} {
|
|
exp -= add(k, #-1) //exp = exp - (k-1)
|
|
k = add(k, #-1)
|
|
p0 = cmp.gt(k, #58)
|
|
c63.H =#0x8000
|
|
} {
|
|
if(!p0)memw(r7+#8) = exp
|
|
lmant = ASL(lmant, k)
|
|
if(p0) jump .Ldenorma
|
|
} {
|
|
memd(r7+#0) = lmant
|
|
jumpr r31
|
|
}
|
|
.Ldenorma:
|
|
memd(r7+#0) = zero
|
|
{
|
|
memw(r7+#8) = c63
|
|
jumpr r31
|
|
}
|
|
/* =================================================================== *
|
|
fast2_QLDOUBLE fast2_ldsub(fast2_QLDOUBLE a,fast2_QLDOUBLE b) {
|
|
fast2_QLDOUBLE 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_ldsub_asm
|
|
.type fast2_ldsub_asm, @function
|
|
fast2_ldsub_asm:
|
|
#define manta R1:0
|
|
#define lmanta R1:0
|
|
#define mantb R3:2
|
|
#define lmantb R3:2
|
|
#define expa R4
|
|
#define expb R5
|
|
#define expd R6
|
|
#define exp R8
|
|
#define c63 R9
|
|
#define lmant R1:0
|
|
#define k R4
|
|
#define ce P0
|
|
#define zero R3:2
|
|
.falign
|
|
{
|
|
expa = memw(r29+#8)
|
|
expb = memw(r29+#24)
|
|
r7 = r0
|
|
}
|
|
{
|
|
expd = sub(expa, expb):sat
|
|
ce = CMP.GT(expa, expb);
|
|
if ( ce.new) exp = add(expa, #1)
|
|
if (!ce.new) exp = add(expb, #1)
|
|
} {
|
|
expd = abs(expd):sat
|
|
if ( ce) expa = #1
|
|
if (!ce) expb = #1
|
|
c63 = #62
|
|
} {
|
|
expd = min(expd, c63)
|
|
manta = memd(r29+#0)
|
|
mantb = memd(r29+#16)
|
|
} {
|
|
if (!ce) expa = add(expd, #1)
|
|
if ( ce) expb = add(expd, #1)
|
|
} {
|
|
lmanta = ASR(lmanta, expa)
|
|
lmantb = ASR(lmantb, expb)
|
|
} {
|
|
lmant = sub(lmanta, lmantb)
|
|
zero = #0
|
|
} {
|
|
k = clb(lmant)
|
|
c63.L =#0x0001
|
|
} {
|
|
exp -= add(k, #-1) //exp = exp - (k+1)
|
|
k = add(k, #-1)
|
|
p0 = cmp.gt(k, #58)
|
|
c63.H =#0x8000
|
|
} {
|
|
if(!p0)memw(r7+#8) = exp
|
|
lmant = asl(lmant, k)
|
|
if(p0) jump .Ldenorma_s
|
|
} {
|
|
memd(r7+#0) = lmant
|
|
jumpr r31
|
|
}
|
|
.Ldenorma_s:
|
|
memd(r7+#0) = zero
|
|
{
|
|
memw(r7+#8) = c63
|
|
jumpr r31
|
|
}
|
|
|
|
/* ==================================================================== *
|
|
fast2_QLDOUBLE fast2_ldmpy(fast2_QLDOUBLE a,fast2_QLDOUBLE b) {
|
|
fast2_QLDOUBLE 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_ldmpy_asm
|
|
.type fast2_ldmpy_asm, @function
|
|
fast2_ldmpy_asm:
|
|
|
|
#define mantxl_ R9
|
|
#define mantxl R14
|
|
#define mantxh R15
|
|
#define mantx R15:14
|
|
#define mantbl R2
|
|
#define mantbl_ R8
|
|
#define mantbh R3
|
|
#define mantb R3:2
|
|
#define expa R4
|
|
#define expb R5
|
|
#define c8001 R8
|
|
#define mantd R7:6
|
|
#define lmantc R11:10
|
|
#define kp R9
|
|
#define min R13:12
|
|
#define minh R13
|
|
#define max R13:12
|
|
#define maxh R13
|
|
#define ret R0
|
|
|
|
.falign
|
|
{
|
|
mantx = memd(r29+#0)
|
|
mantb = memd(r29+#16)
|
|
min = #0
|
|
}
|
|
{
|
|
mantbl_= extractu(mantbl, #31, #1)
|
|
mantxl_= extractu(mantxl, #31, #1)
|
|
minh.H = #0x8000
|
|
}
|
|
{
|
|
lmantc = mpy(mantxh, mantbh)
|
|
mantd = mpy(mantxh, mantbl_)
|
|
expa = memw(r29+#8)
|
|
expb = memw(r29+#24)
|
|
}
|
|
{
|
|
lmantc = add(lmantc, lmantc)
|
|
mantd += mpy(mantbh, mantxl_)
|
|
}
|
|
{
|
|
mantd = asr(mantd, #30)
|
|
c8001.L = #0x0001
|
|
p1 = cmp.eq(mantx, mantb)
|
|
}
|
|
{
|
|
mantd = add(mantd, lmantc)
|
|
expa= add(expa, expb)
|
|
p2 = cmp.eq(mantb, min)
|
|
}
|
|
{
|
|
kp = clb(mantd)
|
|
c8001.H = #0x8000
|
|
p1 = and(p1, p2)
|
|
}
|
|
{
|
|
expa-= add(kp, #-1)
|
|
kp = add(kp, #-1)
|
|
if(p1) jump .Lsat
|
|
}
|
|
{
|
|
mantd = asl(mantd, kp)
|
|
memw(ret+#8) = expa
|
|
p0 = cmp.gt(kp, #58)
|
|
if(p0.new) jump:NT .Ldenorm //rarely happens
|
|
}
|
|
{
|
|
memd(ret+#0) = mantd
|
|
jumpr r31
|
|
}
|
|
.Lsat:
|
|
{
|
|
max = #0
|
|
expa+= add(kp, #1)
|
|
}
|
|
{
|
|
maxh.H = #0x4000
|
|
memw(ret+#8) = expa
|
|
}
|
|
{
|
|
memd(ret+#0) = max
|
|
jumpr r31
|
|
}
|
|
.Ldenorm:
|
|
{
|
|
memw(ret+#8) = c8001
|
|
mantx = #0
|
|
}
|
|
{
|
|
memd(ret+#0) = mantx
|
|
jumpr r31
|
|
}
|