1#!/usr/local/bin/perl
2# x86 assember
3
4sub bn_mul_add_words
5	{
6	local($name)=@_;
7
8	&function_begin($name,"");
9
10	&comment("");
11	$Low="eax";
12	$High="edx";
13	$a="ebx";
14	$w="ebp";
15	$r="edi";
16	$c="esi";
17
18	&xor($c,$c);		# clear carry
19	&mov($r,&wparam(0));	#
20
21	&mov("ecx",&wparam(2));	#
22	&mov($a,&wparam(1));	#
23
24	&and("ecx",0xfffffff8);	# num / 8
25	&mov($w,&wparam(3));	#
26
27	&push("ecx");		# Up the stack for a tmp variable
28
29	&jz(&label("maw_finish"));
30
31	&set_label("maw_loop",0);
32
33	&mov(&swtmp(0),"ecx");	#
34
35	for ($i=0; $i<32; $i+=4)
36		{
37		&comment("Round $i");
38
39		 &mov("eax",&DWP($i,$a,"",0)); 	# *a
40		&mul($w);			# *a * w
41		&add("eax",$c);		# L(t)+= *r
42		 &mov($c,&DWP($i,$r,"",0));	# L(t)+= *r
43		&adc("edx",0);			# H(t)+=carry
44		 &add("eax",$c);		# L(t)+=c
45		&adc("edx",0);			# H(t)+=carry
46		 &mov(&DWP($i,$r,"",0),"eax");	# *r= L(t);
47		&mov($c,"edx");			# c=  H(t);
48		}
49
50	&comment("");
51	&mov("ecx",&swtmp(0));	#
52	&add($a,32);
53	&add($r,32);
54	&sub("ecx",8);
55	&jnz(&label("maw_loop"));
56
57	&set_label("maw_finish",0);
58	&mov("ecx",&wparam(2));	# get num
59	&and("ecx",7);
60	&jnz(&label("maw_finish2"));	# helps branch prediction
61	&jmp(&label("maw_end"));
62
63	&set_label("maw_finish2",1);
64	for ($i=0; $i<7; $i++)
65		{
66		&comment("Tail Round $i");
67		 &mov("eax",&DWP($i*4,$a,"",0));# *a
68		&mul($w);			# *a * w
69		&add("eax",$c);			# L(t)+=c
70		 &mov($c,&DWP($i*4,$r,"",0));	# L(t)+= *r
71		&adc("edx",0);			# H(t)+=carry
72		 &add("eax",$c);
73		&adc("edx",0);			# H(t)+=carry
74		 &dec("ecx") if ($i != 7-1);
75		&mov(&DWP($i*4,$r,"",0),"eax");	# *r= L(t);
76		 &mov($c,"edx");			# c=  H(t);
77		&jz(&label("maw_end")) if ($i != 7-1);
78		}
79	&set_label("maw_end",0);
80	&mov("eax",$c);
81
82	&pop("ecx");	# clear variable from
83
84	&function_end($name);
85	}
86
871;
88