bn-586.pl 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  1. #!/usr/local/bin/perl
  2. push(@INC,"perlasm","../../perlasm");
  3. require "x86asm.pl";
  4. &asm_init($ARGV[0],$0);
  5. $sse2=0;
  6. for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); }
  7. &external_label("OPENSSL_ia32cap_P") if ($sse2);
  8. &bn_mul_add_words("bn_mul_add_words");
  9. &bn_mul_words("bn_mul_words");
  10. &bn_sqr_words("bn_sqr_words");
  11. &bn_div_words("bn_div_words");
  12. &bn_add_words("bn_add_words");
  13. &bn_sub_words("bn_sub_words");
  14. &bn_sub_part_words("bn_sub_part_words");
  15. &asm_finish();
  16. sub bn_mul_add_words
  17. {
  18. local($name)=@_;
  19. &function_begin_B($name,$sse2?"EXTRN\t_OPENSSL_ia32cap_P:DWORD":"");
  20. $r="eax";
  21. $a="edx";
  22. $c="ecx";
  23. if ($sse2) {
  24. &picmeup("eax","OPENSSL_ia32cap_P");
  25. &bt(&DWP(0,"eax"),26);
  26. &jnc(&label("maw_non_sse2"));
  27. &mov($r,&wparam(0));
  28. &mov($a,&wparam(1));
  29. &mov($c,&wparam(2));
  30. &movd("mm0",&wparam(3)); # mm0 = w
  31. &pxor("mm1","mm1"); # mm1 = carry_in
  32. &jmp(&label("maw_sse2_entry"));
  33. &set_label("maw_sse2_unrolled",16);
  34. &movd("mm3",&DWP(0,$r,"",0)); # mm3 = r[0]
  35. &paddq("mm1","mm3"); # mm1 = carry_in + r[0]
  36. &movd("mm2",&DWP(0,$a,"",0)); # mm2 = a[0]
  37. &pmuludq("mm2","mm0"); # mm2 = w*a[0]
  38. &movd("mm4",&DWP(4,$a,"",0)); # mm4 = a[1]
  39. &pmuludq("mm4","mm0"); # mm4 = w*a[1]
  40. &movd("mm6",&DWP(8,$a,"",0)); # mm6 = a[2]
  41. &pmuludq("mm6","mm0"); # mm6 = w*a[2]
  42. &movd("mm7",&DWP(12,$a,"",0)); # mm7 = a[3]
  43. &pmuludq("mm7","mm0"); # mm7 = w*a[3]
  44. &paddq("mm1","mm2"); # mm1 = carry_in + r[0] + w*a[0]
  45. &movd("mm3",&DWP(4,$r,"",0)); # mm3 = r[1]
  46. &paddq("mm3","mm4"); # mm3 = r[1] + w*a[1]
  47. &movd("mm5",&DWP(8,$r,"",0)); # mm5 = r[2]
  48. &paddq("mm5","mm6"); # mm5 = r[2] + w*a[2]
  49. &movd("mm4",&DWP(12,$r,"",0)); # mm4 = r[3]
  50. &paddq("mm7","mm4"); # mm7 = r[3] + w*a[3]
  51. &movd(&DWP(0,$r,"",0),"mm1");
  52. &movd("mm2",&DWP(16,$a,"",0)); # mm2 = a[4]
  53. &pmuludq("mm2","mm0"); # mm2 = w*a[4]
  54. &psrlq("mm1",32); # mm1 = carry0
  55. &movd("mm4",&DWP(20,$a,"",0)); # mm4 = a[5]
  56. &pmuludq("mm4","mm0"); # mm4 = w*a[5]
  57. &paddq("mm1","mm3"); # mm1 = carry0 + r[1] + w*a[1]
  58. &movd("mm6",&DWP(24,$a,"",0)); # mm6 = a[6]
  59. &pmuludq("mm6","mm0"); # mm6 = w*a[6]
  60. &movd(&DWP(4,$r,"",0),"mm1");
  61. &psrlq("mm1",32); # mm1 = carry1
  62. &movd("mm3",&DWP(28,$a,"",0)); # mm3 = a[7]
  63. &add($a,32);
  64. &pmuludq("mm3","mm0"); # mm3 = w*a[7]
  65. &paddq("mm1","mm5"); # mm1 = carry1 + r[2] + w*a[2]
  66. &movd("mm5",&DWP(16,$r,"",0)); # mm5 = r[4]
  67. &paddq("mm2","mm5"); # mm2 = r[4] + w*a[4]
  68. &movd(&DWP(8,$r,"",0),"mm1");
  69. &psrlq("mm1",32); # mm1 = carry2
  70. &paddq("mm1","mm7"); # mm1 = carry2 + r[3] + w*a[3]
  71. &movd("mm5",&DWP(20,$r,"",0)); # mm5 = r[5]
  72. &paddq("mm4","mm5"); # mm4 = r[5] + w*a[5]
  73. &movd(&DWP(12,$r,"",0),"mm1");
  74. &psrlq("mm1",32); # mm1 = carry3
  75. &paddq("mm1","mm2"); # mm1 = carry3 + r[4] + w*a[4]
  76. &movd("mm5",&DWP(24,$r,"",0)); # mm5 = r[6]
  77. &paddq("mm6","mm5"); # mm6 = r[6] + w*a[6]
  78. &movd(&DWP(16,$r,"",0),"mm1");
  79. &psrlq("mm1",32); # mm1 = carry4
  80. &paddq("mm1","mm4"); # mm1 = carry4 + r[5] + w*a[5]
  81. &movd("mm5",&DWP(28,$r,"",0)); # mm5 = r[7]
  82. &paddq("mm3","mm5"); # mm3 = r[7] + w*a[7]
  83. &movd(&DWP(20,$r,"",0),"mm1");
  84. &psrlq("mm1",32); # mm1 = carry5
  85. &paddq("mm1","mm6"); # mm1 = carry5 + r[6] + w*a[6]
  86. &movd(&DWP(24,$r,"",0),"mm1");
  87. &psrlq("mm1",32); # mm1 = carry6
  88. &paddq("mm1","mm3"); # mm1 = carry6 + r[7] + w*a[7]
  89. &movd(&DWP(28,$r,"",0),"mm1");
  90. &lea($r,&DWP(32,$r));
  91. &psrlq("mm1",32); # mm1 = carry_out
  92. &sub($c,8);
  93. &jz(&label("maw_sse2_exit"));
  94. &set_label("maw_sse2_entry");
  95. &test($c,0xfffffff8);
  96. &jnz(&label("maw_sse2_unrolled"));
  97. &set_label("maw_sse2_loop",4);
  98. &movd("mm2",&DWP(0,$a)); # mm2 = a[i]
  99. &movd("mm3",&DWP(0,$r)); # mm3 = r[i]
  100. &pmuludq("mm2","mm0"); # a[i] *= w
  101. &lea($a,&DWP(4,$a));
  102. &paddq("mm1","mm3"); # carry += r[i]
  103. &paddq("mm1","mm2"); # carry += a[i]*w
  104. &movd(&DWP(0,$r),"mm1"); # r[i] = carry_low
  105. &sub($c,1);
  106. &psrlq("mm1",32); # carry = carry_high
  107. &lea($r,&DWP(4,$r));
  108. &jnz(&label("maw_sse2_loop"));
  109. &set_label("maw_sse2_exit");
  110. &movd("eax","mm1"); # c = carry_out
  111. &emms();
  112. &ret();
  113. &set_label("maw_non_sse2",16);
  114. }
  115. # function_begin prologue
  116. &push("ebp");
  117. &push("ebx");
  118. &push("esi");
  119. &push("edi");
  120. &comment("");
  121. $Low="eax";
  122. $High="edx";
  123. $a="ebx";
  124. $w="ebp";
  125. $r="edi";
  126. $c="esi";
  127. &xor($c,$c); # clear carry
  128. &mov($r,&wparam(0)); #
  129. &mov("ecx",&wparam(2)); #
  130. &mov($a,&wparam(1)); #
  131. &and("ecx",0xfffffff8); # num / 8
  132. &mov($w,&wparam(3)); #
  133. &push("ecx"); # Up the stack for a tmp variable
  134. &jz(&label("maw_finish"));
  135. &set_label("maw_loop",16);
  136. for ($i=0; $i<32; $i+=4)
  137. {
  138. &comment("Round $i");
  139. &mov("eax",&DWP($i,$a)); # *a
  140. &mul($w); # *a * w
  141. &add("eax",$c); # L(t)+= c
  142. &adc("edx",0); # H(t)+=carry
  143. &add("eax",&DWP($i,$r)); # L(t)+= *r
  144. &adc("edx",0); # H(t)+=carry
  145. &mov(&DWP($i,$r),"eax"); # *r= L(t);
  146. &mov($c,"edx"); # c= H(t);
  147. }
  148. &comment("");
  149. &sub("ecx",8);
  150. &lea($a,&DWP(32,$a));
  151. &lea($r,&DWP(32,$r));
  152. &jnz(&label("maw_loop"));
  153. &set_label("maw_finish",0);
  154. &mov("ecx",&wparam(2)); # get num
  155. &and("ecx",7);
  156. &jnz(&label("maw_finish2")); # helps branch prediction
  157. &jmp(&label("maw_end"));
  158. &set_label("maw_finish2",1);
  159. for ($i=0; $i<7; $i++)
  160. {
  161. &comment("Tail Round $i");
  162. &mov("eax",&DWP($i*4,$a)); # *a
  163. &mul($w); # *a * w
  164. &add("eax",$c); # L(t)+=c
  165. &adc("edx",0); # H(t)+=carry
  166. &add("eax",&DWP($i*4,$r)); # L(t)+= *r
  167. &adc("edx",0); # H(t)+=carry
  168. &dec("ecx") if ($i != 7-1);
  169. &mov(&DWP($i*4,$r),"eax"); # *r= L(t);
  170. &mov($c,"edx"); # c= H(t);
  171. &jz(&label("maw_end")) if ($i != 7-1);
  172. }
  173. &set_label("maw_end",0);
  174. &mov("eax",$c);
  175. &pop("ecx"); # clear variable from
  176. &function_end($name);
  177. }
  178. sub bn_mul_words
  179. {
  180. local($name)=@_;
  181. &function_begin_B($name,$sse2?"EXTRN\t_OPENSSL_ia32cap_P:DWORD":"");
  182. $r="eax";
  183. $a="edx";
  184. $c="ecx";
  185. if ($sse2) {
  186. &picmeup("eax","OPENSSL_ia32cap_P");
  187. &bt(&DWP(0,"eax"),26);
  188. &jnc(&label("mw_non_sse2"));
  189. &mov($r,&wparam(0));
  190. &mov($a,&wparam(1));
  191. &mov($c,&wparam(2));
  192. &movd("mm0",&wparam(3)); # mm0 = w
  193. &pxor("mm1","mm1"); # mm1 = carry = 0
  194. &set_label("mw_sse2_loop",16);
  195. &movd("mm2",&DWP(0,$a)); # mm2 = a[i]
  196. &pmuludq("mm2","mm0"); # a[i] *= w
  197. &lea($a,&DWP(4,$a));
  198. &paddq("mm1","mm2"); # carry += a[i]*w
  199. &movd(&DWP(0,$r),"mm1"); # r[i] = carry_low
  200. &sub($c,1);
  201. &psrlq("mm1",32); # carry = carry_high
  202. &lea($r,&DWP(4,$r));
  203. &jnz(&label("mw_sse2_loop"));
  204. &movd("eax","mm1"); # return carry
  205. &emms();
  206. &ret();
  207. &set_label("mw_non_sse2",16);
  208. }
  209. # function_begin prologue
  210. &push("ebp");
  211. &push("ebx");
  212. &push("esi");
  213. &push("edi");
  214. &comment("");
  215. $Low="eax";
  216. $High="edx";
  217. $a="ebx";
  218. $w="ecx";
  219. $r="edi";
  220. $c="esi";
  221. $num="ebp";
  222. &xor($c,$c); # clear carry
  223. &mov($r,&wparam(0)); #
  224. &mov($a,&wparam(1)); #
  225. &mov($num,&wparam(2)); #
  226. &mov($w,&wparam(3)); #
  227. &and($num,0xfffffff8); # num / 8
  228. &jz(&label("mw_finish"));
  229. &set_label("mw_loop",0);
  230. for ($i=0; $i<32; $i+=4)
  231. {
  232. &comment("Round $i");
  233. &mov("eax",&DWP($i,$a,"",0)); # *a
  234. &mul($w); # *a * w
  235. &add("eax",$c); # L(t)+=c
  236. # XXX
  237. &adc("edx",0); # H(t)+=carry
  238. &mov(&DWP($i,$r,"",0),"eax"); # *r= L(t);
  239. &mov($c,"edx"); # c= H(t);
  240. }
  241. &comment("");
  242. &add($a,32);
  243. &add($r,32);
  244. &sub($num,8);
  245. &jz(&label("mw_finish"));
  246. &jmp(&label("mw_loop"));
  247. &set_label("mw_finish",0);
  248. &mov($num,&wparam(2)); # get num
  249. &and($num,7);
  250. &jnz(&label("mw_finish2"));
  251. &jmp(&label("mw_end"));
  252. &set_label("mw_finish2",1);
  253. for ($i=0; $i<7; $i++)
  254. {
  255. &comment("Tail Round $i");
  256. &mov("eax",&DWP($i*4,$a,"",0));# *a
  257. &mul($w); # *a * w
  258. &add("eax",$c); # L(t)+=c
  259. # XXX
  260. &adc("edx",0); # H(t)+=carry
  261. &mov(&DWP($i*4,$r,"",0),"eax");# *r= L(t);
  262. &mov($c,"edx"); # c= H(t);
  263. &dec($num) if ($i != 7-1);
  264. &jz(&label("mw_end")) if ($i != 7-1);
  265. }
  266. &set_label("mw_end",0);
  267. &mov("eax",$c);
  268. &function_end($name);
  269. }
  270. sub bn_sqr_words
  271. {
  272. local($name)=@_;
  273. &function_begin_B($name,$sse2?"EXTRN\t_OPENSSL_ia32cap_P:DWORD":"");
  274. $r="eax";
  275. $a="edx";
  276. $c="ecx";
  277. if ($sse2) {
  278. &picmeup("eax","OPENSSL_ia32cap_P");
  279. &bt(&DWP(0,"eax"),26);
  280. &jnc(&label("sqr_non_sse2"));
  281. &mov($r,&wparam(0));
  282. &mov($a,&wparam(1));
  283. &mov($c,&wparam(2));
  284. &set_label("sqr_sse2_loop",16);
  285. &movd("mm0",&DWP(0,$a)); # mm0 = a[i]
  286. &pmuludq("mm0","mm0"); # a[i] *= a[i]
  287. &lea($a,&DWP(4,$a)); # a++
  288. &movq(&DWP(0,$r),"mm0"); # r[i] = a[i]*a[i]
  289. &sub($c,1);
  290. &lea($r,&DWP(8,$r)); # r += 2
  291. &jnz(&label("sqr_sse2_loop"));
  292. &emms();
  293. &ret();
  294. &set_label("sqr_non_sse2",16);
  295. }
  296. # function_begin prologue
  297. &push("ebp");
  298. &push("ebx");
  299. &push("esi");
  300. &push("edi");
  301. &comment("");
  302. $r="esi";
  303. $a="edi";
  304. $num="ebx";
  305. &mov($r,&wparam(0)); #
  306. &mov($a,&wparam(1)); #
  307. &mov($num,&wparam(2)); #
  308. &and($num,0xfffffff8); # num / 8
  309. &jz(&label("sw_finish"));
  310. &set_label("sw_loop",0);
  311. for ($i=0; $i<32; $i+=4)
  312. {
  313. &comment("Round $i");
  314. &mov("eax",&DWP($i,$a,"",0)); # *a
  315. # XXX
  316. &mul("eax"); # *a * *a
  317. &mov(&DWP($i*2,$r,"",0),"eax"); #
  318. &mov(&DWP($i*2+4,$r,"",0),"edx");#
  319. }
  320. &comment("");
  321. &add($a,32);
  322. &add($r,64);
  323. &sub($num,8);
  324. &jnz(&label("sw_loop"));
  325. &set_label("sw_finish",0);
  326. &mov($num,&wparam(2)); # get num
  327. &and($num,7);
  328. &jz(&label("sw_end"));
  329. for ($i=0; $i<7; $i++)
  330. {
  331. &comment("Tail Round $i");
  332. &mov("eax",&DWP($i*4,$a,"",0)); # *a
  333. # XXX
  334. &mul("eax"); # *a * *a
  335. &mov(&DWP($i*8,$r,"",0),"eax"); #
  336. &dec($num) if ($i != 7-1);
  337. &mov(&DWP($i*8+4,$r,"",0),"edx");
  338. &jz(&label("sw_end")) if ($i != 7-1);
  339. }
  340. &set_label("sw_end",0);
  341. &function_end($name);
  342. }
  343. sub bn_div_words
  344. {
  345. local($name)=@_;
  346. &function_begin_B($name,"");
  347. &mov("edx",&wparam(0)); #
  348. &mov("eax",&wparam(1)); #
  349. &mov("ecx",&wparam(2)); #
  350. &div("ecx");
  351. &ret();
  352. &function_end_B($name);
  353. }
  354. sub bn_add_words
  355. {
  356. local($name)=@_;
  357. &function_begin($name,"");
  358. &comment("");
  359. $a="esi";
  360. $b="edi";
  361. $c="eax";
  362. $r="ebx";
  363. $tmp1="ecx";
  364. $tmp2="edx";
  365. $num="ebp";
  366. &mov($r,&wparam(0)); # get r
  367. &mov($a,&wparam(1)); # get a
  368. &mov($b,&wparam(2)); # get b
  369. &mov($num,&wparam(3)); # get num
  370. &xor($c,$c); # clear carry
  371. &and($num,0xfffffff8); # num / 8
  372. &jz(&label("aw_finish"));
  373. &set_label("aw_loop",0);
  374. for ($i=0; $i<8; $i++)
  375. {
  376. &comment("Round $i");
  377. &mov($tmp1,&DWP($i*4,$a,"",0)); # *a
  378. &mov($tmp2,&DWP($i*4,$b,"",0)); # *b
  379. &add($tmp1,$c);
  380. &mov($c,0);
  381. &adc($c,$c);
  382. &add($tmp1,$tmp2);
  383. &adc($c,0);
  384. &mov(&DWP($i*4,$r,"",0),$tmp1); # *r
  385. }
  386. &comment("");
  387. &add($a,32);
  388. &add($b,32);
  389. &add($r,32);
  390. &sub($num,8);
  391. &jnz(&label("aw_loop"));
  392. &set_label("aw_finish",0);
  393. &mov($num,&wparam(3)); # get num
  394. &and($num,7);
  395. &jz(&label("aw_end"));
  396. for ($i=0; $i<7; $i++)
  397. {
  398. &comment("Tail Round $i");
  399. &mov($tmp1,&DWP($i*4,$a,"",0)); # *a
  400. &mov($tmp2,&DWP($i*4,$b,"",0));# *b
  401. &add($tmp1,$c);
  402. &mov($c,0);
  403. &adc($c,$c);
  404. &add($tmp1,$tmp2);
  405. &adc($c,0);
  406. &dec($num) if ($i != 6);
  407. &mov(&DWP($i*4,$r,"",0),$tmp1); # *r
  408. &jz(&label("aw_end")) if ($i != 6);
  409. }
  410. &set_label("aw_end",0);
  411. # &mov("eax",$c); # $c is "eax"
  412. &function_end($name);
  413. }
  414. sub bn_sub_words
  415. {
  416. local($name)=@_;
  417. &function_begin($name,"");
  418. &comment("");
  419. $a="esi";
  420. $b="edi";
  421. $c="eax";
  422. $r="ebx";
  423. $tmp1="ecx";
  424. $tmp2="edx";
  425. $num="ebp";
  426. &mov($r,&wparam(0)); # get r
  427. &mov($a,&wparam(1)); # get a
  428. &mov($b,&wparam(2)); # get b
  429. &mov($num,&wparam(3)); # get num
  430. &xor($c,$c); # clear carry
  431. &and($num,0xfffffff8); # num / 8
  432. &jz(&label("aw_finish"));
  433. &set_label("aw_loop",0);
  434. for ($i=0; $i<8; $i++)
  435. {
  436. &comment("Round $i");
  437. &mov($tmp1,&DWP($i*4,$a,"",0)); # *a
  438. &mov($tmp2,&DWP($i*4,$b,"",0)); # *b
  439. &sub($tmp1,$c);
  440. &mov($c,0);
  441. &adc($c,$c);
  442. &sub($tmp1,$tmp2);
  443. &adc($c,0);
  444. &mov(&DWP($i*4,$r,"",0),$tmp1); # *r
  445. }
  446. &comment("");
  447. &add($a,32);
  448. &add($b,32);
  449. &add($r,32);
  450. &sub($num,8);
  451. &jnz(&label("aw_loop"));
  452. &set_label("aw_finish",0);
  453. &mov($num,&wparam(3)); # get num
  454. &and($num,7);
  455. &jz(&label("aw_end"));
  456. for ($i=0; $i<7; $i++)
  457. {
  458. &comment("Tail Round $i");
  459. &mov($tmp1,&DWP($i*4,$a,"",0)); # *a
  460. &mov($tmp2,&DWP($i*4,$b,"",0));# *b
  461. &sub($tmp1,$c);
  462. &mov($c,0);
  463. &adc($c,$c);
  464. &sub($tmp1,$tmp2);
  465. &adc($c,0);
  466. &dec($num) if ($i != 6);
  467. &mov(&DWP($i*4,$r,"",0),$tmp1); # *r
  468. &jz(&label("aw_end")) if ($i != 6);
  469. }
  470. &set_label("aw_end",0);
  471. # &mov("eax",$c); # $c is "eax"
  472. &function_end($name);
  473. }
  474. sub bn_sub_part_words
  475. {
  476. local($name)=@_;
  477. &function_begin($name,"");
  478. &comment("");
  479. $a="esi";
  480. $b="edi";
  481. $c="eax";
  482. $r="ebx";
  483. $tmp1="ecx";
  484. $tmp2="edx";
  485. $num="ebp";
  486. &mov($r,&wparam(0)); # get r
  487. &mov($a,&wparam(1)); # get a
  488. &mov($b,&wparam(2)); # get b
  489. &mov($num,&wparam(3)); # get num
  490. &xor($c,$c); # clear carry
  491. &and($num,0xfffffff8); # num / 8
  492. &jz(&label("aw_finish"));
  493. &set_label("aw_loop",0);
  494. for ($i=0; $i<8; $i++)
  495. {
  496. &comment("Round $i");
  497. &mov($tmp1,&DWP($i*4,$a,"",0)); # *a
  498. &mov($tmp2,&DWP($i*4,$b,"",0)); # *b
  499. &sub($tmp1,$c);
  500. &mov($c,0);
  501. &adc($c,$c);
  502. &sub($tmp1,$tmp2);
  503. &adc($c,0);
  504. &mov(&DWP($i*4,$r,"",0),$tmp1); # *r
  505. }
  506. &comment("");
  507. &add($a,32);
  508. &add($b,32);
  509. &add($r,32);
  510. &sub($num,8);
  511. &jnz(&label("aw_loop"));
  512. &set_label("aw_finish",0);
  513. &mov($num,&wparam(3)); # get num
  514. &and($num,7);
  515. &jz(&label("aw_end"));
  516. for ($i=0; $i<7; $i++)
  517. {
  518. &comment("Tail Round $i");
  519. &mov($tmp1,&DWP(0,$a,"",0)); # *a
  520. &mov($tmp2,&DWP(0,$b,"",0));# *b
  521. &sub($tmp1,$c);
  522. &mov($c,0);
  523. &adc($c,$c);
  524. &sub($tmp1,$tmp2);
  525. &adc($c,0);
  526. &mov(&DWP(0,$r,"",0),$tmp1); # *r
  527. &add($a, 4);
  528. &add($b, 4);
  529. &add($r, 4);
  530. &dec($num) if ($i != 6);
  531. &jz(&label("aw_end")) if ($i != 6);
  532. }
  533. &set_label("aw_end",0);
  534. &cmp(&wparam(4),0);
  535. &je(&label("pw_end"));
  536. &mov($num,&wparam(4)); # get dl
  537. &cmp($num,0);
  538. &je(&label("pw_end"));
  539. &jge(&label("pw_pos"));
  540. &comment("pw_neg");
  541. &mov($tmp2,0);
  542. &sub($tmp2,$num);
  543. &mov($num,$tmp2);
  544. &and($num,0xfffffff8); # num / 8
  545. &jz(&label("pw_neg_finish"));
  546. &set_label("pw_neg_loop",0);
  547. for ($i=0; $i<8; $i++)
  548. {
  549. &comment("dl<0 Round $i");
  550. &mov($tmp1,0);
  551. &mov($tmp2,&DWP($i*4,$b,"",0)); # *b
  552. &sub($tmp1,$c);
  553. &mov($c,0);
  554. &adc($c,$c);
  555. &sub($tmp1,$tmp2);
  556. &adc($c,0);
  557. &mov(&DWP($i*4,$r,"",0),$tmp1); # *r
  558. }
  559. &comment("");
  560. &add($b,32);
  561. &add($r,32);
  562. &sub($num,8);
  563. &jnz(&label("pw_neg_loop"));
  564. &set_label("pw_neg_finish",0);
  565. &mov($tmp2,&wparam(4)); # get dl
  566. &mov($num,0);
  567. &sub($num,$tmp2);
  568. &and($num,7);
  569. &jz(&label("pw_end"));
  570. for ($i=0; $i<7; $i++)
  571. {
  572. &comment("dl<0 Tail Round $i");
  573. &mov($tmp1,0);
  574. &mov($tmp2,&DWP($i*4,$b,"",0));# *b
  575. &sub($tmp1,$c);
  576. &mov($c,0);
  577. &adc($c,$c);
  578. &sub($tmp1,$tmp2);
  579. &adc($c,0);
  580. &dec($num) if ($i != 6);
  581. &mov(&DWP($i*4,$r,"",0),$tmp1); # *r
  582. &jz(&label("pw_end")) if ($i != 6);
  583. }
  584. &jmp(&label("pw_end"));
  585. &set_label("pw_pos",0);
  586. &and($num,0xfffffff8); # num / 8
  587. &jz(&label("pw_pos_finish"));
  588. &set_label("pw_pos_loop",0);
  589. for ($i=0; $i<8; $i++)
  590. {
  591. &comment("dl>0 Round $i");
  592. &mov($tmp1,&DWP($i*4,$a,"",0)); # *a
  593. &sub($tmp1,$c);
  594. &mov(&DWP($i*4,$r,"",0),$tmp1); # *r
  595. &jnc(&label("pw_nc".$i));
  596. }
  597. &comment("");
  598. &add($a,32);
  599. &add($r,32);
  600. &sub($num,8);
  601. &jnz(&label("pw_pos_loop"));
  602. &set_label("pw_pos_finish",0);
  603. &mov($num,&wparam(4)); # get dl
  604. &and($num,7);
  605. &jz(&label("pw_end"));
  606. for ($i=0; $i<7; $i++)
  607. {
  608. &comment("dl>0 Tail Round $i");
  609. &mov($tmp1,&DWP($i*4,$a,"",0)); # *a
  610. &sub($tmp1,$c);
  611. &mov(&DWP($i*4,$r,"",0),$tmp1); # *r
  612. &jnc(&label("pw_tail_nc".$i));
  613. &dec($num) if ($i != 6);
  614. &jz(&label("pw_end")) if ($i != 6);
  615. }
  616. &mov($c,1);
  617. &jmp(&label("pw_end"));
  618. &set_label("pw_nc_loop",0);
  619. for ($i=0; $i<8; $i++)
  620. {
  621. &mov($tmp1,&DWP($i*4,$a,"",0)); # *a
  622. &mov(&DWP($i*4,$r,"",0),$tmp1); # *r
  623. &set_label("pw_nc".$i,0);
  624. }
  625. &comment("");
  626. &add($a,32);
  627. &add($r,32);
  628. &sub($num,8);
  629. &jnz(&label("pw_nc_loop"));
  630. &mov($num,&wparam(4)); # get dl
  631. &and($num,7);
  632. &jz(&label("pw_nc_end"));
  633. for ($i=0; $i<7; $i++)
  634. {
  635. &mov($tmp1,&DWP($i*4,$a,"",0)); # *a
  636. &mov(&DWP($i*4,$r,"",0),$tmp1); # *r
  637. &set_label("pw_tail_nc".$i,0);
  638. &dec($num) if ($i != 6);
  639. &jz(&label("pw_nc_end")) if ($i != 6);
  640. }
  641. &set_label("pw_nc_end",0);
  642. &mov($c,0);
  643. &set_label("pw_end",0);
  644. # &mov("eax",$c); # $c is "eax"
  645. &function_end($name);
  646. }