#if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) \
&& !defined(PEDANTIC) && !defined(BN_DIV3W)
# if defined(__GNUC__) && __GNUC__>=2
-# if defined(__i386)
+# if defined(__i386) || defined (__i386__)
/*
* There were two reasons for implementing this template:
* - GNU C generates a call to a function (__udivdi3 to be exact)
q; \
})
# define REMAINDER_IS_ALREADY_CALCULATED
+# elif defined(__x86_64) && defined(SIXTY_FOUR_BIT_LONG)
+ /*
+ * Same story here, but it's 128-bit by 64-bit division. Wow!
+ * <appro@fy.chalmers.se>
+ */
+# define bn_div_words(n0,n1,d0) \
+ ({ asm volatile ( \
+ "divq %4" \
+ : "=a"(q), "=d"(rem) \
+ : "a"(n1), "d"(n0), "g"(d0) \
+ : "cc"); \
+ q; \
+ })
+# define REMAINDER_IS_ALREADY_CALCULATED
# endif /* __<cpu> */
# endif /* __GNUC__ */
#endif /* OPENSSL_NO_ASM */
BN_ULONG d0,d1;
int num_n,div_n;
+ bn_check_top(dv);
+ bn_check_top(rm);
bn_check_top(num);
bn_check_top(divisor);
/* First we normalise the numbers */
norm_shift=BN_BITS2-((BN_num_bits(divisor))%BN_BITS2);
- BN_lshift(sdiv,divisor,norm_shift);
+ if (!(BN_lshift(sdiv,divisor,norm_shift))) goto err;
sdiv->neg=0;
norm_shift+=BN_BITS2;
- BN_lshift(snum,num,norm_shift);
+ if (!(BN_lshift(snum,num,norm_shift))) goto err;
snum->neg=0;
div_n=sdiv->top;
num_n=snum->top;
* This is the part that corresponds to the current
* 'area' being divided */
BN_init(&wnum);
+ wnum.flags = BN_FLG_STATIC_DATA; /* prevent accidental "expands" */
wnum.d= &(snum->d[loop]);
wnum.top= div_n;
- wnum.dmax= snum->dmax+1; /* a bit of a lie */
+ wnum.dmax= snum->dmax - loop; /* so we don't step out of bounds */
/* Get the top 2 words of sdiv */
- /* i=sdiv->top; */
+ /* div_n=sdiv->top; */
d0=sdiv->d[div_n-1];
d1=(div_n == 1)?0:sdiv->d[div_n-2];
/* space for temp */
if (!bn_wexpand(tmp,(div_n+1))) goto err;
+ bn_correct_top(&wnum);
if (BN_ucmp(&wnum,sdiv) >= 0)
{
if (!BN_usub(&wnum,&wnum,sdiv)) goto err;
{
BN_ULONG q,l0;
#if defined(BN_DIV3W) && !defined(OPENSSL_NO_ASM)
+ BN_ULONG bn_div_3_words(BN_ULONG*,BN_ULONG,BN_ULONG);
q=bn_div_3_words(wnump,d1,d0);
#else
BN_ULONG n0,n1,rem=0;
q=(BN_ULONG)(((((BN_ULLONG)n0)<<BN_BITS2)|n1)/d0);
#else
q=bn_div_words(n0,n1,d0);
+#ifdef BN_DEBUG_LEVITTE
+ fprintf(stderr,"DEBUG: bn_div_words(0x%08X,0x%08X,0x%08\
+X) -> 0x%08X\n",
+ n0, n1, d0, q);
+#endif
#endif
#ifndef REMAINDER_IS_ALREADY_CALCULATED
BN_ULONG t2l,t2h,ql,qh;
q=bn_div_words(n0,n1,d0);
+#ifdef BN_DEBUG_LEVITTE
+ fprintf(stderr,"DEBUG: bn_div_words(0x%08X,0x%08X,0x%08\
+X) -> 0x%08X\n",
+ n0, n1, d0, q);
+#endif
#ifndef REMAINDER_IS_ALREADY_CALCULATED
rem=(n1-q*d0)&BN_MASK2;
#endif
-#ifdef BN_UMULT_HIGH
+#if defined(BN_UMULT_LOHI)
+ BN_UMULT_LOHI(t2l,t2h,d1,q);
+#elif defined(BN_UMULT_HIGH)
t2l = d1 * q;
t2h = BN_UMULT_HIGH(d1,q);
#else
#endif /* !BN_DIV3W */
l0=bn_mul_words(tmp->d,sdiv->d,div_n,q);
- wnum.d--; wnum.top++;
+ wnum.d--; wnum.top++; wnum.dmax++;
tmp->d[div_n]=l0;
+ /* XXX: Couldn't we replace this with;
+ * tmp->top = div_n;
+ * bn_fix_top(tmp);
+ */
for (j=div_n+1; j>0; j--)
if (tmp->d[j-1]) break;
tmp->top=j;
j=wnum.top;
- BN_sub(&wnum,&wnum,tmp);
+ bn_correct_top(&wnum);
+ if (!BN_sub(&wnum,&wnum,tmp)) goto err;
snum->top=snum->top+wnum.top-j;
{
q--;
j=wnum.top;
- BN_add(&wnum,&wnum,sdiv);
+ if (!BN_add(&wnum,&wnum,sdiv)) goto err;
snum->top+=wnum.top-j;
}
*(resp--)=q;
* BN_rshift() will overwrite it.
*/
int neg = num->neg;
+ bn_correct_top(snum);
BN_rshift(rm,snum,norm_shift);
if (!BN_is_zero(rm))
rm->neg = neg;
+ bn_check_top(rm);
}
BN_CTX_end(ctx);
return(1);
err:
+ bn_check_top(rm);
BN_CTX_end(ctx);
return(0);
}