2
0

alpha.pl 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. #!/usr/local/bin/perl
  2. package alpha;
  3. use Carp qw(croak cluck);
  4. $label="100";
  5. $n_debug=0;
  6. $smear_regs=1;
  7. $reg_alloc=1;
  8. $align="3";
  9. $com_start="#";
  10. sub main'asm_init_output { @out=(); }
  11. sub main'asm_get_output { return(@out); }
  12. sub main'get_labels { return(@labels); }
  13. sub main'external_label { push(@labels,@_); }
  14. # General registers
  15. %regs=( 'r0', '$0',
  16. 'r1', '$1',
  17. 'r2', '$2',
  18. 'r3', '$3',
  19. 'r4', '$4',
  20. 'r5', '$5',
  21. 'r6', '$6',
  22. 'r7', '$7',
  23. 'r8', '$8',
  24. 'r9', '$22',
  25. 'r10', '$23',
  26. 'r11', '$24',
  27. 'r12', '$25',
  28. 'r13', '$27',
  29. 'r14', '$28',
  30. 'r15', '$21', # argc == 5
  31. 'r16', '$20', # argc == 4
  32. 'r17', '$19', # argc == 3
  33. 'r18', '$18', # argc == 2
  34. 'r19', '$17', # argc == 1
  35. 'r20', '$16', # argc == 0
  36. 'r21', '$9', # save 0
  37. 'r22', '$10', # save 1
  38. 'r23', '$11', # save 2
  39. 'r24', '$12', # save 3
  40. 'r25', '$13', # save 4
  41. 'r26', '$14', # save 5
  42. 'a0', '$16',
  43. 'a1', '$17',
  44. 'a2', '$18',
  45. 'a3', '$19',
  46. 'a4', '$20',
  47. 'a5', '$21',
  48. 's0', '$9',
  49. 's1', '$10',
  50. 's2', '$11',
  51. 's3', '$12',
  52. 's4', '$13',
  53. 's5', '$14',
  54. 'zero', '$31',
  55. 'sp', '$30',
  56. );
  57. $main'reg_s0="r21";
  58. $main'reg_s1="r22";
  59. $main'reg_s2="r23";
  60. $main'reg_s3="r24";
  61. $main'reg_s4="r25";
  62. $main'reg_s5="r26";
  63. @reg=( '$0', '$1' ,'$2' ,'$3' ,'$4' ,'$5' ,'$6' ,'$7' ,'$8',
  64. '$22','$23','$24','$25','$20','$21','$27','$28');
  65. sub main'sub { &out3("subq",@_); }
  66. sub main'add { &out3("addq",@_); }
  67. sub main'mov { &out3("bis",$_[0],$_[0],$_[1]); }
  68. sub main'or { &out3("bis",@_); }
  69. sub main'bis { &out3("bis",@_); }
  70. sub main'br { &out1("br",@_); }
  71. sub main'ld { &out2("ldq",@_); }
  72. sub main'st { &out2("stq",@_); }
  73. sub main'cmpult { &out3("cmpult",@_); }
  74. sub main'cmplt { &out3("cmplt",@_); }
  75. sub main'bgt { &out2("bgt",@_); }
  76. sub main'ble { &out2("ble",@_); }
  77. sub main'blt { &out2("blt",@_); }
  78. sub main'mul { &out3("mulq",@_); }
  79. sub main'muh { &out3("umulh",@_); }
  80. $main'QWS=8;
  81. sub main'asm_add
  82. {
  83. push(@out,@_);
  84. }
  85. sub main'asm_finish
  86. {
  87. &main'file_end();
  88. print &main'asm_get_output();
  89. }
  90. sub main'asm_init
  91. {
  92. ($type,$fn)=@_;
  93. $filename=$fn;
  94. &main'asm_init_output();
  95. &main'comment("Don't even think of reading this code");
  96. &main'comment("It was automatically generated by $filename");
  97. &main'comment("Which is a perl program used to generate the alpha assember.");
  98. &main'comment("eric <eay\@cryptsoft.com>");
  99. &main'comment("");
  100. $filename =~ s/\.pl$//;
  101. &main'file($filename);
  102. }
  103. sub conv
  104. {
  105. local($r)=@_;
  106. local($v);
  107. return($regs{$r}) if defined($regs{$r});
  108. return($r);
  109. }
  110. sub main'QWPw
  111. {
  112. local($off,$reg)=@_;
  113. return(&main'QWP($off*8,$reg));
  114. }
  115. sub main'QWP
  116. {
  117. local($off,$reg)=@_;
  118. $ret="$off(".&conv($reg).")";
  119. return($ret);
  120. }
  121. sub out3
  122. {
  123. local($name,$p1,$p2,$p3)=@_;
  124. $p1=&conv($p1);
  125. $p2=&conv($p2);
  126. $p3=&conv($p3);
  127. push(@out,"\t$name\t");
  128. $l=length($p1)+1;
  129. push(@out,$p1.",");
  130. $ll=3-($l+9)/8;
  131. $tmp1=sprintf("\t" x $ll);
  132. push(@out,$tmp1);
  133. $l=length($p2)+1;
  134. push(@out,$p2.",");
  135. $ll=3-($l+9)/8;
  136. $tmp1=sprintf("\t" x $ll);
  137. push(@out,$tmp1);
  138. push(@out,&conv($p3)."\n");
  139. }
  140. sub out2
  141. {
  142. local($name,$p1,$p2,$p3)=@_;
  143. $p1=&conv($p1);
  144. $p2=&conv($p2);
  145. push(@out,"\t$name\t");
  146. $l=length($p1)+1;
  147. push(@out,$p1.",");
  148. $ll=3-($l+9)/8;
  149. $tmp1=sprintf("\t" x $ll);
  150. push(@out,$tmp1);
  151. push(@out,&conv($p2)."\n");
  152. }
  153. sub out1
  154. {
  155. local($name,$p1)=@_;
  156. $p1=&conv($p1);
  157. push(@out,"\t$name\t".$p1."\n");
  158. }
  159. sub out0
  160. {
  161. push(@out,"\t$_[0]\n");
  162. }
  163. sub main'file
  164. {
  165. local($file)=@_;
  166. local($tmp)=<<"EOF";
  167. # DEC Alpha assember
  168. # Generated from perl scripts contains in SSLeay
  169. .file 1 "$file.s"
  170. .set noat
  171. EOF
  172. push(@out,$tmp);
  173. }
  174. sub main'function_begin
  175. {
  176. local($func)=@_;
  177. print STDERR "$func\n";
  178. local($tmp)=<<"EOF";
  179. .text
  180. .align $align
  181. .globl $func
  182. .ent $func
  183. ${func}:
  184. ${func}..ng:
  185. .frame \$30,0,\$26,0
  186. .prologue 0
  187. EOF
  188. push(@out,$tmp);
  189. $stack=0;
  190. }
  191. sub main'function_end
  192. {
  193. local($func)=@_;
  194. local($tmp)=<<"EOF";
  195. ret \$31,(\$26),1
  196. .end $func
  197. EOF
  198. push(@out,$tmp);
  199. $stack=0;
  200. %label=();
  201. }
  202. sub main'function_end_A
  203. {
  204. local($func)=@_;
  205. local($tmp)=<<"EOF";
  206. ret \$31,(\$26),1
  207. EOF
  208. push(@out,$tmp);
  209. }
  210. sub main'function_end_B
  211. {
  212. local($func)=@_;
  213. $func=$under.$func;
  214. push(@out,"\t.end $func\n");
  215. $stack=0;
  216. %label=();
  217. }
  218. sub main'wparam
  219. {
  220. local($num)=@_;
  221. if ($num < 6)
  222. {
  223. $num=20-$num;
  224. return("r$num");
  225. }
  226. else
  227. { return(&main'QWP($stack+$num*8,"sp")); }
  228. }
  229. sub main'stack_push
  230. {
  231. local($num)=@_;
  232. $stack+=$num*8;
  233. &main'sub("sp",$num*8,"sp");
  234. }
  235. sub main'stack_pop
  236. {
  237. local($num)=@_;
  238. $stack-=$num*8;
  239. &main'add("sp",$num*8,"sp");
  240. }
  241. sub main'swtmp
  242. {
  243. return(&main'QWP(($_[0])*8,"sp"));
  244. }
  245. # Should use swtmp, which is above sp. Linix can trash the stack above esp
  246. #sub main'wtmp
  247. # {
  248. # local($num)=@_;
  249. #
  250. # return(&main'QWP(-($num+1)*4,"esp","",0));
  251. # }
  252. sub main'comment
  253. {
  254. foreach (@_)
  255. {
  256. if (/^\s*$/)
  257. { push(@out,"\n"); }
  258. else
  259. { push(@out,"\t$com_start $_ $com_end\n"); }
  260. }
  261. }
  262. sub main'label
  263. {
  264. if (!defined($label{$_[0]}))
  265. {
  266. $label{$_[0]}=$label;
  267. $label++;
  268. }
  269. return('$'.$label{$_[0]});
  270. }
  271. sub main'set_label
  272. {
  273. if (!defined($label{$_[0]}))
  274. {
  275. $label{$_[0]}=$label;
  276. $label++;
  277. }
  278. # push(@out,".align $align\n") if ($_[1] != 0);
  279. push(@out,'$'."$label{$_[0]}:\n");
  280. }
  281. sub main'file_end
  282. {
  283. }
  284. sub main'data_word
  285. {
  286. push(@out,"\t.long $_[0]\n");
  287. }
  288. @pool_free=();
  289. @pool_taken=();
  290. $curr_num=0;
  291. $max=0;
  292. sub main'init_pool
  293. {
  294. local($args)=@_;
  295. local($i);
  296. @pool_free=();
  297. for ($i=(14+(6-$args)); $i >= 0; $i--)
  298. {
  299. push(@pool_free,"r$i");
  300. }
  301. print STDERR "START :register pool:@pool_free\n";
  302. $curr_num=$max=0;
  303. }
  304. sub main'fin_pool
  305. {
  306. printf STDERR "END %2d:register pool:@pool_free\n",$max;
  307. }
  308. sub main'GR
  309. {
  310. local($r)=@_;
  311. local($i,@n,$_);
  312. foreach (@pool_free)
  313. {
  314. if ($r ne $_)
  315. { push(@n,$_); }
  316. else
  317. {
  318. $curr_num++;
  319. $max=$curr_num if ($curr_num > $max);
  320. }
  321. }
  322. @pool_free=@n;
  323. print STDERR "GR:@pool_free\n" if $reg_alloc;
  324. return(@_);
  325. }
  326. sub main'NR
  327. {
  328. local($num)=@_;
  329. local(@ret);
  330. $num=1 if $num == 0;
  331. ($#pool_free >= ($num-1)) || croak "out of registers: want $num, have @pool_free";
  332. while ($num > 0)
  333. {
  334. push(@ret,pop @pool_free);
  335. $curr_num++;
  336. $max=$curr_num if ($curr_num > $max);
  337. $num--
  338. }
  339. print STDERR "nr @ret\n" if $n_debug;
  340. print STDERR "NR:@pool_free\n" if $reg_alloc;
  341. return(@ret);
  342. }
  343. sub main'FR
  344. {
  345. local(@r)=@_;
  346. local(@a,$v,$w);
  347. print STDERR "fr @r\n" if $n_debug;
  348. # cluck "fr @r";
  349. for $w (@pool_free)
  350. {
  351. foreach $v (@r)
  352. {
  353. croak "double register free of $v (@pool_free)" if $w eq $v;
  354. }
  355. }
  356. foreach $v (@r)
  357. {
  358. croak "bad argument to FR" if ($v !~ /^r\d+$/);
  359. if ($smear_regs)
  360. { unshift(@pool_free,$v); }
  361. else { push(@pool_free,$v); }
  362. $curr_num--;
  363. }
  364. print STDERR "FR:@pool_free\n" if $reg_alloc;
  365. }
  366. 1;