1656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#!/usr/local/bin/perl
2656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
3221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
4221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrompush(@INC,"${dir}","${dir}../../perlasm");
5656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectrequire "x86asm.pl";
6656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
7656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project&asm_init($ARGV[0],$0);
8656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
9656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project$sse2=0;
10656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectfor (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); }
11656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
12656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project&external_label("OPENSSL_ia32cap_P") if ($sse2);
13656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
14656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project&bn_mul_add_words("bn_mul_add_words");
15656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project&bn_mul_words("bn_mul_words");
16656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project&bn_sqr_words("bn_sqr_words");
17656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project&bn_div_words("bn_div_words");
18656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project&bn_add_words("bn_add_words");
19656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project&bn_sub_words("bn_sub_words");
20656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project&bn_sub_part_words("bn_sub_part_words");
21656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
22656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project&asm_finish();
23656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
24656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectsub bn_mul_add_words
25656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
26656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	local($name)=@_;
27656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
28221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&function_begin_B($name,$sse2?"EXTRN\t_OPENSSL_ia32cap_P:DWORD":"");
29656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
30221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	$r="eax";
31221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	$a="edx";
32221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	$c="ecx";
33656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
34656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if ($sse2) {
35656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&picmeup("eax","OPENSSL_ia32cap_P");
36656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&bt(&DWP(0,"eax"),26);
37221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&jnc(&label("maw_non_sse2"));
38656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
39221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&mov($r,&wparam(0));
40221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&mov($a,&wparam(1));
41221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&mov($c,&wparam(2));
42221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&movd("mm0",&wparam(3));	# mm0 = w
43656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&pxor("mm1","mm1");		# mm1 = carry_in
44221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&jmp(&label("maw_sse2_entry"));
45221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
46221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&set_label("maw_sse2_unrolled",16);
47656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&movd("mm3",&DWP(0,$r,"",0));	# mm3 = r[0]
48656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&paddq("mm1","mm3");		# mm1 = carry_in + r[0]
49656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&movd("mm2",&DWP(0,$a,"",0));	# mm2 = a[0]
50656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&pmuludq("mm2","mm0");		# mm2 = w*a[0]
51656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&movd("mm4",&DWP(4,$a,"",0));	# mm4 = a[1]
52656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&pmuludq("mm4","mm0");		# mm4 = w*a[1]
53656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&movd("mm6",&DWP(8,$a,"",0));	# mm6 = a[2]
54656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&pmuludq("mm6","mm0");		# mm6 = w*a[2]
55656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&movd("mm7",&DWP(12,$a,"",0));	# mm7 = a[3]
56656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&pmuludq("mm7","mm0");		# mm7 = w*a[3]
57656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&paddq("mm1","mm2");		# mm1 = carry_in + r[0] + w*a[0]
58656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&movd("mm3",&DWP(4,$r,"",0));	# mm3 = r[1]
59656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&paddq("mm3","mm4");		# mm3 = r[1] + w*a[1]
60656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&movd("mm5",&DWP(8,$r,"",0));	# mm5 = r[2]
61656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&paddq("mm5","mm6");		# mm5 = r[2] + w*a[2]
62656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&movd("mm4",&DWP(12,$r,"",0));	# mm4 = r[3]
63656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&paddq("mm7","mm4");		# mm7 = r[3] + w*a[3]
64656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&movd(&DWP(0,$r,"",0),"mm1");
65656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&movd("mm2",&DWP(16,$a,"",0));	# mm2 = a[4]
66656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&pmuludq("mm2","mm0");		# mm2 = w*a[4]
67656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&psrlq("mm1",32);		# mm1 = carry0
68656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&movd("mm4",&DWP(20,$a,"",0));	# mm4 = a[5]
69656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&pmuludq("mm4","mm0");		# mm4 = w*a[5]
70656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&paddq("mm1","mm3");		# mm1 = carry0 + r[1] + w*a[1]
71656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&movd("mm6",&DWP(24,$a,"",0));	# mm6 = a[6]
72656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&pmuludq("mm6","mm0");		# mm6 = w*a[6]
73656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&movd(&DWP(4,$r,"",0),"mm1");
74656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&psrlq("mm1",32);		# mm1 = carry1
75656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&movd("mm3",&DWP(28,$a,"",0));	# mm3 = a[7]
76656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&add($a,32);
77656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&pmuludq("mm3","mm0");		# mm3 = w*a[7]
78656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&paddq("mm1","mm5");		# mm1 = carry1 + r[2] + w*a[2]
79656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&movd("mm5",&DWP(16,$r,"",0));	# mm5 = r[4]
80656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&paddq("mm2","mm5");		# mm2 = r[4] + w*a[4]
81656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&movd(&DWP(8,$r,"",0),"mm1");
82656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&psrlq("mm1",32);		# mm1 = carry2
83656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&paddq("mm1","mm7");		# mm1 = carry2 + r[3] + w*a[3]
84656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&movd("mm5",&DWP(20,$r,"",0));	# mm5 = r[5]
85656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&paddq("mm4","mm5");		# mm4 = r[5] + w*a[5]
86656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&movd(&DWP(12,$r,"",0),"mm1");
87656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&psrlq("mm1",32);		# mm1 = carry3
88656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&paddq("mm1","mm2");		# mm1 = carry3 + r[4] + w*a[4]
89656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&movd("mm5",&DWP(24,$r,"",0));	# mm5 = r[6]
90656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&paddq("mm6","mm5");		# mm6 = r[6] + w*a[6]
91656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&movd(&DWP(16,$r,"",0),"mm1");
92656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&psrlq("mm1",32);		# mm1 = carry4
93656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&paddq("mm1","mm4");		# mm1 = carry4 + r[5] + w*a[5]
94656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&movd("mm5",&DWP(28,$r,"",0));	# mm5 = r[7]
95656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&paddq("mm3","mm5");		# mm3 = r[7] + w*a[7]
96656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&movd(&DWP(20,$r,"",0),"mm1");
97656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&psrlq("mm1",32);		# mm1 = carry5
98656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&paddq("mm1","mm6");		# mm1 = carry5 + r[6] + w*a[6]
99656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&movd(&DWP(24,$r,"",0),"mm1");
100656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&psrlq("mm1",32);		# mm1 = carry6
101656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&paddq("mm1","mm3");		# mm1 = carry6 + r[7] + w*a[7]
102656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&movd(&DWP(28,$r,"",0),"mm1");
103221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&lea($r,&DWP(32,$r));
104656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&psrlq("mm1",32);		# mm1 = carry_out
105656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
106221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&sub($c,8);
107221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&jz(&label("maw_sse2_exit"));
108221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&set_label("maw_sse2_entry");
109221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&test($c,0xfffffff8);
110221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&jnz(&label("maw_sse2_unrolled"));
111221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
112221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&set_label("maw_sse2_loop",4);
113221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&movd("mm2",&DWP(0,$a));	# mm2 = a[i]
114221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&movd("mm3",&DWP(0,$r));	# mm3 = r[i]
115221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&pmuludq("mm2","mm0");		# a[i] *= w
116221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&lea($a,&DWP(4,$a));
117221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&paddq("mm1","mm3");		# carry += r[i]
118221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&paddq("mm1","mm2");		# carry += a[i]*w
119221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&movd(&DWP(0,$r),"mm1");	# r[i] = carry_low
120221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&sub($c,1);
121221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&psrlq("mm1",32);		# carry = carry_high
122221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&lea($r,&DWP(4,$r));
123656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&jnz(&label("maw_sse2_loop"));
124221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&set_label("maw_sse2_exit");
125221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&movd("eax","mm1");		# c = carry_out
126656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&emms();
127221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&ret();
128656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
129221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&set_label("maw_non_sse2",16);
130656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
131656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
132221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	# function_begin prologue
133221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&push("ebp");
134221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&push("ebx");
135221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&push("esi");
136221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&push("edi");
137221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
138221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&comment("");
139221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	$Low="eax";
140221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	$High="edx";
141221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	$a="ebx";
142221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	$w="ebp";
143221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	$r="edi";
144221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	$c="esi";
145221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
146221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&xor($c,$c);		# clear carry
147221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&mov($r,&wparam(0));	#
148221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
149221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&mov("ecx",&wparam(2));	#
150221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&mov($a,&wparam(1));	#
151221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
152221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&and("ecx",0xfffffff8);	# num / 8
153221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&mov($w,&wparam(3));	#
154656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
155221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&push("ecx");		# Up the stack for a tmp variable
156221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
157221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&jz(&label("maw_finish"));
158221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
159221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&set_label("maw_loop",16);
160656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
161656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	for ($i=0; $i<32; $i+=4)
162656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
163656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&comment("Round $i");
164656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
165221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		 &mov("eax",&DWP($i,$a)); 	# *a
166656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&mul($w);			# *a * w
167221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&add("eax",$c);			# L(t)+= c
168656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&adc("edx",0);			# H(t)+=carry
169221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		 &add("eax",&DWP($i,$r));	# L(t)+= *r
170656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&adc("edx",0);			# H(t)+=carry
171221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		 &mov(&DWP($i,$r),"eax");	# *r= L(t);
172656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&mov($c,"edx");			# c=  H(t);
173656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
174656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
175656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&comment("");
176656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&sub("ecx",8);
177221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&lea($a,&DWP(32,$a));
178221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&lea($r,&DWP(32,$r));
179656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jnz(&label("maw_loop"));
180656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
181656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("maw_finish",0);
182656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov("ecx",&wparam(2));	# get num
183656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&and("ecx",7);
184656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jnz(&label("maw_finish2"));	# helps branch prediction
185656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jmp(&label("maw_end"));
186656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
187656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("maw_finish2",1);
188656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	for ($i=0; $i<7; $i++)
189656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
190656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&comment("Tail Round $i");
191221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		 &mov("eax",&DWP($i*4,$a));	# *a
192656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&mul($w);			# *a * w
193656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&add("eax",$c);			# L(t)+=c
194656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&adc("edx",0);			# H(t)+=carry
195221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		 &add("eax",&DWP($i*4,$r));	# L(t)+= *r
196656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&adc("edx",0);			# H(t)+=carry
197656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &dec("ecx") if ($i != 7-1);
198221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&mov(&DWP($i*4,$r),"eax");	# *r= L(t);
199221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		 &mov($c,"edx");		# c=  H(t);
200656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&jz(&label("maw_end")) if ($i != 7-1);
201656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
202656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("maw_end",0);
203656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov("eax",$c);
204656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
205656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&pop("ecx");	# clear variable from
206656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
207656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&function_end($name);
208656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
209656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
210656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectsub bn_mul_words
211656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
212656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	local($name)=@_;
213656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
214221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&function_begin_B($name,$sse2?"EXTRN\t_OPENSSL_ia32cap_P:DWORD":"");
215221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
216221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	$r="eax";
217221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	$a="edx";
218221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	$c="ecx";
219221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
220221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if ($sse2) {
221221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&picmeup("eax","OPENSSL_ia32cap_P");
222221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&bt(&DWP(0,"eax"),26);
223221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&jnc(&label("mw_non_sse2"));
224221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
225221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&mov($r,&wparam(0));
226221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&mov($a,&wparam(1));
227221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&mov($c,&wparam(2));
228221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&movd("mm0",&wparam(3));	# mm0 = w
229221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&pxor("mm1","mm1");		# mm1 = carry = 0
230221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
231221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&set_label("mw_sse2_loop",16);
232221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&movd("mm2",&DWP(0,$a));	# mm2 = a[i]
233221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&pmuludq("mm2","mm0");		# a[i] *= w
234221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&lea($a,&DWP(4,$a));
235221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&paddq("mm1","mm2");		# carry += a[i]*w
236221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&movd(&DWP(0,$r),"mm1");	# r[i] = carry_low
237221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&sub($c,1);
238221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&psrlq("mm1",32);		# carry = carry_high
239221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&lea($r,&DWP(4,$r));
240221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&jnz(&label("mw_sse2_loop"));
241221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
242221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&movd("eax","mm1");		# return carry
243221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&emms();
244221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&ret();
245221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&set_label("mw_non_sse2",16);
246221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
247221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
248221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	# function_begin prologue
249221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&push("ebp");
250221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&push("ebx");
251221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&push("esi");
252221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&push("edi");
253656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
254656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&comment("");
255656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$Low="eax";
256656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$High="edx";
257656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$a="ebx";
258656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$w="ecx";
259656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$r="edi";
260656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$c="esi";
261656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$num="ebp";
262656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
263656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&xor($c,$c);		# clear carry
264656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($r,&wparam(0));	#
265656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($a,&wparam(1));	#
266656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($num,&wparam(2));	#
267656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($w,&wparam(3));	#
268656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
269656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&and($num,0xfffffff8);	# num / 8
270656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jz(&label("mw_finish"));
271656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
272656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("mw_loop",0);
273656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	for ($i=0; $i<32; $i+=4)
274656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
275656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&comment("Round $i");
276656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
277656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &mov("eax",&DWP($i,$a,"",0)); 	# *a
278656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&mul($w);			# *a * w
279656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&add("eax",$c);			# L(t)+=c
280656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 # XXX
281656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
282656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&adc("edx",0);			# H(t)+=carry
283656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &mov(&DWP($i,$r,"",0),"eax");	# *r= L(t);
284656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
285656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&mov($c,"edx");			# c=  H(t);
286656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
287656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
288656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&comment("");
289656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&add($a,32);
290656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&add($r,32);
291656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&sub($num,8);
292656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jz(&label("mw_finish"));
293656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jmp(&label("mw_loop"));
294656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
295656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("mw_finish",0);
296656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($num,&wparam(2));	# get num
297656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&and($num,7);
298656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jnz(&label("mw_finish2"));
299656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jmp(&label("mw_end"));
300656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
301656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("mw_finish2",1);
302656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	for ($i=0; $i<7; $i++)
303656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
304656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&comment("Tail Round $i");
305656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &mov("eax",&DWP($i*4,$a,"",0));# *a
306656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&mul($w);			# *a * w
307656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&add("eax",$c);			# L(t)+=c
308656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 # XXX
309656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&adc("edx",0);			# H(t)+=carry
310656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &mov(&DWP($i*4,$r,"",0),"eax");# *r= L(t);
311656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&mov($c,"edx");			# c=  H(t);
312656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &dec($num) if ($i != 7-1);
313656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&jz(&label("mw_end")) if ($i != 7-1);
314656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
315656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("mw_end",0);
316656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov("eax",$c);
317656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
318656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&function_end($name);
319656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
320656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
321656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectsub bn_sqr_words
322656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
323656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	local($name)=@_;
324656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
325221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&function_begin_B($name,$sse2?"EXTRN\t_OPENSSL_ia32cap_P:DWORD":"");
326221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
327221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	$r="eax";
328221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	$a="edx";
329221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	$c="ecx";
330221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
331221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if ($sse2) {
332221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&picmeup("eax","OPENSSL_ia32cap_P");
333221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&bt(&DWP(0,"eax"),26);
334221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&jnc(&label("sqr_non_sse2"));
335221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
336221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&mov($r,&wparam(0));
337221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&mov($a,&wparam(1));
338221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&mov($c,&wparam(2));
339221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
340221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&set_label("sqr_sse2_loop",16);
341221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&movd("mm0",&DWP(0,$a));	# mm0 = a[i]
342221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&pmuludq("mm0","mm0");		# a[i] *= a[i]
343221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&lea($a,&DWP(4,$a));		# a++
344221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&movq(&QWP(0,$r),"mm0");	# r[i] = a[i]*a[i]
345221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&sub($c,1);
346221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&lea($r,&DWP(8,$r));		# r += 2
347221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&jnz(&label("sqr_sse2_loop"));
348221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
349221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&emms();
350221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		&ret();
351221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&set_label("sqr_non_sse2",16);
352221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
353221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
354221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	# function_begin prologue
355221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&push("ebp");
356221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&push("ebx");
357221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&push("esi");
358221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&push("edi");
359656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
360656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&comment("");
361656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$r="esi";
362656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$a="edi";
363656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$num="ebx";
364656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
365656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($r,&wparam(0));	#
366656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($a,&wparam(1));	#
367656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($num,&wparam(2));	#
368656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
369656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&and($num,0xfffffff8);	# num / 8
370656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jz(&label("sw_finish"));
371656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
372656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("sw_loop",0);
373656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	for ($i=0; $i<32; $i+=4)
374656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
375656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&comment("Round $i");
376656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&mov("eax",&DWP($i,$a,"",0)); 	# *a
377656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 # XXX
378656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&mul("eax");			# *a * *a
379656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&mov(&DWP($i*2,$r,"",0),"eax");	#
380656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &mov(&DWP($i*2+4,$r,"",0),"edx");#
381656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
382656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
383656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&comment("");
384656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&add($a,32);
385656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&add($r,64);
386656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&sub($num,8);
387656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jnz(&label("sw_loop"));
388656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
389656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("sw_finish",0);
390656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($num,&wparam(2));	# get num
391656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&and($num,7);
392656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jz(&label("sw_end"));
393656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
394656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	for ($i=0; $i<7; $i++)
395656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
396656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&comment("Tail Round $i");
397656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&mov("eax",&DWP($i*4,$a,"",0));	# *a
398656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 # XXX
399656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&mul("eax");			# *a * *a
400656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&mov(&DWP($i*8,$r,"",0),"eax");	#
401656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &dec($num) if ($i != 7-1);
402656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&mov(&DWP($i*8+4,$r,"",0),"edx");
403656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &jz(&label("sw_end")) if ($i != 7-1);
404656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
405656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("sw_end",0);
406656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
407656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&function_end($name);
408656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
409656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
410656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectsub bn_div_words
411656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
412656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	local($name)=@_;
413656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
414221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&function_begin_B($name,"");
415656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov("edx",&wparam(0));	#
416656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov("eax",&wparam(1));	#
417221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&mov("ecx",&wparam(2));	#
418221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&div("ecx");
419221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&ret();
420221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	&function_end_B($name);
421656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
422656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
423656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectsub bn_add_words
424656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
425656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	local($name)=@_;
426656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
427656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&function_begin($name,"");
428656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
429656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&comment("");
430656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$a="esi";
431656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$b="edi";
432656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$c="eax";
433656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$r="ebx";
434656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$tmp1="ecx";
435656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$tmp2="edx";
436656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$num="ebp";
437656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
438656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($r,&wparam(0));	# get r
439656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 &mov($a,&wparam(1));	# get a
440656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($b,&wparam(2));	# get b
441656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 &mov($num,&wparam(3));	# get num
442656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&xor($c,$c);		# clear carry
443656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 &and($num,0xfffffff8);	# num / 8
444656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
445656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jz(&label("aw_finish"));
446656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
447656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("aw_loop",0);
448656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	for ($i=0; $i<8; $i++)
449656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
450656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&comment("Round $i");
451656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
452656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&mov($tmp1,&DWP($i*4,$a,"",0)); 	# *a
453656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &mov($tmp2,&DWP($i*4,$b,"",0)); 	# *b
454656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&add($tmp1,$c);
455656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &mov($c,0);
456656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&adc($c,$c);
457656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &add($tmp1,$tmp2);
458656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&adc($c,0);
459656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &mov(&DWP($i*4,$r,"",0),$tmp1); 	# *r
460656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
461656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
462656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&comment("");
463656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&add($a,32);
464656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 &add($b,32);
465656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&add($r,32);
466656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 &sub($num,8);
467656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jnz(&label("aw_loop"));
468656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
469656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("aw_finish",0);
470656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($num,&wparam(3));	# get num
471656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&and($num,7);
472656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 &jz(&label("aw_end"));
473656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
474656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	for ($i=0; $i<7; $i++)
475656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
476656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&comment("Tail Round $i");
477656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&mov($tmp1,&DWP($i*4,$a,"",0));	# *a
478656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &mov($tmp2,&DWP($i*4,$b,"",0));# *b
479656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&add($tmp1,$c);
480656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &mov($c,0);
481656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&adc($c,$c);
482656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &add($tmp1,$tmp2);
483656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&adc($c,0);
484656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &dec($num) if ($i != 6);
485656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&mov(&DWP($i*4,$r,"",0),$tmp1);	# *r
486656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &jz(&label("aw_end")) if ($i != 6);
487656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
488656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("aw_end",0);
489656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
490656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#	&mov("eax",$c);		# $c is "eax"
491656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
492656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&function_end($name);
493656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
494656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
495656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectsub bn_sub_words
496656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
497656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	local($name)=@_;
498656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
499656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&function_begin($name,"");
500656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
501656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&comment("");
502656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$a="esi";
503656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$b="edi";
504656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$c="eax";
505656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$r="ebx";
506656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$tmp1="ecx";
507656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$tmp2="edx";
508656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$num="ebp";
509656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
510656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($r,&wparam(0));	# get r
511656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 &mov($a,&wparam(1));	# get a
512656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($b,&wparam(2));	# get b
513656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 &mov($num,&wparam(3));	# get num
514656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&xor($c,$c);		# clear carry
515656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 &and($num,0xfffffff8);	# num / 8
516656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
517656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jz(&label("aw_finish"));
518656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
519656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("aw_loop",0);
520656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	for ($i=0; $i<8; $i++)
521656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
522656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&comment("Round $i");
523656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
524656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&mov($tmp1,&DWP($i*4,$a,"",0)); 	# *a
525656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &mov($tmp2,&DWP($i*4,$b,"",0)); 	# *b
526656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&sub($tmp1,$c);
527656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &mov($c,0);
528656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&adc($c,$c);
529656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &sub($tmp1,$tmp2);
530656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&adc($c,0);
531656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &mov(&DWP($i*4,$r,"",0),$tmp1); 	# *r
532656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
533656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
534656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&comment("");
535656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&add($a,32);
536656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 &add($b,32);
537656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&add($r,32);
538656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 &sub($num,8);
539656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jnz(&label("aw_loop"));
540656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
541656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("aw_finish",0);
542656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($num,&wparam(3));	# get num
543656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&and($num,7);
544656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 &jz(&label("aw_end"));
545656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
546656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	for ($i=0; $i<7; $i++)
547656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
548656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&comment("Tail Round $i");
549656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&mov($tmp1,&DWP($i*4,$a,"",0));	# *a
550656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &mov($tmp2,&DWP($i*4,$b,"",0));# *b
551656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&sub($tmp1,$c);
552656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &mov($c,0);
553656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&adc($c,$c);
554656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &sub($tmp1,$tmp2);
555656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&adc($c,0);
556656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &dec($num) if ($i != 6);
557656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&mov(&DWP($i*4,$r,"",0),$tmp1);	# *r
558656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &jz(&label("aw_end")) if ($i != 6);
559656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
560656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("aw_end",0);
561656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
562656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#	&mov("eax",$c);		# $c is "eax"
563656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
564656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&function_end($name);
565656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
566656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
567656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectsub bn_sub_part_words
568656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
569656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	local($name)=@_;
570656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
571656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&function_begin($name,"");
572656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
573656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&comment("");
574656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$a="esi";
575656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$b="edi";
576656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$c="eax";
577656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$r="ebx";
578656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$tmp1="ecx";
579656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$tmp2="edx";
580656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	$num="ebp";
581656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
582656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($r,&wparam(0));	# get r
583656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 &mov($a,&wparam(1));	# get a
584656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($b,&wparam(2));	# get b
585656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 &mov($num,&wparam(3));	# get num
586656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&xor($c,$c);		# clear carry
587656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 &and($num,0xfffffff8);	# num / 8
588656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
589656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jz(&label("aw_finish"));
590656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
591656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("aw_loop",0);
592656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	for ($i=0; $i<8; $i++)
593656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
594656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&comment("Round $i");
595656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
596656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&mov($tmp1,&DWP($i*4,$a,"",0)); 	# *a
597656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &mov($tmp2,&DWP($i*4,$b,"",0)); 	# *b
598656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&sub($tmp1,$c);
599656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &mov($c,0);
600656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&adc($c,$c);
601656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &sub($tmp1,$tmp2);
602656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&adc($c,0);
603656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &mov(&DWP($i*4,$r,"",0),$tmp1); 	# *r
604656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
605656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
606656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&comment("");
607656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&add($a,32);
608656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 &add($b,32);
609656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&add($r,32);
610656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 &sub($num,8);
611656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jnz(&label("aw_loop"));
612656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
613656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("aw_finish",0);
614656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($num,&wparam(3));	# get num
615656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&and($num,7);
616656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 &jz(&label("aw_end"));
617656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
618656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	for ($i=0; $i<7; $i++)
619656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
620656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&comment("Tail Round $i");
621656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&mov($tmp1,&DWP(0,$a,"",0));	# *a
622656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &mov($tmp2,&DWP(0,$b,"",0));# *b
623656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&sub($tmp1,$c);
624656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &mov($c,0);
625656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&adc($c,$c);
626656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &sub($tmp1,$tmp2);
627656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&adc($c,0);
628656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&mov(&DWP(0,$r,"",0),$tmp1);	# *r
629656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&add($a, 4);
630656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&add($b, 4);
631656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		&add($r, 4);
632656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &dec($num) if ($i != 6);
633656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 &jz(&label("aw_end")) if ($i != 6);
634656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
635656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("aw_end",0);
636656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
637656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&cmp(&wparam(4),0);
638656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&je(&label("pw_end"));
639656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
640656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($num,&wparam(4));	# get dl
641656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&cmp($num,0);
642656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&je(&label("pw_end"));
643656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jge(&label("pw_pos"));
644656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
645656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&comment("pw_neg");
646656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($tmp2,0);
647656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&sub($tmp2,$num);
648656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($num,$tmp2);
649656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&and($num,0xfffffff8);	# num / 8
650656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jz(&label("pw_neg_finish"));
651656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
652656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("pw_neg_loop",0);
653656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	for ($i=0; $i<8; $i++)
654656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
655656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &comment("dl<0 Round $i");
656656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
657656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &mov($tmp1,0);
658656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &mov($tmp2,&DWP($i*4,$b,"",0)); 	# *b
659656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &sub($tmp1,$c);
660656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &mov($c,0);
661656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &adc($c,$c);
662656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &sub($tmp1,$tmp2);
663656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &adc($c,0);
664656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &mov(&DWP($i*4,$r,"",0),$tmp1); 	# *r
665656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
666656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
667656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&comment("");
668656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&add($b,32);
669656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&add($r,32);
670656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&sub($num,8);
671656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jnz(&label("pw_neg_loop"));
672656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
673656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("pw_neg_finish",0);
674656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($tmp2,&wparam(4));	# get dl
675656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($num,0);
676656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&sub($num,$tmp2);
677656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&and($num,7);
678656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jz(&label("pw_end"));
679656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
680656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	for ($i=0; $i<7; $i++)
681656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
682656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &comment("dl<0 Tail Round $i");
683656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &mov($tmp1,0);
684656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &mov($tmp2,&DWP($i*4,$b,"",0));# *b
685656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &sub($tmp1,$c);
686656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &mov($c,0);
687656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &adc($c,$c);
688656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &sub($tmp1,$tmp2);
689656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &adc($c,0);
690656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &dec($num) if ($i != 6);
691656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &mov(&DWP($i*4,$r,"",0),$tmp1);	# *r
692656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &jz(&label("pw_end")) if ($i != 6);
693656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
694656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
695656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jmp(&label("pw_end"));
696656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
697656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("pw_pos",0);
698656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
699656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&and($num,0xfffffff8);	# num / 8
700656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jz(&label("pw_pos_finish"));
701656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
702656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("pw_pos_loop",0);
703656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
704656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	for ($i=0; $i<8; $i++)
705656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
706656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &comment("dl>0 Round $i");
707656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
708656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &mov($tmp1,&DWP($i*4,$a,"",0));	# *a
709656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &sub($tmp1,$c);
710656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &mov(&DWP($i*4,$r,"",0),$tmp1);	# *r
711656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &jnc(&label("pw_nc".$i));
712656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
713656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
714656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&comment("");
715656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&add($a,32);
716656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&add($r,32);
717656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&sub($num,8);
718656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jnz(&label("pw_pos_loop"));
719656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
720656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("pw_pos_finish",0);
721656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($num,&wparam(4));	# get dl
722656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&and($num,7);
723656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jz(&label("pw_end"));
724656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
725656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	for ($i=0; $i<7; $i++)
726656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
727656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &comment("dl>0 Tail Round $i");
728656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &mov($tmp1,&DWP($i*4,$a,"",0));	# *a
729656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &sub($tmp1,$c);
730656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &mov(&DWP($i*4,$r,"",0),$tmp1);	# *r
731656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &jnc(&label("pw_tail_nc".$i));
732656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &dec($num) if ($i != 6);
733656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &jz(&label("pw_end")) if ($i != 6);
734656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
735656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($c,1);
736656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jmp(&label("pw_end"));
737656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
738656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("pw_nc_loop",0);
739656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	for ($i=0; $i<8; $i++)
740656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
741656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &mov($tmp1,&DWP($i*4,$a,"",0));	# *a
742656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &mov(&DWP($i*4,$r,"",0),$tmp1);	# *r
743656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &set_label("pw_nc".$i,0);
744656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
745656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
746656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&comment("");
747656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&add($a,32);
748656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&add($r,32);
749656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&sub($num,8);
750656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jnz(&label("pw_nc_loop"));
751656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
752656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($num,&wparam(4));	# get dl
753656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&and($num,7);
754656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&jz(&label("pw_nc_end"));
755656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
756656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	for ($i=0; $i<7; $i++)
757656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
758656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &mov($tmp1,&DWP($i*4,$a,"",0));	# *a
759656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &mov(&DWP($i*4,$r,"",0),$tmp1);	# *r
760656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &set_label("pw_tail_nc".$i,0);
761656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &dec($num) if ($i != 6);
762656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    &jz(&label("pw_nc_end")) if ($i != 6);
763656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
764656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
765656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("pw_nc_end",0);
766656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&mov($c,0);
767656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
768656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&set_label("pw_end",0);
769656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
770656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#	&mov("eax",$c);		# $c is "eax"
771656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
772656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	&function_end($name);
773656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
774656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
775