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.h - OpenStep-dependent giant definitions.
12 *
13 * Revision History
14 * ----------------
15 * 06 Apr 1998 at Apple
16 *	Created.
17 */
18
19#ifndef	_CK_NSGIANT_PORT_I486_H_
20#define _CK_NSGIANT_PORT_I486_H_
21
22#include "giantIntegers.h"
23
24#ifdef __cplusplus
25extern "C" {
26#endif
27
28/*
29 * Add two digits, return sum. Carry bit returned as an out parameter.
30 */
31static inline giantDigit giantAddDigits(
32	giantDigit dig1,
33 	giantDigit dig2,
34 	giantDigit *carry) 	/* RETURNED, 0 or 1 */
35{
36	giantDigit _sum;	/* r/w %0 */
37	asm volatile(
38		"movl %2, %0	/* _sum = dig1 */	\n"
39		"addl %3, %0	/* _sum += dig2 */	\n"
40		"jc .+9					\n"
41		"movl $0, %1	/* carry = 0 */		\n"
42		"jmp .+7				\n"
43		"movl $1, %1	/* carry = 1 */		\n"
44	    	: "=&r" (_sum), "=&r" (*carry)
45		: "r" (dig1), "r" (dig2));
46	return _sum;
47}
48
49/*
50 * Add a single digit value to a double digit accumulator in place.
51 * Carry out of the MSD of the accumulator is not handled.
52 */
53static inline void giantAddDouble(
54 	giantDigit *accLow,		/* IN/OUT */
55 	giantDigit *accHigh,		/* IN/OUT */
56 	giantDigit val)
57{
58	asm volatile(
59		"addl %4, %0	/* accLow += val */	\n"
60		"jnc .+3				\n"
61		"incl %1	/* accHigh++ */		\n"
62	    	: "=&r" (*accLow), "=&r" (*accHigh)
63		: "0" (*accLow), "1" (*accHigh), "r" (val));
64}
65
66/*
67 * Subtract a - b, return difference. Borrow bit returned as an out parameter.
68 */
69static inline giantDigit giantSubDigits(
70 	giantDigit a,
71 	giantDigit b,
72 	giantDigit *borrow)		/* RETURNED, 0 or 1 */
73{
74	giantDigit _diff;	/* r/w %0 */
75	asm volatile(
76		"movl %2, %0	/* _diff = a */		\n"
77		"subl %3, %0	/* _diff -= b */	\n"
78		"jc .+9					\n"
79		"movl $0, %1	/* borrow = 0 */	\n"
80		"jmp .+7				\n"
81		"movl $1, %1	/* borrow = 1 */	\n"
82	    	: "=&r" (_diff), "=&r" (*borrow)
83		: "r" (a), "r" (b));
84	return _diff;
85}
86
87/*
88 * Multiply two digits, return two digits.
89 */
90static inline void giantMulDigits(
91 	giantDigit	dig1,
92 	giantDigit	dig2,
93 	giantDigit	*lowProduct,	// RETURNED, low digit
94 	giantDigit	*hiProduct)	// RETURNED, high digit
95
96{
97	asm volatile(
98		"movl %2, %%eax	/* eax = dig1 */	\n"
99		"movl %3, %%edx /* edx = dig2 */	\n"
100		"mull %%edx	/* eax *= dig2 */	\n"
101	    	: "=&a" (*lowProduct), "=&d" (*hiProduct)
102		: "r" (dig1), "r" (dig2)
103		: "%eax", "%edx" );
104}
105
106/*
107 * Multiply a vector of giantDigits, candVector, by a single giantDigit,
108 * plierDigit, adding results into prodVector. Returns m.s. digit from
109 * final multiply; only candLength digits of *prodVector will be written.
110 *
111 * This one's implemented in a .s file.
112 */
113extern giantDigit vectorMult_x86(
114	giantDigit plierDigit,
115	giantDigit *candVector,
116	unsigned candLength,
117	giantDigit *prodVector);
118
119#define VectorMultiply(pd, cv, cl, pv) vectorMult_x86(pd, cv, cl, pv)
120
121
122#ifdef __cplusplus
123}
124#endif
125
126#endif	_CK_NSGIANT_PORT_I486_H_
127