insns.pl
上传用户:yuppie_zhu
上传日期:2007-01-08
资源大小:535k
文件大小:7k
源码类别:

编译器/解释器

开发平台:

C/C++

  1. #!/usr/bin/perl
  2. #
  3. # insns.pl   produce insnsa.c, insnsd.c, insnsi.h, insnsn.c from insns.dat
  4. #
  5. # The Netwide Assembler is copyright (C) 1996 Simon Tatham and
  6. # Julian Hall. All rights reserved. The software is
  7. # redistributable under the licence given in the file "Licence"
  8. # distributed in the NASM archive.
  9. print STDERR "Reading insns.dat...n";
  10. @args   = ();
  11. undef $output;
  12. foreach $arg ( @ARGV ) {
  13.     if ( $arg =~ /^-/ ) {
  14. if  ( $arg =~ /^-([adin])$/ ) {
  15.     $output = $1;
  16. } else {
  17.     die "$0: Unknown option: ${arg}n";
  18. }
  19.     } else {
  20. push (@args, $arg);
  21.     }
  22. }
  23. $fname = "insns.dat" unless $fname = $args[0];
  24. open (F, $fname) || die "unable to open $fname";
  25. $line = 0;
  26. $insns = 0;
  27. while (<F>) {
  28.   $line++;
  29.   next if /^s*;/;   # comments
  30.   chomp;
  31.   split;
  32.   next if $#_ == -1; # blank lines
  33.   (warn "line $line does not contain four fieldsn"), next if $#_ != 3;
  34.   ($formatted, $nd) = &format(@_);
  35.   if ($formatted) {
  36.     $insns++;
  37.     $aname = "aa_$_[0]";
  38.     push @$aname, $formatted;
  39.   }
  40.   if ( $_[0] =~ /cc$/ ) {
  41.       # Conditional instruction
  42.       $k_opcodes_cc{$_[0]}++;
  43.   } else {
  44.       # Unconditional instruction
  45.       $k_opcodes{$_[0]}++;
  46.   }
  47.   if ($formatted && !$nd) {
  48.     push @big, $formatted;
  49.     foreach $i (&startbyte($_[2])) {
  50.       $aname = sprintf "dd_%02X",$i;
  51.       push @$aname, $#big;
  52.     }
  53.   }
  54. }
  55. close F;
  56. @opcodes    = sort keys(%k_opcodes);
  57. @opcodes_cc = sort keys(%k_opcodes_cc);
  58. if ( !defined($output) || $output eq 'a' ) {
  59.     print STDERR "Writing insnsa.c...n";
  60.     
  61.     open A, ">insnsa.c";
  62.     
  63.     print A "/* This file auto-generated from insns.dat by insns.pl" .
  64.         " - don't edit it */nn";
  65.     print A "#include <stdio.h>n";
  66.     print A "#include "nasm.h"n";
  67.     print A "#include "insns.h"n";
  68.     print A "n";
  69.     
  70.     foreach $i (@opcodes, @opcodes_cc) {
  71. print A "static struct itemplate instrux_${i}[] = {n";
  72. $aname = "aa_$i";
  73. foreach $j (@$aname) {
  74.     print A "    $jn";
  75. }
  76. print A "    {-1}n};nn";
  77.     }
  78.     print A "struct itemplate *nasm_instructions[] = {n";
  79.     foreach $i (@opcodes, @opcodes_cc) {
  80. print A "    instrux_${i},n";
  81.     }
  82.     print A "};n";
  83.     
  84.     close A;
  85. }
  86. if ( !defined($output) || $output eq 'd' ) {
  87.     print STDERR "Writing insnsd.c...n";
  88.     
  89.     open D, ">insnsd.c";
  90.     
  91.     print D "/* This file auto-generated from insns.dat by insns.pl" .
  92.         " - don't edit it */nn";
  93.     print D "#include <stdio.h>n";
  94.     print D "#include "nasm.h"n";
  95.     print D "#include "insns.h"n";
  96.     print D "n";
  97.     
  98.     print D "static struct itemplate instrux[] = {n";
  99.     foreach $j (@big) {
  100. print D "    $jn";
  101.     }
  102.     print D "    {-1}n};nn";
  103.     
  104.     for ($c=0; $c<256; $c++) {
  105. $h = sprintf "%02X", $c;
  106. print D "static struct itemplate *itable_${h}[] = {n";
  107. $aname = "dd_$h";
  108. foreach $j (@$aname) {
  109.     print D "    instrux + $j,n";
  110. }
  111. print D "    NULLn};nn";
  112.     }
  113.     
  114.     print D "struct itemplate **itable[] = {n";
  115.     for ($c=0; $c<256; $c++) {
  116. printf D "    itable_%02X,n", $c;
  117.     }
  118.     print D "};n";
  119.     
  120.     close D;
  121. }
  122. if ( !defined($output) || $output eq 'i' ) {
  123.     print STDERR "Writing insnsi.h...n";
  124.     
  125.     open I, ">insnsi.h";
  126.     
  127.     print I "/* This file is auto-generated from insns.dat by insns.pl" .
  128.         " - don't edit it */nn";
  129.     print I "/* This file in included by nasm.h */nn";
  130.     
  131.     print I "/* Instruction names */n";
  132.     print I "enum {";
  133.     $first  = 1;
  134.     $maxlen = 0;
  135.     foreach $i (@opcodes, @opcodes_cc) {
  136. print I "," if ( !$first );
  137. $first = 0;
  138. print I "ntI_${i}";
  139. $len = length($i);
  140. $len++ if ( $i =~ /cc$/ ); # Condition codes can be 3 characters long
  141. $maxlen = $len if ( $len > $maxlen );
  142.     }
  143.     print I "n};nn";
  144.     print I "#define MAX_INSLEN ", $maxlen, "n";
  145.     
  146.     close I;
  147. }
  148. if ( !defined($output) || $output eq 'n' ) {
  149.     print STDERR "Writing insnsn.c...n";
  150.     
  151.     open N, ">insnsn.c";
  152.     
  153.     print N "/* This file is auto-generated from insns.dat by insns.pl" .
  154.         " - don't edit it */nn";
  155.     print N "/* This file in included by names.c */nn";
  156.     
  157.     print N "static char *insn_names[] = {";
  158.     $first = 1;
  159.     foreach $i (@opcodes) {
  160. print N "," if ( !$first );
  161. $first = 0;
  162. $ilower = $i;
  163. $ilower =~ tr/A-Z/a-z/; # Change to lower case (Perl 4 compatible)
  164. print N "nt"${ilower}"";
  165.     }
  166.     print N "n};nn";
  167.     print N "/* Conditional instructions */n";
  168.     print N "static char *icn[] = {";
  169.     $first = 1;
  170.     foreach $i (@opcodes_cc) {
  171. print N "," if ( !$first );
  172. $first = 0;
  173. $ilower = $i;
  174. $ilower =~ s/cc$//; # Skip cc suffix
  175. $ilower =~ tr/A-Z/a-z/; # Change to lower case (Perl 4 compatible)
  176. print N "nt"${ilower}"";
  177.     }
  178.     
  179.     print N "n};nn";
  180.     print N "/* and the corresponding opcodes */n";
  181.     print N "static int ico[] = {";
  182.     $first = 1;
  183.     foreach $i (@opcodes_cc) {
  184. print N "," if ( !$first );
  185. $first = 0;
  186. print N "ntI_$i";
  187.     }
  188.     
  189.     print N "n};n";
  190.     
  191.     close N;
  192. }
  193. printf STDERR "Done: %d instructionsn", $insns;
  194. sub format {
  195.   local ($opcode, $operands, $codes, $flags) = @_;
  196.   local $num, $nd = 0;
  197.   return (undef, undef) if $operands eq "ignore";
  198.   # format the operands
  199.   $operands =~ s/:/|colon,/g;
  200.   $operands =~ s/mem(d+)/mem|bits$1/g;
  201.   $operands =~ s/mem/memory/g;
  202.   $operands =~ s/memory_offs/mem_offs/g;
  203.   $operands =~ s/imm(d+)/imm|bits$1/g;
  204.   $operands =~ s/imm/immediate/g;
  205.   $operands =~ s/rm(d+)/regmem|bits$1/g;
  206.   $num = 3;
  207.   $operands = '0,0,0', $num = 0 if $operands eq 'void';
  208.   $operands .= ',0', $num-- while $operands !~ /,.*,/;
  209.   $operands =~ tr/a-z/A-Z/;
  210.   # format the flags
  211.   $flags =~ s/,/|IF_/g;
  212.   $flags =~ s/(|IF_ND|IF_ND|)//, $nd = 1 if $flags =~ /IF_ND/;
  213.   $flags = "IF_" . $flags;
  214.   ("{I_$opcode, $num, {$operands}, "$codes", $flags},", $nd);
  215. }
  216. # Here we determine the range of possible starting bytes for a given
  217. # instruction. We need only consider the codes:
  218. # 1 2 3     mean literal bytes, of course
  219. # 4 5 6 7  mean PUSH/POP of segment registers: special case
  220. # 10 11 12  mean byte plus register value
  221. # 17          means byte zero
  222. # 330         means byte plus condition code
  223. #  or 340   mean give up and return empty set
  224. sub startbyte {
  225.   local ($codes) = @_;
  226.   local $word, @range;
  227.   while (1) {
  228.     die "couldn't get code in '$codes'" if $codes !~ /^(\[^\]+)(\.*)?$/;
  229.     $word = $1, $codes = $2;
  230.     return (hex $1) if $word =~ /^\[123]$/ && $codes =~ /^\x(..)/;
  231.     return (0x07, 0x17, 0x1F) if $word eq "\4";
  232.     return (0xA1, 0xA9) if $word eq "\5";
  233.     return (0x06, 0x0E, 0x16, 0x1E) if $word eq "\6";
  234.     return (0xA0, 0xA8) if $word eq "\7";
  235.     $start=hex $1, $r=8, last if $word =~ /^\1[012]$/ && $codes =~/^\x(..)/;
  236.     return (0) if $word eq "\17";
  237.     $start=hex $1, $r=16, last if $word =~ /^\330$/ && $codes =~ /^\x(..)/;
  238.     return () if $word eq "\0" || $word eq "\340";
  239.   }
  240.   @range = ();
  241.   push @range, $start++ while ($r-- > 0);
  242.   @range;
  243. }