1/* Copyright (c) 1998,2011,2014 Apple Inc.  All Rights Reserved.
2 *
3 * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT
4 * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE
5 * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE
6 * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE,
7 * INC.  ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL
8 * EXPOSE YOU TO LIABILITY.
9 ***************************************************************************
10 *
11 * giantPorti486.s - i486-specific assembly routines.
12 *
13 * Revision History
14 * ----------------
15 * 17 Apr 1998 at Apple
16 *	Created.
17 */
18
19#if defined (i386) || defined(__i386__)
20.text
21
22/*
23 * Multiply a vector a giantDigits, candVector, by a single giantDigit,
24 * plierDigit, adding results in prodVector.
25 *
26 * void VectorMultiply(
27 *	giantDigit plierDigit,
28 *	giantDigit *candVector,
29 *	unsigned candLength,
30 *	giantDigit *prodVector)
31 */
32
33.align 2,0x90
34.globl _vectorMult_x86
35
36/*
37 * Stack locations, relative to adjusted bp.
38 */
39#define LOCAL_SPACE		0x4
40
41#define ARG_START		(LOCAL_SPACE + 8)	/* rtn ptr plus bp */
42#define ARG_PLIER_DIGIT		(ARG_START + 0)
43#define ARG_CAND_VECTOR		(ARG_START + 4)		/* cached in ecx */
44#define ARG_CAND_LENGTH		(ARG_START + 8)
45#define ARG_PROD_VECTOR		(ARG_START + 12)	/* cached in esi */
46
47#define LOCAL_START		(0)
48#define LOC_CAND_DEX		(LOCAL_START + 0)  /* index into candVector */
49
50/*
51 * ebx : lastCarry
52 * esi : prodVector
53 * ecx : candVector
54 */
55_vectorMult_x86:
56
57	pushl   %ebp
58	subl    $LOCAL_SPACE,%esp
59	movl    %esp,%ebp
60	pushl   %edi
61	pushl   %esi
62	pushl   %ebx
63
64	/* esp not used again 'til we pop these off stack */
65
66	/* prodVector = %esi */
67	movl    ARG_PROD_VECTOR(%ebp),%esi
68
69	/* lastCarry = 0 */
70	/* 0 --> candDex in 0xf0(%ebp) */
71	xorl    %ebx,%ebx
72
73	/* candVector --> %ecx */
74	movl    ARG_CAND_VECTOR(%ebp),%ecx
75
76	/* for(candDex=0; candDex<candLength; ++candDex) */
77	movl    $0, LOC_CAND_DEX(%ebp)
78
79	/* make sure candLenth > 0 to start...*/
80	cmpl    %ebx,ARG_CAND_LENGTH(%ebp)
81	jbe     _loopEnd
82
83_loopTop:
84	/* branch back to top of for loop */
85
86	/* *candVector--> %eax */
87	movl    (%ecx),%eax
88
89	/* candVector++ */
90	addl    $0x04,%ecx
91
92	/* plierDigit --> %edx */
93	movl    ARG_PLIER_DIGIT(%ebp),%edx
94
95	/* eax = *candVector
96	 * edx = plierDigit
97	 * edx:eax := (plierDigit * *candVector) */
98	mull    %edx
99
100	/* from here to end of loop:
101	   prodLo : eax
102	   prodHi : edx */
103
104	/* prodLo += *prodVector */
105	addl    (%esi),%eax
106
107	/* add carry to hi digit */
108	adc	$0,%edx
109
110	/* prodLo += lastCarry */
111	addl    %ebx,%eax
112	/* add carry to hi digit */
113	adc	$0,%edx
114
115	/* *(prodVector++) = prodLo; */
116	movl    %eax,(%esi)
117	addl    $0x04,%esi
118
119	/* lastCarry = prodHi */
120	movl	%edx, %ebx
121
122	/* candDex++ */
123	incl    LOC_CAND_DEX(%ebp)
124
125	/* top of loop if candDex < candLength */
126	movl    ARG_CAND_LENGTH(%ebp),%eax
127	cmpl    %eax,LOC_CAND_DEX(%ebp)
128	jb      _loopTop
129
130_loopEnd:
131	/* out of for loop */
132	/* *prodVector += lastCarry; */
133#if	0
134	addl    %ebx,(%esi)
135
136	/* return carry from last addition */
137	xorl	%eax,%eax
138	adc	$0,%eax
139#else
140	/* return lastCarry */
141	movl	%ebx,%eax
142#endif
143	popl   	%ebx
144	popl   	%esi
145	popl   	%edi
146	addl	$LOCAL_SPACE,%esp
147	popl   	%ebp
148	ret
149#endif /* i386 */
150