Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

arm-xlate.pl 3.8 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #!/usr/bin/env perl
  2. # ARM assembler distiller by <appro>.
  3. my $flavour = shift;
  4. my $output = shift;
  5. open STDOUT,">$output" || die "can't open $output: $!";
  6. $flavour = "linux32" if (!$flavour or $flavour eq "void");
  7. my %GLOBALS;
  8. my $dotinlocallabels=($flavour=~/linux/)?1:0;
  9. ################################################################
  10. # directives which need special treatment on different platforms
  11. ################################################################
  12. my $arch = sub {
  13. if ($flavour =~ /linux/) { ".arch\t".join(',',@_); }
  14. else { ""; }
  15. };
  16. my $fpu = sub {
  17. if ($flavour =~ /linux/) { ".fpu\t".join(',',@_); }
  18. else { ""; }
  19. };
  20. my $hidden = sub {
  21. if ($flavour =~ /ios/) { ".private_extern\t".join(',',@_); }
  22. else { ".hidden\t".join(',',@_); }
  23. };
  24. my $comm = sub {
  25. my @args = split(/,\s*/,shift);
  26. my $name = @args[0];
  27. my $global = \$GLOBALS{$name};
  28. my $ret;
  29. if ($flavour =~ /ios32/) {
  30. $ret = ".comm\t_$name,@args[1]\n";
  31. $ret .= ".non_lazy_symbol_pointer\n";
  32. $ret .= "$name:\n";
  33. $ret .= ".indirect_symbol\t_$name\n";
  34. $ret .= ".long\t0";
  35. $name = "_$name";
  36. } else { $ret = ".comm\t".join(',',@args); }
  37. $$global = $name;
  38. $ret;
  39. };
  40. my $globl = sub {
  41. my $name = shift;
  42. my $global = \$GLOBALS{$name};
  43. my $ret;
  44. SWITCH: for ($flavour) {
  45. /ios/ && do { $name = "_$name";
  46. last;
  47. };
  48. }
  49. $ret = ".globl $name" if (!$ret);
  50. $$global = $name;
  51. $ret;
  52. };
  53. my $global = $globl;
  54. my $extern = sub {
  55. &$globl(@_);
  56. return; # return nothing
  57. };
  58. my $type = sub {
  59. if ($flavour =~ /linux/) { ".type\t".join(',',@_); }
  60. else { ""; }
  61. };
  62. my $size = sub {
  63. if ($flavour =~ /linux/) { ".size\t".join(',',@_); }
  64. else { ""; }
  65. };
  66. my $inst = sub {
  67. if ($flavour =~ /linux/) { ".inst\t".join(',',@_); }
  68. else { ".long\t".join(',',@_); }
  69. };
  70. my $asciz = sub {
  71. my $line = join(",",@_);
  72. if ($line =~ /^"(.*)"$/)
  73. { ".byte " . join(",",unpack("C*",$1),0) . "\n.align 2"; }
  74. else
  75. { ""; }
  76. };
  77. sub range {
  78. my ($r,$sfx,$start,$end) = @_;
  79. join(",",map("$r$_$sfx",($start..$end)));
  80. }
  81. sub expand_line {
  82. my $line = shift;
  83. my @ret = ();
  84. pos($line)=0;
  85. while ($line =~ m/\G[^@\/\{\"]*/g) {
  86. if ($line =~ m/\G(@|\/\/|$)/gc) {
  87. last;
  88. }
  89. elsif ($line =~ m/\G\{/gc) {
  90. my $saved_pos = pos($line);
  91. $line =~ s/\G([rdqv])([0-9]+)([^\-]*)\-\1([0-9]+)\3/range($1,$3,$2,$4)/e;
  92. pos($line) = $saved_pos;
  93. $line =~ m/\G[^\}]*\}/g;
  94. }
  95. elsif ($line =~ m/\G\"/gc) {
  96. $line =~ m/\G[^\"]*\"/g;
  97. }
  98. }
  99. $line =~ s/\b(\w+)/$GLOBALS{$1} or $1/ge;
  100. return $line;
  101. }
  102. print "#if defined(__arm__)\n" if ($flavour eq "linux32");
  103. print "#if defined(__aarch64__)\n" if ($flavour eq "linux64");
  104. while($line=<>) {
  105. if ($line =~ m/^\s*(#|@|\/\/)/) { print $line; next; }
  106. $line =~ s|/\*.*\*/||; # get rid of C-style comments...
  107. $line =~ s|^\s+||; # ... and skip white spaces in beginning...
  108. $line =~ s|\s+$||; # ... and at the end
  109. {
  110. $line =~ s|[\b\.]L(\w{2,})|L$1|g; # common denominator for Locallabel
  111. $line =~ s|\bL(\w{2,})|\.L$1|g if ($dotinlocallabels);
  112. }
  113. {
  114. $line =~ s|(^[\.\w]+)\:\s*||;
  115. my $label = $1;
  116. if ($label) {
  117. printf "%s:",($GLOBALS{$label} or $label);
  118. }
  119. }
  120. if ($line !~ m/^[#@]/) {
  121. $line =~ s|^\s*(\.?)(\S+)\s*||;
  122. my $c = $1; $c = "\t" if ($c eq "");
  123. my $mnemonic = $2;
  124. my $opcode;
  125. if ($mnemonic =~ m/([^\.]+)\.([^\.]+)/) {
  126. $opcode = eval("\$$1_$2");
  127. } else {
  128. $opcode = eval("\$$mnemonic");
  129. }
  130. my $arg=expand_line($line);
  131. if (ref($opcode) eq 'CODE') {
  132. $line = &$opcode($arg);
  133. } elsif ($mnemonic) {
  134. $line = $c.$mnemonic;
  135. $line.= "\t$arg" if ($arg ne "");
  136. }
  137. }
  138. print $line if ($line);
  139. print "\n";
  140. }
  141. print "#endif" if ($flavour eq "linux32" || $flavour eq "linux64");
  142. close STDOUT;