• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/libgcrypt-1.5.0/mpi/pentium4/sse2/
1/* Intel Pentium-4 mpn_submul_1 -- Multiply a limb vector with a limb and
2 * subtract the result from a second limb vector.
3 *
4 * Copyright 2001, 2002 Free Software Foundation, Inc.
5 *
6 * This file is part of Libgcrypt.
7 *
8 * Libgcrypt is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as
10 * published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
12 *
13 * Libgcrypt is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 *
22 * Note: This code is heavily based on the GNU MP Library.
23 *	 Actually it's the same code with only minor changes in the
24 *	 way the data is stored; this is to support the abstraction
25 *	 of an optional secure memory allocation which may be used
26 *	 to avoid revealing of sensitive data due to paging etc.
27 */
28
29
30#include "sysdep.h"
31#include "asm-syntax.h"
32
33
34/*******************
35 * mpi_limb_t
36 * _gcry_mpih_submul_1( mpi_ptr_t res_ptr,      (sp + 4)
37 *		     mpi_ptr_t s1_ptr,	     (sp + 8)
38 *		     mpi_size_t s1_size,     (sp + 12)
39 *		     mpi_limb_t s2_limb)     (sp + 16)
40 *
41 * P4: 7 cycles/limb, unstable timing, at least on early Pentium4 silicon
42 *    (stepping 10).
43 *
44 * This code is not particularly good at 7 c/l.  The dependent chain is only
45 * 4 c/l and there's only 4 MMX unit instructions, so it's not clear why that
46 * speed isn't achieved.
47 *
48 * The arrangements made here to get a two instruction dependent chain are
49 * slightly subtle.  In the loop the carry (or borrow rather) is a negative
50 * so that a paddq can be used to give a low limb ready to store, and a high
51 * limb ready to become the new carry after a psrlq.
52 *
53 * If the carry was a simple twos complement negative then the psrlq shift
54 * would need to bring in 0 bits or 1 bits according to whether the high was
55 * zero or non-zero, since a non-zero value would represent a negative
56 * needing sign extension.  That wouldn't be particularly easy to arrange and
57 * certainly would add an instruction to the dependent chain, so instead an
58 * offset is applied so that the high limb will be 0xFFFFFFFF+c.  With c in
59 * the range -0xFFFFFFFF to 0, the value 0xFFFFFFFF+c is in the range 0 to
60 * 0xFFFFFFFF and is therefore always positive and can always have 0 bits
61 * shifted in, which is what psrlq does.
62 *
63 * The extra 0xFFFFFFFF must be subtracted before c is used, but that can be
64 * done off the dependent chain.  The total adjustment then is to add
65 * 0xFFFFFFFF00000000 to offset the new carry, and subtract
66 * 0x00000000FFFFFFFF to remove the offset from the current carry, for a net
67 * add of 0xFFFFFFFE00000001.  In the code this is applied to the destination
68 * limb when fetched.
69 *
70 * It's also possible to view the 0xFFFFFFFF adjustment as a ones-complement
71 * negative, which is how it's undone for the return value, but that doesn't
72 * seem as clear.
73*/
74
75	TEXT
76	ALIGN (4)
77	GLOBL	C_SYMBOL_NAME(_gcry_mpih_submul_1)
78C_SYMBOL_NAME(_gcry_mpih_submul_1:)
79
80	pxor	%mm1, %mm1
81
82.Lstart_1c:
83	movl	8(%esp), %eax
84	pcmpeqd	%mm0, %mm0
85
86	movd	16(%esp), %mm7
87	pcmpeqd	%mm6, %mm6
88
89	movl	4(%esp), %edx
90	psrlq	$32, %mm0
91
92	movl	12(%esp), %ecx
93	psllq	$32, %mm6
94
95	psubq	%mm0, %mm6
96
97	psubq	%mm1, %mm0
98
99/*
100	C eax	src, incrementing
101	C ebx
102	C ecx	loop counter, decrementing
103	C edx	dst, incrementing
104	C
105	C mm0	0xFFFFFFFF - borrow
106	C mm6	0xFFFFFFFE00000001
107	C mm7	multiplier
108*/
109
110.Lloop:
111	movd	(%eax), %mm1
112	leal	4(%eax), %eax
113	movd	(%edx), %mm2
114	paddq	%mm6, %mm2
115	pmuludq	%mm7, %mm1
116	psubq	%mm1, %mm2
117	paddq	%mm2, %mm0
118	subl	$1, %ecx
119	movd	%mm0, (%edx)
120	psrlq	$32, %mm0
121	leal	4(%edx), %edx
122	jnz	.Lloop
123
124	movd	%mm0, %eax
125	notl	%eax
126	emms
127	ret
128