gencios_reg_20 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. #!/usr/bin/perl
  2. # cudadl version 0.8: Compute discrete logs in smooth group orders
  3. # using CUDA
  4. # Copyright (C) 2012 by Ryan Henry and Ian Goldberg
  5. # {rhenry,iang}@cs.uwaterloo.ca
  6. #
  7. # This program is free software: you can redistribute it and/or modify
  8. # it under the terms of version 3 of the GNU General Public License as
  9. # published by the Free Software Foundation.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. use strict;
  19. die "Usage: $0 WORDS\n" unless $#ARGV == 0;
  20. my $WORDS = shift;
  21. my $WORDSm1 = ($WORDS-1);
  22. my $WORDSp1 = ($WORDS+1);
  23. my $WORDSp2 = ($WORDS+2);
  24. my $i;
  25. ## Output an evil hack that declares a bunch of registers in the module
  26. ## scope
  27. print <<EOA;
  28. // An evil hack that declares a bunch of registers in the module scope
  29. __device__ __noinline__ void evilhack() {
  30. asm("ret;}\\n"
  31. ".reg.u32 \$xr<$WORDSp1>;\\n"
  32. ".reg.u32 \$cg<$WORDS>;\\n"
  33. ".reg.u32 \$cy<$WORDS>;\\n"
  34. ".reg.u32 \$yi,\$crp,\$m;\\n"
  35. ".reg.u64 \$cs,\$ct;\\n"
  36. ".reg.u32 \$zr<$WORDSp2>;\\n"
  37. ".reg.u32 \$crho<$WORDS>;\\n"
  38. ".func hackend {\\n"
  39. EOA
  40. print "\t\"ret.uni;\\n\"\n";
  41. print " );\n";
  42. print "}\n";
  43. print <<'EOA';
  44. __device__ inline void loadx(unsigned int *x)
  45. {
  46. asm(
  47. EOA
  48. for ($i=0;$i<$WORDS;++$i) {
  49. my $xoff = $i*4;
  50. print "\t\"ld.global.u32 \$xr$i, [%[x]+$xoff];\\n\"\n";
  51. }
  52. print "\t\"// Load c_rho into registers\\n\"\n";
  53. my ($xoff, $xoffm1);
  54. my $croff;
  55. for($i=0;$i<$WORDS;++$i) {
  56. $croff = $i*4;
  57. print "\t\"ld.const.u32 \$crho$i, [c_rho+$croff];\\n\"\n";
  58. }
  59. print "\t\"mov.u32 \$crp, %[crp];\\n\"\n";
  60. print "\t\"// Load c_g into registers\\n\"\n";
  61. for($i=0;$i<$WORDS;++$i) {
  62. $croff = $i*4;
  63. print "\t\"ld.const.u32 \$cg$i, [c_g+$croff];\\n\"\n";
  64. }
  65. print "\t\"// Load c_y into registers\\n\"\n";
  66. for($i=0;$i<$WORDS;++$i) {
  67. $croff = $i*4;
  68. print "\t\"ld.const.u32 \$cy$i, [c_y+$croff];\\n\"\n";
  69. }
  70. print <<'EOA';
  71. : : [x] "l" (x), [crp] "r" (c_rho_prime));
  72. }
  73. __device__ inline void savex(unsigned int *x)
  74. {
  75. asm(
  76. EOA
  77. for ($i=0;$i<$WORDS;++$i) {
  78. my $xoff = $i*4;
  79. print "\t\"st.global.u32 [%[x]+$xoff], \$xr$i;\\n\"\n";
  80. }
  81. print <<'EOA';
  82. : : [x] "l" (x));
  83. }
  84. EOA
  85. print <<'EOA';
  86. __device__ void modmul(int multtype)
  87. // x <- (x * y) * r_inv (mod rho);
  88. // where y is (multtype == 0 ? c_g : multtype == 1 ? c_y : x)
  89. {
  90. asm(
  91. ".reg.pred $mtp0,$mtp1;\n"
  92. EOA
  93. print " \".reg.pred \$retaddr<", $WORDS-2, ">;\\n\"\n";
  94. print <<'EOA';
  95. "mov.u32 $m, 0;\n"
  96. "setp.eq.u32 $mtp0, %[tp], $m;\n"
  97. "mov.u32 $m, 1;\n"
  98. "setp.eq.u32 $mtp1, %[tp], $m;\n"
  99. : : [tp] "r" (multtype));
  100. EOA
  101. print " asm(\n";
  102. print "\t\"// First iteration: i=0 and z is unset\\n\"\n";
  103. # Pick the correct value of $yi
  104. print "\t\"selp.u32 \$yi, \$cg0, \$xr0, \$mtp0;\\n\"\n";
  105. print "\t\"selp.u32 \$yi, \$cy0, \$yi, \$mtp1;\\n\"\n";
  106. print "\t\"mul.wide.u32 \$cs, \$xr0, \$yi;\\n\"\n";
  107. print "\t\"cvt.u32.u64 \$zr0, \$cs;\\n\"\n";
  108. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\"\n";
  109. for($i=1; $i<$WORDS; ++$i) {
  110. $xoff = $i*32*4;
  111. print "\t\"mad.wide.u32 \$cs, \$xr$i, \$yi, \$cs;\\n\"\n";
  112. print "\t\"cvt.u32.u64 \$zr$i, \$cs;\\n\"\n";
  113. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\"\n";
  114. }
  115. print "\t\"cvt.u32.u64 \$zr$WORDS, \$cs;\\n\"\n";
  116. print "\t\"mul.lo.u32 \$m, \$zr0, \$crp;\\n\"\n";
  117. print "\t\"cvt.u64.u32 \$ct, \$zr0;\\n\"\n";
  118. print "\t\"mad.wide.u32 \$cs, \$m, \$crho0, \$ct;\\n\"\n";
  119. for($i=1;$i<$WORDS;++$i) {
  120. my $im1 = ($i-1);
  121. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\"\n";
  122. print "\t\"cvt.u64.u32 \$ct, \$zr$i;\\n\"\n";
  123. print "\t\"add.u64 \$cs, \$cs, \$ct;\\n\"\n";
  124. print "\t\"mad.wide.u32 \$cs, \$m, \$crho$i, \$cs;\\n\"\n";
  125. print "\t\"cvt.u32.u64 \$zr$im1, \$cs;\\n\"\n";
  126. }
  127. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\"\n";
  128. print "\t\"cvt.u64.u32 \$ct, \$zr$WORDS;\\n\"\n";
  129. print "\t\"add.u64 \$cs, \$cs, \$ct;\\n\"\n";
  130. print "\t\"cvt.u32.u64 \$zr$WORDSm1, \$cs;\\n\"\n";
  131. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\"\n";
  132. print "\t\"cvt.u32.u64 \$zr$WORDS, \$cs;\\n\"\n";
  133. my $j;
  134. for ($j=1; $j<$WORDS-1; ++$j) {
  135. print <<'EOA';
  136. "// Middle iterations\n"
  137. EOA
  138. # Pick the correct value of $yi
  139. my $yioff = $j*4;
  140. print "\t\"selp.u32 \$yi, \$cg$j, \$xr$j, \$mtp0;\\n\"\n";
  141. print "\t\"selp.u32 \$yi, \$cy$j, \$yi, \$mtp1;\\n\"\n";
  142. my $jm1 = $j-1;
  143. my $jm2 = $j-2;
  144. if ($j==1) {
  145. print "\t\"setp.eq.u32 \$retaddr0,\$xr0,\$xr0;\\n\"\n";
  146. } else {
  147. print "\t\"setp.eq.u32 \$retaddr$jm1|\$retaddr$jm2,\$xr0,\$xr0;\\n\"\n";
  148. }
  149. print "\t\"bra.uni innerloop;\\n\"\n";
  150. print "\t\"innerret$jm1:\\n\"\n";
  151. }
  152. print <<'EOA';
  153. "// Last iteration: store the output in x instead of z\n"
  154. EOA
  155. # Pick the correct value of $yi
  156. my $yioff = ($WORDSm1)*4;
  157. print "\t\"selp.u32 \$yi, \$cg$WORDSm1, \$xr$WORDSm1, \$mtp0;\\n\"\n";
  158. print "\t\"selp.u32 \$yi, \$cy$WORDSm1, \$yi, \$mtp1;\\n\"\n";
  159. print "\t\"cvt.u64.u32 \$ct, \$zr0;\\n\"\n";
  160. print "\t\"mad.wide.u32 \$cs, \$xr0, \$yi, \$ct;\\n\"\n";
  161. print "\t\"cvt.u32.u64 \$zr0, \$cs;\\n\"\n";
  162. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\"\n";
  163. for($i=1; $i<$WORDS; ++$i) {
  164. $xoff = $i*32*4;
  165. print "\t\"cvt.u64.u32 \$ct, \$zr$i;\\n\"\n";
  166. print "\t\"add.u64 \$cs, \$cs, \$ct;\\n\"\n";
  167. print "\t\"mad.wide.u32 \$cs, \$xr$i, \$yi, \$cs;\\n\"\n";
  168. print "\t\"cvt.u32.u64 \$zr$i, \$cs;\\n\"\n";
  169. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\"\n";
  170. }
  171. print "\t\"cvt.u64.u32 \$ct, \$zr$WORDS;\\n\"\n";
  172. print "\t\"add.u64 \$cs, \$cs, \$ct;\\n\"\n";
  173. print "\t\"cvt.u32.u64 \$zr$WORDS, \$cs;\\n\"\n";
  174. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\"\n";
  175. print "\t\"cvt.u32.u64 \$zr$WORDSp1, \$cs;\\n\"\n";
  176. print "\t\"mul.lo.u32 \$m, \$zr0, \$crp;\\n\"\n";
  177. print "\t\"cvt.u64.u32 \$ct, \$zr0;\\n\"\n";
  178. print "\t\"mad.wide.u32 \$cs, \$m, \$crho0, \$ct;\\n\"\n";
  179. for($i=1;$i<$WORDS;++$i) {
  180. my $im1 = $i-1;
  181. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\"\n";
  182. print "\t\"cvt.u64.u32 \$ct, \$zr$i;\\n\"\n";
  183. print "\t\"add.u64 \$cs, \$cs, \$ct;\\n\"\n";
  184. print "\t\"mad.wide.u32 \$cs, \$m, \$crho$i, \$cs;\\n\"\n";
  185. print "\t\"cvt.u32.u64 \$xr$im1, \$cs;\\n\"\n";
  186. }
  187. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\"\n";
  188. print "\t\"cvt.u64.u32 \$ct, \$zr$WORDS;\\n\"\n";
  189. print "\t\"add.u64 \$cs, \$cs, \$ct;\\n\"\n";
  190. print "\t\"cvt.u32.u64 \$xr$WORDSm1, \$cs;\\n\"\n";
  191. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\"\n";
  192. print "\t\"cvt.u64.u32 \$ct, \$zr$WORDSp1;\\n\"\n";
  193. print "\t\"add.u64 \$cs, \$cs, \$ct;\\n\"\n";
  194. print "\t\"cvt.u32.u64 \$xr$WORDS, \$cs;\\n\"\n";
  195. print <<'EOA';
  196. );
  197. EOA
  198. # If x >= c_rho, x <- x - c_rho
  199. print " asm(\n";
  200. print "\t\".reg.pred \$gtP,\$ltP;\\n\"\n";
  201. print "\t\"mov.u32 \$m, 0;\\n\"\n";
  202. print "\t\"setp.gt.u32 \$gtP, \$xr$WORDS, \$m;\\n\"\n";
  203. print "\t\"\@\$gtP bra \$comp_done;\\n\"\n";
  204. for ($i = $WORDS-1; $i >= 1; --$i) {
  205. print "\t\"setp.gt.u32 \$gtP, \$xr$i, \$crho$i;\\n\"\n";
  206. print "\t\"\@\$gtP bra \$comp_done;\\n\"\n";
  207. print "\t\"setp.lt.u32 \$ltP, \$xr$i, \$crho$i;\\n\"\n";
  208. print "\t\"\@\$ltP bra \$comp_done;\\n\"\n";
  209. }
  210. print "\t\"setp.ge.u32 \$gtP, \$xr0, \$crho0;\\n\"\n";
  211. print "\t\"\$comp_done:\\n\"\n";
  212. # Do the subtraction
  213. print "\t\"@\$gtP sub.cc.u32 \$xr0, \$xr0, \$crho0;\\n\"\n";
  214. for ($i=1; $i<$WORDS; ++$i) {
  215. print "\t\"@\$gtP subc.cc.u32 \$xr$i, \$xr$i, \$crho$i;\\n\"\n";
  216. }
  217. print "\t\"@\$gtP subc.u32 \$xr$WORDS, \$xr$WORDS, \$m;\\n\"\n";
  218. print "\t\"bra.uni mulmoddone;\\n\"\n";
  219. print "\t\"innerloop:\\n\"\n";
  220. print "\t\"cvt.u64.u32 \$ct, \$zr0;\\n\"\n";
  221. print "\t\"mad.wide.u32 \$cs, \$xr0, \$yi, \$ct;\\n\"\n";
  222. print "\t\"cvt.u32.u64 \$zr0, \$cs;\\n\"\n";
  223. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\"\n";
  224. my $i;
  225. for($i=1; $i<$WORDS; ++$i) {
  226. print "\t\"cvt.u64.u32 \$ct, \$zr$i;\\n\"\n";
  227. print "\t\"add.u64 \$cs, \$cs, \$ct;\\n\"\n";
  228. print "\t\"mad.wide.u32 \$cs, \$xr$i, \$yi, \$cs;\\n\"\n";
  229. print "\t\"cvt.u32.u64 \$zr$i, \$cs;\\n\"\n";
  230. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\"\n";
  231. }
  232. print "\t\"cvt.u64.u32 \$ct, \$zr$WORDS;\\n\"\n";
  233. print "\t\"add.u64 \$cs, \$cs, \$ct;\\n\"\n";
  234. print "\t\"cvt.u32.u64 \$zr$WORDS, \$cs;\\n\"\n";
  235. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\"\n";
  236. print "\t\"cvt.u32.u64 \$zr$WORDSp1, \$cs;\\n\"\n";
  237. print "\t\"mul.lo.u32 \$m, \$zr0, \$crp;\\n\"\n";
  238. print "\t\"cvt.u64.u32 \$ct, \$zr0;\\n\"\n";
  239. print "\t\"mad.wide.u32 \$cs, \$m, \$crho0, \$ct;\\n\"\n";
  240. for($i=1;$i<$WORDS;++$i) {
  241. my $im1 = ($i-1);
  242. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\"\n";
  243. print "\t\"cvt.u64.u32 \$ct, \$zr$i;\\n\"\n";
  244. print "\t\"add.u64 \$cs, \$cs, \$ct;\\n\"\n";
  245. print "\t\"mad.wide.u32 \$cs, \$m, \$crho$i, \$cs;\\n\"\n";
  246. print "\t\"cvt.u32.u64 \$zr$im1, \$cs;\\n\"\n";
  247. }
  248. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\"\n";
  249. print "\t\"cvt.u64.u32 \$ct, \$zr$WORDS;\\n\"\n";
  250. print "\t\"add.u64 \$cs, \$cs, \$ct;\\n\"\n";
  251. print "\t\"cvt.u32.u64 \$zr$WORDSm1, \$cs;\\n\"\n";
  252. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\"\n";
  253. print "\t\"cvt.u32.u64 \$zr$WORDS, \$cs;\\n\"\n";
  254. for ($i=0;$i<$WORDS-2;++$i) {
  255. print "\t\"\@\$retaddr$i bra.uni innerret$i;\\n\"\n";
  256. }
  257. print "\t\"mulmoddone:\\n\"\n";
  258. print " );\n";
  259. print "}\n";
  260. print <<'EOA';
  261. __device__ inline void write_dp(unsigned int *buf, unsigned long a, unsigned long b)
  262. {
  263. unsigned short blockid = blockIdx.x + gridDim.x*blockIdx.y;
  264. unsigned short threadid = threadIdx.x + blockDim.x*threadIdx.y + blockDim.x*blockDim.y*threadIdx.z;
  265. buf[0] = (((unsigned int)blockid) << 16) + threadid;
  266. asm(
  267. EOA
  268. for($i=0;$i<$WORDS;++$i) {
  269. my $off = 4*($i+1);
  270. print "\t\"st.global.u32 [%0+$off], \$xr$i;\\n\"\n";
  271. }
  272. print <<'EOA';
  273. : : "l" (buf));
  274. buf[WORDS+1] = (unsigned int)a;
  275. buf[WORDS+2] = a>>32;
  276. buf[WORDS+3] = (unsigned int)b;
  277. buf[WORDS+4] = b>>32;
  278. }
  279. EOA