gencios_reg_20 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. #!/usr/bin/perl
  2. # cudadl version 0.9: 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. #define CIOS_REG_DECLARE \\
  29. asm volatile ( \\
  30. ".reg.u32 \$xr<$WORDSp1>;\\n" \\
  31. ".reg.u32 \$cg<$WORDS>;\\n" \\
  32. ".reg.u32 \$cy<$WORDS>;\\n" \\
  33. ".reg.u32 \$yi,\$crp,\$m;\\n" \\
  34. ".reg.u64 \$cs,\$ct;\\n" \\
  35. ".reg.u32 \$zr<$WORDSp2>;\\n" \\
  36. ".reg.u32 \$crho<$WORDS>;\\n" \\
  37. )
  38. EOA
  39. print <<'EOA';
  40. #define CIOS_LOADX(x) \
  41. asm volatile ( \
  42. EOA
  43. for ($i=0;$i<$WORDS;++$i) {
  44. my $xoff = $i*4;
  45. print "\t\"ld.global.u32 \$xr$i, [%0+$xoff];\\n\" \\\n";
  46. }
  47. print "\t\"// Load c_rho into registers\\n\" \\\n";
  48. my ($xoff, $xoffm1);
  49. my $croff;
  50. for($i=0;$i<$WORDS;++$i) {
  51. $croff = $i*4;
  52. print "\t\"ld.const.u32 \$crho$i, [c_rho+$croff];\\n\" \\\n";
  53. }
  54. print "\t\"mov.u32 \$crp, %1;\\n\" \\\n";
  55. print "\t\"// Load c_g into registers\\n\" \\\n";
  56. for($i=0;$i<$WORDS;++$i) {
  57. $croff = $i*4;
  58. print "\t\"ld.const.u32 \$cg$i, [c_g+$croff];\\n\" \\\n";
  59. }
  60. print "\t\"// Load c_y into registers\\n\" \\\n";
  61. for($i=0;$i<$WORDS;++$i) {
  62. $croff = $i*4;
  63. print "\t\"ld.const.u32 \$cy$i, [c_y+$croff];\\n\" \\\n";
  64. }
  65. print <<'EOA';
  66. : : "l" (x), "r" (c_rho_prime))
  67. EOA
  68. print <<'EOA';
  69. #define CIOS_SAVEX(x) \
  70. asm volatile ( \
  71. EOA
  72. for ($i=0;$i<$WORDS;++$i) {
  73. my $xoff = $i*4;
  74. print "\t\"st.global.u32 [%0+$xoff], \$xr$i;\\n\" \\\n";
  75. }
  76. print <<'EOA';
  77. : : "l" (x))
  78. EOA
  79. print <<'EOA';
  80. // x <- (x * y) * r_inv (mod rho);
  81. // where y is (multtype == 0 ? c_g : multtype == 1 ? c_y : x)
  82. #define CIOS_MODMUL(multtype) \
  83. asm volatile ( \
  84. ".reg.pred $mtp0,$mtp1;\n" \
  85. EOA
  86. print " \".reg.pred \$retaddr<", $WORDS-2, ">;\\n\" \\\n";
  87. print <<'EOA';
  88. "mov.u32 $m, 0;\n" \
  89. "setp.eq.u32 $mtp0, %0, $m;\n" \
  90. "mov.u32 $m, 1;\n" \
  91. "setp.eq.u32 $mtp1, %0, $m;\n" \
  92. : : "r" (multtype)); \
  93. EOA
  94. print " asm volatile ( \\\n";
  95. print "\t\"// First iteration: i=0 and z is unset\\n\" \\\n";
  96. # Pick the correct value of $yi
  97. print "\t\"selp.u32 \$yi, \$cg0, \$xr0, \$mtp0;\\n\" \\\n";
  98. print "\t\"selp.u32 \$yi, \$cy0, \$yi, \$mtp1;\\n\" \\\n";
  99. print "\t\"mul.wide.u32 \$cs, \$xr0, \$yi;\\n\" \\\n";
  100. print "\t\"cvt.u32.u64 \$zr0, \$cs;\\n\" \\\n";
  101. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\" \\\n";
  102. for($i=1; $i<$WORDS; ++$i) {
  103. $xoff = $i*32*4;
  104. print "\t\"mad.wide.u32 \$cs, \$xr$i, \$yi, \$cs;\\n\" \\\n";
  105. print "\t\"cvt.u32.u64 \$zr$i, \$cs;\\n\" \\\n";
  106. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\" \\\n";
  107. }
  108. print "\t\"cvt.u32.u64 \$zr$WORDS, \$cs;\\n\" \\\n";
  109. print "\t\"mul.lo.u32 \$m, \$zr0, \$crp;\\n\" \\\n";
  110. print "\t\"cvt.u64.u32 \$ct, \$zr0;\\n\" \\\n";
  111. print "\t\"mad.wide.u32 \$cs, \$m, \$crho0, \$ct;\\n\" \\\n";
  112. for($i=1;$i<$WORDS;++$i) {
  113. my $im1 = ($i-1);
  114. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\" \\\n";
  115. print "\t\"cvt.u64.u32 \$ct, \$zr$i;\\n\" \\\n";
  116. print "\t\"add.u64 \$cs, \$cs, \$ct;\\n\" \\\n";
  117. print "\t\"mad.wide.u32 \$cs, \$m, \$crho$i, \$cs;\\n\" \\\n";
  118. print "\t\"cvt.u32.u64 \$zr$im1, \$cs;\\n\" \\\n";
  119. }
  120. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\" \\\n";
  121. print "\t\"cvt.u64.u32 \$ct, \$zr$WORDS;\\n\" \\\n";
  122. print "\t\"add.u64 \$cs, \$cs, \$ct;\\n\" \\\n";
  123. print "\t\"cvt.u32.u64 \$zr$WORDSm1, \$cs;\\n\" \\\n";
  124. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\" \\\n";
  125. print "\t\"cvt.u32.u64 \$zr$WORDS, \$cs;\\n\" \\\n";
  126. my $j;
  127. for ($j=1; $j<$WORDS-1; ++$j) {
  128. print <<'EOA';
  129. "// Middle iterations\n" \
  130. EOA
  131. # Pick the correct value of $yi
  132. my $yioff = $j*4;
  133. print "\t\"selp.u32 \$yi, \$cg$j, \$xr$j, \$mtp0;\\n\" \\\n";
  134. print "\t\"selp.u32 \$yi, \$cy$j, \$yi, \$mtp1;\\n\" \\\n";
  135. my $jm1 = $j-1;
  136. my $jm2 = $j-2;
  137. if ($j==1) {
  138. print "\t\"setp.eq.u32 \$retaddr0,\$xr0,\$xr0;\\n\" \\\n";
  139. } else {
  140. print "\t\"setp.eq.u32 \$retaddr$jm1|\$retaddr$jm2,\$xr0,\$xr0;\\n\" \\\n";
  141. }
  142. print "\t\"bra.uni innerloop;\\n\" \\\n";
  143. print "\t\"innerret$jm1:\\n\" \\\n";
  144. }
  145. print <<'EOA';
  146. "// Last iteration: store the output in x instead of z\n" \
  147. EOA
  148. # Pick the correct value of $yi
  149. my $yioff = ($WORDSm1)*4;
  150. print "\t\"selp.u32 \$yi, \$cg$WORDSm1, \$xr$WORDSm1, \$mtp0;\\n\" \\\n";
  151. print "\t\"selp.u32 \$yi, \$cy$WORDSm1, \$yi, \$mtp1;\\n\" \\\n";
  152. print "\t\"cvt.u64.u32 \$ct, \$zr0;\\n\" \\\n";
  153. print "\t\"mad.wide.u32 \$cs, \$xr0, \$yi, \$ct;\\n\" \\\n";
  154. print "\t\"cvt.u32.u64 \$zr0, \$cs;\\n\" \\\n";
  155. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\" \\\n";
  156. for($i=1; $i<$WORDS; ++$i) {
  157. $xoff = $i*32*4;
  158. print "\t\"cvt.u64.u32 \$ct, \$zr$i;\\n\" \\\n";
  159. print "\t\"add.u64 \$cs, \$cs, \$ct;\\n\" \\\n";
  160. print "\t\"mad.wide.u32 \$cs, \$xr$i, \$yi, \$cs;\\n\" \\\n";
  161. print "\t\"cvt.u32.u64 \$zr$i, \$cs;\\n\" \\\n";
  162. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\" \\\n";
  163. }
  164. print "\t\"cvt.u64.u32 \$ct, \$zr$WORDS;\\n\" \\\n";
  165. print "\t\"add.u64 \$cs, \$cs, \$ct;\\n\" \\\n";
  166. print "\t\"cvt.u32.u64 \$zr$WORDS, \$cs;\\n\" \\\n";
  167. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\" \\\n";
  168. print "\t\"cvt.u32.u64 \$zr$WORDSp1, \$cs;\\n\" \\\n";
  169. print "\t\"mul.lo.u32 \$m, \$zr0, \$crp;\\n\" \\\n";
  170. print "\t\"cvt.u64.u32 \$ct, \$zr0;\\n\" \\\n";
  171. print "\t\"mad.wide.u32 \$cs, \$m, \$crho0, \$ct;\\n\" \\\n";
  172. for($i=1;$i<$WORDS;++$i) {
  173. my $im1 = $i-1;
  174. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\" \\\n";
  175. print "\t\"cvt.u64.u32 \$ct, \$zr$i;\\n\" \\\n";
  176. print "\t\"add.u64 \$cs, \$cs, \$ct;\\n\" \\\n";
  177. print "\t\"mad.wide.u32 \$cs, \$m, \$crho$i, \$cs;\\n\" \\\n";
  178. print "\t\"cvt.u32.u64 \$xr$im1, \$cs;\\n\" \\\n";
  179. }
  180. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\" \\\n";
  181. print "\t\"cvt.u64.u32 \$ct, \$zr$WORDS;\\n\" \\\n";
  182. print "\t\"add.u64 \$cs, \$cs, \$ct;\\n\" \\\n";
  183. print "\t\"cvt.u32.u64 \$xr$WORDSm1, \$cs;\\n\" \\\n";
  184. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\" \\\n";
  185. print "\t\"cvt.u64.u32 \$ct, \$zr$WORDSp1;\\n\" \\\n";
  186. print "\t\"add.u64 \$cs, \$cs, \$ct;\\n\" \\\n";
  187. print "\t\"cvt.u32.u64 \$xr$WORDS, \$cs;\\n\" \\\n";
  188. print <<'EOA';
  189. ); \
  190. EOA
  191. # If x >= c_rho, x <- x - c_rho
  192. print " asm volatile ( \\\n";
  193. print "\t\".reg.pred \$gtP,\$ltP;\\n\" \\\n";
  194. print "\t\"mov.u32 \$m, 0;\\n\" \\\n";
  195. print "\t\"setp.gt.u32 \$gtP, \$xr$WORDS, \$m;\\n\" \\\n";
  196. print "\t\"\@\$gtP bra \$comp_done;\\n\" \\\n";
  197. for ($i = $WORDS-1; $i >= 1; --$i) {
  198. print "\t\"setp.gt.u32 \$gtP, \$xr$i, \$crho$i;\\n\" \\\n";
  199. print "\t\"\@\$gtP bra \$comp_done;\\n\" \\\n";
  200. print "\t\"setp.lt.u32 \$ltP, \$xr$i, \$crho$i;\\n\" \\\n";
  201. print "\t\"\@\$ltP bra \$comp_done;\\n\" \\\n";
  202. }
  203. print "\t\"setp.ge.u32 \$gtP, \$xr0, \$crho0;\\n\" \\\n";
  204. print "\t\"\$comp_done:\\n\" \\\n";
  205. # Do the subtraction
  206. print "\t\"@\$gtP sub.cc.u32 \$xr0, \$xr0, \$crho0;\\n\" \\\n";
  207. for ($i=1; $i<$WORDS; ++$i) {
  208. print "\t\"@\$gtP subc.cc.u32 \$xr$i, \$xr$i, \$crho$i;\\n\" \\\n";
  209. }
  210. print "\t\"@\$gtP subc.u32 \$xr$WORDS, \$xr$WORDS, \$m;\\n\" \\\n";
  211. print "\t\"bra.uni mulmoddone;\\n\" \\\n";
  212. print "\t\"innerloop:\\n\" \\\n";
  213. print "\t\"cvt.u64.u32 \$ct, \$zr0;\\n\" \\\n";
  214. print "\t\"mad.wide.u32 \$cs, \$xr0, \$yi, \$ct;\\n\" \\\n";
  215. print "\t\"cvt.u32.u64 \$zr0, \$cs;\\n\" \\\n";
  216. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\" \\\n";
  217. my $i;
  218. for($i=1; $i<$WORDS; ++$i) {
  219. print "\t\"cvt.u64.u32 \$ct, \$zr$i;\\n\" \\\n";
  220. print "\t\"add.u64 \$cs, \$cs, \$ct;\\n\" \\\n";
  221. print "\t\"mad.wide.u32 \$cs, \$xr$i, \$yi, \$cs;\\n\" \\\n";
  222. print "\t\"cvt.u32.u64 \$zr$i, \$cs;\\n\" \\\n";
  223. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\" \\\n";
  224. }
  225. print "\t\"cvt.u64.u32 \$ct, \$zr$WORDS;\\n\" \\\n";
  226. print "\t\"add.u64 \$cs, \$cs, \$ct;\\n\" \\\n";
  227. print "\t\"cvt.u32.u64 \$zr$WORDS, \$cs;\\n\" \\\n";
  228. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\" \\\n";
  229. print "\t\"cvt.u32.u64 \$zr$WORDSp1, \$cs;\\n\" \\\n";
  230. print "\t\"mul.lo.u32 \$m, \$zr0, \$crp;\\n\" \\\n";
  231. print "\t\"cvt.u64.u32 \$ct, \$zr0;\\n\" \\\n";
  232. print "\t\"mad.wide.u32 \$cs, \$m, \$crho0, \$ct;\\n\" \\\n";
  233. for($i=1;$i<$WORDS;++$i) {
  234. my $im1 = ($i-1);
  235. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\" \\\n";
  236. print "\t\"cvt.u64.u32 \$ct, \$zr$i;\\n\" \\\n";
  237. print "\t\"add.u64 \$cs, \$cs, \$ct;\\n\" \\\n";
  238. print "\t\"mad.wide.u32 \$cs, \$m, \$crho$i, \$cs;\\n\" \\\n";
  239. print "\t\"cvt.u32.u64 \$zr$im1, \$cs;\\n\" \\\n";
  240. }
  241. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\" \\\n";
  242. print "\t\"cvt.u64.u32 \$ct, \$zr$WORDS;\\n\" \\\n";
  243. print "\t\"add.u64 \$cs, \$cs, \$ct;\\n\" \\\n";
  244. print "\t\"cvt.u32.u64 \$zr$WORDSm1, \$cs;\\n\" \\\n";
  245. print "\t\"shr.u64 \$cs, \$cs, 32;\\n\" \\\n";
  246. print "\t\"cvt.u32.u64 \$zr$WORDS, \$cs;\\n\" \\\n";
  247. for ($i=0;$i<$WORDS-2;++$i) {
  248. print "\t\"\@\$retaddr$i bra.uni innerret$i;\\n\" \\\n";
  249. }
  250. print "\t\"mulmoddone:\\n\" \\\n";
  251. print " )\n";
  252. print <<'EOA';
  253. #define CIOS_WRITE_DP(buf, a_0, a_1, a_2, b_0, b_1, b_2) \
  254. do { \
  255. unsigned short blockid = blockIdx.x + gridDim.x*blockIdx.y; \
  256. unsigned short threadid = threadIdx.x + blockDim.x*threadIdx.y + blockDim.x*blockDim.y*threadIdx.z; \
  257. buf[0] = (((unsigned int)blockid) << 16) + threadid; \
  258. asm volatile ( \
  259. EOA
  260. for($i=0;$i<$WORDS;++$i) {
  261. my $off = 4*($i+1);
  262. print "\t\"st.u32 [%0+$off], \$xr$i;\\n\" \\\n";
  263. }
  264. print <<'EOA';
  265. : : "l" (buf)); \
  266. buf[WORDS+1] = a_0; \
  267. buf[WORDS+2] = a_1; \
  268. buf[WORDS+3] = a_2; \
  269. buf[WORDS+4] = b_0; \
  270. buf[WORDS+5] = b_1; \
  271. buf[WORDS+6] = b_2; \
  272. } while(0)
  273. EOA