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);
* 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;
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_correct_top(&wnum);
if (!BN_sub(&wnum,&wnum,tmp)) goto err;
snum->top=snum->top+wnum.top-j;
* 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);
}