557 lines
15 KiB
Perl
557 lines
15 KiB
Perl
#!/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;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|