#!/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 () { 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 () { 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; } }