int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, const BN_ULONG *np,const BN_ULONG *n0p, int num)
	{
	BN_ULONG c0,c1,ml,*tp,n0;
#ifdef mul64
	BN_ULONG mh;
#endif
	volatile BN_ULONG *vp;
	int i=0,j;

#if 0	/* template for platform-specific implementation */
	if (ap==bp)	return bn_sqr_mont(rp,ap,np,n0p,num);
#endif
	vp = tp = alloca((num+2)*sizeof(BN_ULONG));

	n0 = *n0p;

	c0 = 0;
	ml = bp[0];
#ifdef mul64
	mh = HBITS(ml);
	ml = LBITS(ml);
	for (j=0;j<num;++j)
		mul(tp[j],ap[j],ml,mh,c0);
#else
	for (j=0;j<num;++j)
		mul(tp[j],ap[j],ml,c0);
#endif

	tp[num]   = c0;
	tp[num+1] = 0;
	goto enter;

	for(i=0;i<num;i++)
		{
		c0 = 0;
		ml = bp[i];
#ifdef mul64
		mh = HBITS(ml);
		ml = LBITS(ml);
		for (j=0;j<num;++j)
			mul_add(tp[j],ap[j],ml,mh,c0);
#else
		for (j=0;j<num;++j)
			mul_add(tp[j],ap[j],ml,c0);
#endif
		c1 = (tp[num] + c0)&BN_MASK2;
		tp[num]   = c1;
		tp[num+1] = (c1<c0?1:0);
	enter:
		c1  = tp[0];
		ml = (c1*n0)&BN_MASK2;
		c0 = 0;
#ifdef mul64
		mh = HBITS(ml);
		ml = LBITS(ml);
		mul_add(c1,np[0],ml,mh,c0);
#else
		mul_add(c1,ml,np[0],c0);
#endif
		for(j=1;j<num;j++)
			{
			c1 = tp[j];
#ifdef mul64
			mul_add(c1,np[j],ml,mh,c0);
#else
			mul_add(c1,ml,np[j],c0);
#endif
			tp[j-1] = c1&BN_MASK2;
			}
		c1        = (tp[num] + c0)&BN_MASK2;
		tp[num-1] = c1;
		tp[num]   = tp[num+1] + (c1<c0?1:0);
		}

	if (tp[num]!=0 || tp[num-1]>=np[num-1])
		{
		c0 = bn_sub_words(rp,tp,np,num);
		if (tp[num]!=0 || c0==0)
			{
			for(i=0;i<num+2;i++)	vp[i] = 0;
			return 1;
			}
		}
	for(i=0;i<num;i++)	rp[i] = tp[i],	vp[i] = 0;
	vp[num]   = 0;
	vp[num+1] = 0;
	return 1;
	}
int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, const BN_ULONG *np,const BN_ULONG *n0p, int num)
	{
	BN_ULONG c0,c1,ml,*tp,n0;
#ifdef mul64
	BN_ULONG mh;
#endif
	volatile BN_ULONG *vp;
	int i=0,j;

#if 0	 
	if (ap==bp)	return bn_sqr_mont(rp,ap,np,n0p,num);
#endif
	vp = tp = alloca((num+2)*sizeof(BN_ULONG));

	n0 = *n0p;

	c0 = 0;
	ml = bp[0];
#ifdef mul64
	mh = HBITS(ml);
	ml = LBITS(ml);
	for (j=0;j<num;++j)
		mul(tp[j],ap[j],ml,mh,c0);
#else
	for (j=0;j<num;++j)
		mul(tp[j],ap[j],ml,c0);
#endif

	tp[num]   = c0;
	tp[num+1] = 0;
	goto enter;

	for(i=0;i<num;i++)
		{
		c0 = 0;
		ml = bp[i];
#ifdef mul64
		mh = HBITS(ml);
		ml = LBITS(ml);
		for (j=0;j<num;++j)
			mul_add(tp[j],ap[j],ml,mh,c0);
#else
		for (j=0;j<num;++j)
			mul_add(tp[j],ap[j],ml,c0);
#endif
		c1 = (tp[num] + c0)&BN_MASK2;
		tp[num]   = c1;
		tp[num+1] = (c1<c0?1:0);
	enter:
		c1  = tp[0];
		ml = (c1*n0)&BN_MASK2;
		c0 = 0;
#ifdef mul64
		mh = HBITS(ml);
		ml = LBITS(ml);
		mul_add(c1,np[0],ml,mh,c0);
#else
		mul_add(c1,ml,np[0],c0);
#endif
		for(j=1;j<num;j++)
			{
			c1 = tp[j];
#ifdef mul64
			mul_add(c1,np[j],ml,mh,c0);
#else
			mul_add(c1,ml,np[j],c0);
#endif
			tp[j-1] = c1&BN_MASK2;
			}
		c1        = (tp[num] + c0)&BN_MASK2;
		tp[num-1] = c1;
		tp[num]   = tp[num+1] + (c1<c0?1:0);
		}

	if (tp[num]!=0 || tp[num-1]>=np[num-1])
		{
		c0 = bn_sub_words(rp,tp,np,num);
		if (tp[num]!=0 || c0==0)
			{
			for(i=0;i<num+2;i++)	vp[i] = 0;
			return 1;
			}
		}
	for(i=0;i<num;i++)	rp[i] = tp[i],	vp[i] = 0;
	vp[num]   = 0;
	vp[num+1] = 0;
	return 1;
	}