|
|
#!/usr/local/bin/perl5 -w
## ## Copyright (c) 2000, Intel Corporation ## All rights reserved. ## ## WARRANTY DISCLAIMER ## ## THESE MATERIALS ARE PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY ## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING ## NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THESE ## MATERIALS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ## ## Intel Corporation is the author of the Materials, and requests that all ## problem reports or change requests be submitted to it directly at ## http://developer.intel.com/opensource. ##
$GenDir = shift(@ARGV); $EmdbDir = shift(@ARGV);
################################################ # CONSTANTS AND VARIABLES ################################################
### Second role instruction flag # ASSUMPTIONS: #1) Each instructions has at most one operand with a second role. #2) The _2ROLE flags are made up of EXACTLY one decimal digit. $_2ROLE_NONE = 0; $_2ROLE_DST = 1; $_2ROLE_SRC = 2;
### NOTE # All arrays of completers below must be sorted by their length in descending order
### Compare types comleters which can appear in mnemonics @cmp_types = ("or\.andcm", "and", "unc", "or");
### Compare relations comleters which can appear in mnemonics @cmp_rels = ("unord", "ord", "neq", "nlt", "nle", "geu", "ltu", "eq", "ne", "lt", "ge", "gt", "le");
### All those instructions that have floating point precision specification @fp_precis_insts = ("EM_FNMA", "EM_SETF", "EM_GETF", "EM_FMA", "EM_FMS");
### Branch types comleters which can appear in mnemonics @branch_types = ("CLOOP", "CEXIT", "WEXIT", "COND", "CALL", "CTOP", "WTOP", "RET", "IA");
### Memory access hints comleters which can appear in mnemonics @mem_access_hints = ("nt1", "nt2", "nta");
### Prefix of branch_hints enumerators $branch_hint_prefix = "EM_branch_hint";
### Prefix of memory_access_hints enumerators $mem_access_hint_prefix = "EM_memory_access_hint";
### Hints file (EM_hints.h) header $hints_header = "#ifndef EM_HINTS_H\n#define EM_HINTS_H\n\n";
### Add branch hints enumeration's header $branch_hints_header = ("typedef enum ".$branch_hint_prefix."_e\n{\n"); $branch_hints_header .= (" ".$branch_hint_prefix."_none"); ### Branch hints enumeration's tail $branch_hints_tail = (",\n ".$branch_hint_prefix."_last\n} ".$branch_hint_prefix."_t;\n\n");
### Memory access hints enumeration's header $mem_access_hints_header = ("typedef enum ".$mem_access_hint_prefix."_e\n{\n"); $mem_access_hints_header .= (" ".$mem_access_hint_prefix."_none");
### Memory access hints enumeration's tail $mem_access_hints_tail = (",\n ".$mem_access_hint_prefix."_last\n} ".$mem_access_hint_prefix."_t;\n\n");
### Hints file (EM_hints.h) tail $hints_tail = ("\n#endif /* EM_HINTS_H */\n");
### BR_hints: Associative array that holds existing branch hints $BR_hints{"none"} = "exist"; #enumerated by 0 - printed the first in EM_hints.h $BR_hints{"last"} = "exist"; #printed the last in EM_hints.h
### MEM_ACCESS_hints: Associative array that holds existing memory access hints $MEM_ACCESS_hints{"none"} = "exist"; #enumerated by 0 - printed the first in EM_hints.h $MEM_ACCESS_hints{"last"} = "exist"; #printed the last in EM_hints.h
### Initialize branch hints enumeration string $branch_hints_enum = "";
### Initilize memory access hints enumeration string $mem_access_hints_enum = "";
### memory_size: Associative array that maps "letter" into mem_size %memory_size = ("s", 4, "d", 8, "e", 10, "q", 16);
################################################ # open input and output files ################################################
### Input file: all_emdb.c open(EMDB_ALL, "$GenDir/all_emdb.tab") || die "Can't open all_emdb.tab\n";
### Output file: decoder.txt open(EMDB5, ">$GenDir/decoder.txt") || die "Can't open decoder.txt\n"; ### Output file: EM_hints.h open (HINTS_ENUM, ">$GenDir/EM_hints.h") || die "Can't open EM_hints.h\n";
### Column names in decoder.txt @dec_col_names = ("inst_id", "mem_size", "dec_flags", "false_pred_flag", "modifiers", "br_hint_flag", "br_flag", "control_transfer_flag");
### Type names in decoder.txt @dec_type_names = ("Inst_id_t", "Mem_size_t", "int", "int", "EM_Decoder_modifiers_t", "int", "int", "int");
### Prefix names in decoder.txt @dec_prefix_names = ("---", "---", "---", "---", "EM_cmp_type;EM_CMP_REL;EM_branch_type;EM_branch_hint;EM_FP_PRECISION;EM_FP_STATUS;EM_memory_access_hint", "---", "---", "---");
###open emdb.txt to extract its version open(EMDB, "$EmdbDir/emdb.txt") || die "Can't open emdb.txt\n"; ### Skip comments in emdb.txt file while (<EMDB>) { last if /^###/; }
close (EMDB); ### Set emdb.txt version die "ERROR !!! unexpected EMDB.txt header format\n" if ($_ !~ /\$Revision/); $EMDB_version = $_;
### Select decoder.txt to be the current output file select(EMDB5);
### Print headers in decoder.txt print $EMDB_version;
### Set format for output to decoder.txt format EMDB5 = @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<@<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $id, $mem_size, $dec_flags, $false_pred_flag, $modifiers, $br_hint_flag, $br_flag, $control_transfer_flag .
### Print column names ($id, $mem_size, $dec_flags, $false_pred_flag, $modifiers, $br_hint_flag, $br_flag, $control_transfer_flag) = @dec_col_names; $id = "&" . $id; write;
### Print type names ($id, $mem_size, $dec_flags, $false_pred_flag, $modifiers, $br_hint_flag, $br_flag, $control_transfer_flag) = @dec_type_names; $id = "?" . $id; write;
### Print prefix names ($id, $mem_size, $dec_flags, $false_pred_flag, $modifiers, $br_hint_flag, $br_flag, $control_transfer_flag) = @dec_prefix_names; $id = "@" . $id; write;
### While loop over lines of all_emdb.tab ### Each line is read into $_
while (<EMDB_ALL>) { if (/^EM_/) { ### Initialization $mem_size = 0; $dec_flags = $_2ROLE_NONE;
### Extract instruction id and mnemonic from current input line ($id, $mnemonic) = split(/,/, $_);
### Set mem_size if ($mnemonic =~ /ld(\d+)/) { $mem_size = $1; } elsif ($mnemonic =~ /ldf(\d+)/) { $mem_size = $1; } elsif ($mnemonic =~ /ldfp(\d+)/) { $mem_size = $1; } elsif ($mnemonic =~ /ldfpd/) { $mem_size = 16; } elsif ($mnemonic =~ /ldfps/) { $mem_size = 8; } elsif ($mnemonic =~ /ldf([a-z])/) { die "ERROR !!! unexpected mnemonic: \"ldf$1\"\n" if (!$memory_size{$1}); $mem_size = $memory_size{$1}; } elsif ($mnemonic =~ /ldf\./) { $mem_size = 16; } elsif ($mnemonic =~ /lfetch/) { $mem_size = 32; } elsif ($mnemonic =~ /st(\d+)/) { $mem_size = $1; } elsif ($mnemonic =~ /stf(\d+)/) { $mem_size = $1; } elsif ($mnemonic =~ /stf([a-z])/) { die "ERROR !!! unexpected mnemonic: \"stf$1\"\n" if (!$memory_size{$1}); $mem_size = $memory_size{$1}; } elsif ($mnemonic =~ /stf\./) { $mem_size = 16; } elsif ($mnemonic =~ /fetchadd(\d+)/) { $mem_size = $1; } elsif ($mnemonic =~ /xchg(\d+)/) { $mem_size = $1; }
### Set second role flag ### loads or lfetchs with "_R2" or "IMM" in inst_id #!!! to be updated when this conventions change !!!
if ((($id =~ /EM_LD/) && (($id =~ /_R2/)||($id =~ /IMM/)||($id =~ /_(\d+)/))) || (($id =~ /EM_LFETCH/) && (($id =~ /_R2/)||($id =~ /IMM/)))) { $dec_flags = $_2ROLE_DST; } elsif (($id =~ /EM_ST/) && ($id =~ /IMM/)) ### stores with "IMM" in inst_id { $dec_flags = $_2ROLE_SRC; }
### Set false predicate exec flag &Set_false_pred_flag(); ### Set branch flags &Set_branch_flags(); ### Set control transfer flag &Set_control_transfer_flag();
### Set modifiers: cmp_type, cmp_rel, branch_type, branch_hint, fp_precision, fp_status, mem_access_hint &Set_modifiers();
### Join all the modifiers separated by ';' $modifiers = join(';', $cmp_type, $cmp_rel, $branch_type, $branch_hint, $fp_precision, $fp_status, $mem_access_hint);
write; } }
### Print headers in EM_hints.h print HINTS_ENUM $hints_header;
&Print_branch_hints();
### Print memory access hints enumeration in EM_hints.h &Print_mem_access_hints();
### Print tail in EM_hints.h print HINTS_ENUM $hints_tail;
### Close open files close(HINTS_ENUM); close(EMDB_ALL); close(EMDB5);
################################## # PROCEDURES ##################################
sub Set_modifiers { $cmp_type = "none"; $cmp_rel = "NONE"; ### Set cmp_rel modifier for ($i=0; $i <= $#cmp_rels; $i++) { if ($mnemonic =~ /\.$cmp_rels[$i]/) { $cmp_rel = "\U$cmp_rels[$i]"; last; } }
### Set cmp_type modifier for ($i=0; $i <= $#cmp_types; $i++) { if ($mnemonic =~ /\.$cmp_types[$i]/) { $cmp_type = $cmp_types[$i]; $cmp_type =~ s/\./_/g; last; } }
### Set fp_precision modifier $fp_precision = "NONE";
for ($i=0; $i <= $#fp_precis_insts; $i++) { if ($id =~ /$fp_precis_insts[$i]_/) { if ($id =~ /_S_/) { $fp_precision = "SINGLE"; } elsif ($id =~ /_D_/) { $fp_precision = "DOUBLE"; } else { $fp_precision = "DYNAMIC"; } last; } }
### Set fp_status modifier $fp_status = "NONE";
if ($mnemonic =~ /\.s0/) { $fp_status = "S0"; } elsif ($mnemonic =~ /\.s1/) { $fp_status = "S1"; } elsif ($mnemonic =~ /\.s2/) { $fp_status = "S2"; } elsif ($mnemonic =~ /\.s3/) { $fp_status = "S3"; }
### Set branch_type modifier $branch_type = "none"; $branch_hint = "none";
if ($id =~ /EM_BR_/ || $id =~ /EM_BRL_/) ### Pattern: mnemonic - "br.type.hints" { for ($i=0; $i <= $#branch_types; $i++) { if ($id =~ /_$branch_types[$i]/) { if ($id =~ /TARGET25/ || $id =~ /TARGET64/) { $branch_type = "direct"; } else { $branch_type = "indirect"; } $branch_type .= "_\L$branch_types[$i]";
last; } } }
### Set branch_hint modifier if ($mnemonic =~ /brp\./) ### Pattern: mnemonic - "brp.[ret.]hints" { $branch_hint = $mnemonic; $branch_hint =~ s/brp\.//; $branch_hint =~ s/\./_/g; } elsif ($id =~ /^EM_MOV_/ && $id =~ /TAG13/) ### Pattern: inst_id - EM_MOV_[RET_]HINTS__B1_R2_TAG13 ### mnemonic - "mov.[ret.]hints" { $branch_hint = $mnemonic; $branch_hint =~ s/mov\.//; $branch_hint =~ s/\./_/g; } elsif ($id =~ /EM_BR_/ || $id =~ /EM_BRL_/) ### Pattern: mnemonic - "br.type.hints" { for ($i=0; $i <= $#branch_types; $i++) { if ($id =~ /_$branch_types[$i]/) { $branch_hint = $mnemonic; $br_type_low = "\L$branch_types[$i]"; $branch_hint =~ s/br\.$br_type_low\.//; $branch_hint =~ s/brl\.$br_type_low\.//; $branch_hint =~ s/\./_/g;
last; } } }
### Append the branch hint enumerator (if first appearance) ### to the enums string if (! $BR_hints{$branch_hint}) { $BR_hints{$branch_hint} = "exist"; $hint = join('_', $branch_hint_prefix, $branch_hint); $branch_hints_enum .= ",\n $hint"; }
### Set mem_access_hint modifier
$mem_access_hint = "none";
for ($i=0; $i <= $#mem_access_hints; $i++) { if ($mnemonic =~ /\.$mem_access_hints[$i]/) { $mem_access_hint = $mem_access_hints[$i]; last; } }
### Append the memory access hint enumerator (if first appearance) ### to the enums string if (! $MEM_ACCESS_hints{$mem_access_hint}) { $MEM_ACCESS_hints{$mem_access_hint} = "exist"; $hint = join('_', $mem_access_hint_prefix, $mem_access_hint); $mem_access_hints_enum .= ",\n $hint"; } }
### False qualifying predicate exec flag
sub Set_false_pred_flag { if (($mnemonic =~ /\.unc/) || ($mnemonic =~ /frcpa/) || ($mnemonic =~ /frsqrta/) || ($mnemonic =~ /fprcpa/) || ($mnemonic =~ /fprsqrta/) || (($mnemonic =~ /br\./) && (($mnemonic =~ /\.cloop/) || ($mnemonic =~ /\.cexit/) || ($mnemonic =~ /\.ctop/) || ($mnemonic =~ /\.wtop/) || ($mnemonic =~ /\.wexit/))) ) { $false_pred_flag = 1; } else { $false_pred_flag = 0; } }
### Branch flag
sub Set_branch_flags { if ($id =~ /EM_BRP_/) { $br_hint_flag = 1; $br_flag = 0; } elsif ($id =~ /EM_BR_/ || $id =~ /EM_BRL_/) { $br_hint_flag = 0; $br_flag = 1; } else { $br_hint_flag = 0; $br_flag = 0; } }
### Print branch hints enumeration in EM_hints.h
sub Print_branch_hints { ### Print branch hints enumeration's header print HINTS_ENUM $branch_hints_header;
### Print branch hints enumeration string print HINTS_ENUM $branch_hints_enum;
### Print branch hints enumeration's tail print HINTS_ENUM $branch_hints_tail; }
### Print memory access hints enumeration in EM_hints.h
sub Print_mem_access_hints {
### Print memory access hints enumeration's header print HINTS_ENUM $mem_access_hints_header;
### Print memory access hints enumeration string print HINTS_ENUM $mem_access_hints_enum;
### Print memory access hints enumeration's tail print HINTS_ENUM $mem_access_hints_tail; }
### Control transfer flag
sub Set_control_transfer_flag { if ($id =~ /EM_BR_/ || $id =~ /EM_BRL_/ || $id =~ /EM_RFI/ || $id =~ /EM_BREAK/ || ($id =~ /TARGET25/ && $id !~ /EM_BRP_/)) { $control_transfer_flag = 1; } else { $control_transfer_flag = 0; } }
|