maxas/MaxAs/MaxAsGrammar.pm (1,200 lines of code) (raw):
package MaxAs::MaxAsGrammar;
use strict;
use Carp;
use Exporter;
use Data::Dumper;
our @ISA = qw(Exporter);
our @EXPORT = qw(
%grammar %flags
parseInstruct genCode genReuseCode
processAsmLine processSassLine processSassCtrlLine
replaceXMADs printCtrl readCtrl getRegNum getVecRegisters getAddrVecRegisters
);
require 5.10.0;
# Helper functions for operands
sub getI
{
my ($orig, $pos, $mask) = @_;
my $val = $orig;
my $neg = $val =~ s|^\-||;
# parse out our custom index immediates for addresses
if ($val =~ m'^(\d+)[xX]<([^>]+)>')
{
# allow any perl expression and multiply result by leading decimal.
# also allow global scalar varibles in the expression.
my $mul = $1;
my $exp = $2;
# strip leading zeros (don't interpret numbers as octal)
$exp =~ s/(?<!\d)0+(?=[1-9])//g;
my @globals = $exp =~ m'\$\w+'g;
my $our = @globals ? ' our (' . join(',',@globals) . ');' : '';
$val = $mul * eval "package MaxAs::MaxAs::CODE;$our $exp";
#print "$val = $mul x $exp\n"; # if $our;
}
# hexidecial value
elsif ($val =~ m'^0x[0-9a-zA-Z]+')
{
$val = hex($val);
}
# otherwise val is a simple decimal value that doesn't need to be modified
if ( $neg )
{
# if the mask removes the sign bit the "neg" flag adds it back on the code somewhere else
$val = -$val;
$val &= $mask;
}
if (($val & $mask) != $val)
{
die sprintf "Immediate value out of range(0x%x): 0x%x ($orig)\n", $mask, $val;
}
return $val << $pos;
}
sub getF
{
my ($val, $pos, $type, $trunc) = @_;
# hexidecial value
if ($val =~ m'^0x[0-9a-zA-Z]+')
{
$val = hex($val);
}
# support infinity
elsif ($val =~ m'INF'i)
{
$val = $trunc ? ($type eq 'f' ? 0x7f800 : 0x7ff00) : 0x7f800000;
}
else
{
$val = unpack(($type eq 'f' ? 'L' : 'Q'), pack $type, $val);
# strip off sign bit if truncating. It will added elsewhere in the code by the flag capture.
$val = ($val >> $trunc) & 0x7ffff if $trunc;
}
return $val << $pos;
}
sub getR
{
my ($val, $pos) = @_;
if ($val =~ m'^R(\d+|Z)$' && $1 < 255)
{
$val = $1 eq 'Z' ? 0xff : $1;
}
else
{
die "Bad register name found: $val\n";
}
return $val << $pos;
}
sub getP
{
my ($val, $pos) = @_;
if ($val =~ m'^P(\d|T)$' && $1 < 7)
{
$val = $1 eq 'T' ? 7 : $1;
}
else
{
die "Bad predicate name found: $val\n";
}
return $val << $pos;
}
sub getC { ((hex($_[0]) >> 2) & 0x7fff) << 20 }
# Map operands into their value and position in the op code.
my %operands =
(
p0 => sub { getP($_[0], 0) },
p3 => sub { getP($_[0], 3) },
p12 => sub { getP($_[0], 12) },
p29 => sub { getP($_[0], 29) },
p39 => sub { getP($_[0], 39) },
p45 => sub { getP($_[0], 45) },
p48 => sub { getP($_[0], 48) },
p58 => sub { getP($_[0], 58) },
r0 => sub { getR($_[0], 0) },
r8 => sub { getR($_[0], 8) },
r20 => sub { getR($_[0], 20) },
r28 => sub { getR($_[0], 28) },
r39s20 => sub { getR($_[0], 39) },
r39 => sub { getR($_[0], 39) },
r39a => sub { getR($_[0], 39) }, # does not modify op code, xor the r39 value again to whipe it out, register must be in sequence with r20
c20 => sub { getC($_[0]) },
c39 => sub { getC($_[0]) },
c34 => sub { hex($_[0]) << 34 },
c36 => sub { hex($_[0]) << 36 },
f20w32 => sub { getF($_[0], 20, 'f') },
f20 => sub { getF($_[0], 20, 'f', 12) },
d20 => sub { getF($_[0], 20, 'd', 44) },
i8w4 => sub { getI($_[0], 8, 0xf) },
i20 => sub { getI($_[0], 20, 0x7ffff) },
i20w6 => sub { getI($_[0], 20, 0x3f) },
i20w7 => sub { getI($_[0], 20, 0x7f) },
i20w8 => sub { getI($_[0], 20, 0xff) },
i20w12 => sub { getI($_[0], 20, 0xfff) },
i20w24 => sub { getI($_[0], 20, 0xffffff) },
i20w32 => sub { getI($_[0], 20, 0xffffffff) },
i31w4 => sub { getI($_[0], 31, 0xf) },
i34w13 => sub { getI($_[0], 34, 0x1fff) },
i36w20 => sub { getI($_[0], 36, 0xfffff) },
i39w8 => sub { getI($_[0], 39, 0xff) },
i28w8 => sub { getI($_[0], 28, 0xff) },
i28w20 => sub { getI($_[0], 28, 0xfffff) },
i48w8 => sub { getI($_[0], 48, 0xff) },
i51w5 => sub { getI($_[0], 51, 0x1f) },
i53w5 => sub { getI($_[0], 53, 0x1f) },
);
# Rules for operands and their closely tied flags
my $hex = qr"0[xX][0-9a-fA-F]+";
my $iAddr = qr"\d+[xX]<[^>]+>";
my $immed = qr"$hex|$iAddr|\d+"o;
my $reg = qr"[a-zA-Z_]\w*"; # must start with letter or underscore\
my $p = qr"P[0-6T]";
my $noPred = qr"(?<noPred>)";
my $pred = qr"\@(?<predNot>\!)?P(?<predNum>[0-6]) ";
my $p0 = qr"(?<p0>$p)"o;
my $p3 = qr"(?<p3>$p)"o;
my $p12 = qr"(?<p12not>\!)?(?<p12>$p)"o;
my $p29 = qr"(?<p29not>\!)?(?<p29>$p)"o;
my $p39 = qr"(?<p39not>\!)?(?<p39>$p)"o;
my $p45 = qr"(?<p45>$p)"o;
my $p48 = qr"(?<p48>$p)"o;
my $p58 = qr"(?<p58>$p)"o;
my $r0 = qr"(?<r0>$reg)";
my $r0cc = qr"(?<r0>$reg)(?<CC>\.CC)?";
my $r8 = qr"(?<r8neg>\-)?(?<r8abs>\|)?(?<r8>$reg)\|?(?:\.(?<r8part>H0|H1|B0|B1|B2|B3|H0_H0|H1_H1|F32))?(?<reuse1>\.reuse)?";
my $r20 = qr"(?<r20neg>\-)?(?<r20abs>\|)?(?<r20>$reg)\|?(?:\.(?<r20part>H0|H1|B0|B1|B2|B3|H0_H0|H1_H1))?(?<reuse2>\.reuse)?";
my $r28 = qr"(?<r28>$reg)";
my $r39s20 = qr"(?<r20neg>\-)?(?<r20abs>\|)?(?<r39s20>(?<r20>$reg))\|?(?:\.(?<r39part>H0|H1))?(?<reuse2>\.reuse)?";
my $r39 = qr"(?<r39neg>\-)?(?<r39>$reg)(?:\.(?<r39part>H0|H1|H0_H0|H1_H1|F32))?(?<reuse3>\.reuse)?";
my $r39a = qr"(?<r39a>(?<r39>$reg))(?<reuse3>\.reuse)?";
my $c20 = qr"(?<r20neg>\-)?(?<r20abs>\|)?c\[(?<c34>$hex)\]\s*\[(?<c20>$hex)\]\|?(?:\.(?<r20part>H0|H1|B0|B1|B2|B3))?"o;
my $c20x = qr"(?<r20neg>\-)?(?<r20abs>\|)?c\[(?<c34>$hex)\]\s*\[(?<c20>$hex)\]\|?(?:\.(?<r20partx>H0|H1|B0|B1|B2|B3))?"o;
my $c20s39 = qr"(?<r39neg>\-)?c\[(?<c34>$hex)\]\s*\[(?<c39>$hex)\]"o;
my $f20w32 = qr"(?<f20w32>(?:\-|\+|)(?i:$hex|inf\s*|\d+(?:\.\d+(?:e[\+\-]\d+)?)?))";
my $f20 = qr"(?<f20>(?:(?<neg>\-)|\+|)(?i:inf\s*|\d+(?:\.\d+(?:e[\+\-]\d+)?)?))(?<r20neg>\.NEG)?"o;
my $d20 = qr"(?<d20>(?:(?<neg>\-)|\+|)(?i:inf\s*|\d+(?:\.\d+(?:e[\+\-]\d+)?)?))(?<r20neg>\.NEG)?"o;
my $i8w4 = qr"(?<i8w4>$immed)"o;
my $i20 = qr"(?<i20>(?<neg>\-)?$immed)(?<r20neg>\.NEG)?"o;
my $i20w6 = qr"(?<i20w6>$immed)"o;
my $i20w7 = qr"(?<i20w7>$immed)"o;
my $i20w8 = qr"(?<i20w8>$immed)"o;
my $i20w12 = qr"(?<i20w12>$immed)"o;
my $i20w24 = qr"(?<i20w24>\-?$immed)"o;
my $i20w32 = qr"(?<i20w32>\-?$immed)"o;
my $i39w8 = qr"(?<i39w8>\-?$immed)"o;
my $i28w8 = qr"(?<i28w8>$immed)"o;
my $i28w20 = qr"(?<i28w20>\-?$immed)"o;
my $i31w4 = qr"(?<i31w4>$immed)"o;
my $i34w13 = qr"(?<i34w13>$immed)"o;
my $i36w20 = qr"(?<i36w20>$immed)"o;
my $i48w8 = qr"(?<i48w8>$immed)"o;
my $i51w5 = qr"(?<i51w5>$immed)"o;
my $i53w5 = qr"(?<i53w5>$immed)"o;
my $ir20 = qr"$i20|$r20"o;
my $cr20 = qr"$c20|$r20"o;
my $icr20 = qr"$i20|$c20|$r20"o;
my $fcr20 = qr"$f20|$c20|$r20"o;
my $cr39 = qr"$c20s39|$r39"o;
my $dr20 = qr"$d20|$r20"o;
# Instruction specific rules for capturing various flags
my $u32 = qr"(?<U32>\.U32)?";
my $ftz = qr"(?<FTZ>\.FTZ)?";
my $fmz = qr"(?<FMZ>\.FMZ)?";
my $sat = qr"(?<SAT>\.SAT)?";
my $rnd = qr"(?:\.(?<rnd>RN|RM|RP|RZ))?";
my $round = qr"(?:\.(?<round>ROUND|FLOOR|CEIL|TRUNC))?";
my $fcmp = qr"(?<cmp>\.LT|\.EQ|\.LE|\.GT|\.NE|\.GE|\.NUM|\.NAN|\.LTU|\.EQU|\.LEU|\.GTU|\.NEU|\.GEU|)";
my $icmp = qr"\.(?<cmp>LT|EQ|LE|GT|NE|GE)";
my $bool = qr"\.(?<bool>AND|OR|XOR|PASS_B)";
my $bool2 = qr"\.(?<bool2>AND|OR|XOR)";
my $func = qr"\.(?<func>COS|SIN|EX2|LG2|RCP|RSQ|RCP64H|RSQ64H)";
my $rro = qr"\.(?<func>SINCOS|EX2)";
my $add3 = qr"(?:\.(?<type>X|RS|LS))?";
my $lopz = qr"(?:\.(?<z>NZ|Z) $p48,|(?<noz>))"o;
my $X = qr"(?<X>\.X)?";
my $tld = qr"(?<NODEP>NODEP\.)?(?:(?<reuse1>T)|(?<reuse2>P))";
my $chnls = qr"(?<chnls>R|RGBA)";
my $sr = qr"SR_(?<sr>\S+)";
my $shf = qr"(?<W>\.W)?(?:\.(?<type>U64|S64))?(?<HI>\.HI)?";
my $xmad = qr"(?:\.(?<type1>U16|S16))?(?:\.(?<type2>U16|S16))?(?:\.(?<mode>MRG|PSL\.CLO|PSL|CHI|CLO|CSFU))?(?<CBCC>\.CBCC)?";
my $xmadc = qr"(?:\.(?<type1>U16|S16))?(?:\.(?<type2>U16|S16))?(?:\.(?<modec>MRG|PSL\.CLO|PSL|CHI|CLO|CSFU))?(?<CBCC>\.CBCC)?";
my $vmad8 = qr"\.(?<sign1>[SU])(?<size1>8|16)\.(?<sign2>[SU])(?<size2>8|16)(?<PO>\.PO)?(?<SHR_7>\.SHR_7)?(?<SHR_15>\.SHR_15)?(?<SAT>\.SAT)?";
my $vmad16= qr"\.(?<sign1>[SU])(?<size1>16)\.(?<sign2>[SU])(?<size2>16)";
my $hilo = qr"(?:\.(?<mode>XHI|XLO))?";
my $vaddType = qr"(?:\.(?<UD>UD))?(?:\.(?<SD>SD))?(?:\.(?<sign1>[SU])(?<size1>8|16|32))?(?:\.(?<sign2>[SU])(?<size2>8|16|32))?";
my $vaddMode = qr"(?:\.(?<mode>MRG_16[HL]|MRG_8B[0-3]|ACC|MIN|MAX))?";
my $vmnmx = qr"(?:\.(?<MX>MX))?";
my $x2x = qr"\.(?<destSign>F|U|S)(?<destWidth>8|16|32|64)\.(?<srcSign>F|U|S)(?<srcWidth>8|16|32|64)";
my $prmt = qr"(?:\.(?<mode>F4E|B4E|RC8|ECL|ECR|RC16))?";
my $shfl = qr"\.(?<mode>IDX|UP|DOWN|BFLY)";
my $bar = qr"\.(?<mode>SYNC|ARV|RED)(?:\.(?<red>POPC|AND|OR))? (?:$i8w4|$r8)(?:, (?:$i20w12|$r20))?(?(<r20>)|(?<nor20>))(?(<red>), $p39|(?<nop39>))"o;
my $b2r = qr"\.RESULT $r0(?:, $p45|(?<nop45>))"o;
my $dbar = qr"(?<SB>SB0|SB1|SB2|SB3|SB4|SB5)";
my $dbar2 = qr" \{(?<db5>5)?,?(?<db4>4)?,?(?<db3>3)?,?(?<db2>2)?,?(?<db1>1)?,?(?<db0>0)?\}";
my $mbar = qr"\.(?<mode>CTA|GL|SYS)";
my $addr = qr"\[(?:(?<r8>$reg)|(?<nor8>))(?:\s*\+?\s*$i20w24)?\]"o;
my $addr2 = qr"\[(?:(?<r8>$reg)|(?<nor8>))(?:\s*\+?\s*$i28w20)?\]"o;
my $ldc = qr"c\[(?<c36>$hex)\]\s*$addr"o;
my $atom = qr"(?<E>\.E)?(?:\.(?<mode>ADD|MIN|MAX|INC|DEC|AND|OR|XOR|EXCH|CAS))(?<type>|\.S32|\.U64|\.F(?:16x2|32)\.FTZ\.RN|\.S64|\.64)";
my $vote = qr"\.(?<mode>ALL|ANY|EQ)"o;
my $memType = qr"(?<type>\.U8|\.S8|\.U16|\.S16||\.32|\.64|\.128)";
my $memCache = qr"(?<E>\.E)?(?<U>\.U)?(?:\.(?<cache>CG|CI|CS|CV|IL|WT))?";
my $dptype = qr"(?:\.(?<type1>U32|S32))?(?:\.(?<type2>U32|S32))?";
my $dpmode = qr"\.(?<mode>LO|HI)";
my $hmode = qr"(?:\.(?<mode>F32|MRG_H0|MRG_H1))?$ftz";
# class: hardware resource that shares characteristics with types
# lat : pipeline depth where relevent, placeholder for memory ops
# blat : barrier latency, typical fetch time for memory operations. Highly variable.
# rlat : operand read latency for memory ops
# rhold: clock cycles that a memory op typically holds onto a register before it's free to be written by another op.
# tput : throughput, clock cycles an op takes when two ops of the same class are issued in succession.
# dual : whether this instruction type can be dual issued
# reuse: whether this instruction type accepts register reuse flags.
# Some of these values are guesses and need to be updated from micro benchmarks.
# We may need to split these classes up further.
my $s2rT = {class => 's2r', lat => 2, blat => 25, rlat => 0, rhold => 0, tput => 1, dual => 0, reuse => 0};
my $smemT = {class => 'mem', lat => 2, blat => 30, rlat => 2, rhold => 20, tput => 1, dual => 1, reuse => 0};
my $gmemT = {class => 'mem', lat => 2, blat => 200, rlat => 4, rhold => 20, tput => 1, dual => 1, reuse => 0};
my $x32T = {class => 'x32', lat => 6, blat => 0, rlat => 0, rhold => 0, tput => 1, dual => 0, reuse => 1};
my $x64T = {class => 'x64', lat => 2, blat => 128, rlat => 0, rhold => 0, tput => 128, dual => 0, reuse => 1};
my $shftT = {class => 'shift', lat => 6, blat => 0, rlat => 0, rhold => 0, tput => 2, dual => 0, reuse => 1};
my $cmpT = {class => 'cmp', lat => 13, blat => 0, rlat => 0, rhold => 0, tput => 2, dual => 0, reuse => 1};
my $qtrT = {class => 'qtr', lat => 8, blat => 0, rlat => 4, rhold => 0, tput => 1, dual => 1, reuse => 0};
my $rroT = {class => 'rro', lat => 2, blat => 0, rlat => 0, rhold => 0, tput => 1, dual => 0, reuse => 0};
my $voteT = {class => 'vote', lat => 2, blat => 0, rlat => 0, rhold => 0, tput => 1, dual => 0, reuse => 0};
# Create map of op names to rules
our %grammar =
(
#Floating Point Instructions
FADD => [ { type => $x32T, code => 0x5c58000000000000, rule => qr"^$pred?FADD$ftz$rnd$sat $r0, $r8, $fcr20;"o, } ],
FADD32I => [ { type => $x32T, code => 0x0800000000000000, rule => qr"^$pred?FADD32I$ftz $r0, $r8, $f20w32;"o, } ],
FCHK => [ { type => $x32T, code => 0x5c88000000000000, rule => qr"^$pred?FCHK\.DIVIDE $p0, $r8, $r20;"o, } ], #Partial?
FCMP => [ { type => $cmpT, code => 0x5ba0000000000000, rule => qr"^$pred?FCMP$fcmp$ftz $r0, $r8, $fcr20, $r39;"o, } ],
FFMA => [
{ type => $x32T, code => 0x5980000000000000, rule => qr"^$pred?FFMA$ftz$rnd$sat $r0, $r8, $fcr20, $r39;"o, },
{ type => $x32T, code => 0x5980000000000000, rule => qr"^$pred?FFMA$ftz$rnd$sat $r0, $r8, $r39s20, $c20s39;"o, },
],
FMNMX => [ { type => $shftT, code => 0x5c60000000000000, rule => qr"^$pred?FMNMX$ftz $r0, $r8, $fcr20, $p39;"o, } ],
FMUL => [ { type => $x32T, code => 0x5c68000000000000, rule => qr"^$pred?FMUL$ftz$rnd$sat $r0, $r8, $fcr20;"o, } ],
FMUL32I => [ { type => $x32T, code => 0x1e00000000000000, rule => qr"^$pred?FMUL32I$ftz $r0, $r8, $f20w32;"o, } ],
FSET => [ { type => $shftT, code => 0x5800000000000000, rule => qr"^$pred?FSET$fcmp$ftz$bool $r0, $r8, $fcr20, $p39;"o, } ],
FSETP => [ { type => $cmpT, code => 0x5bb0000000000000, rule => qr"^$pred?FSETP$fcmp$ftz$bool $p3, $p0, $r8, $fcr20, $p39;"o, } ],
MUFU => [ { type => $qtrT, code => 0x5080000000000000, rule => qr"^$pred?MUFU$func $r0, $r8;"o, } ],
RRO => [ { type => $rroT, code => 0x5c90000000000000, rule => qr"^$pred?RRO$rro $r0, $r20;"o, } ],
DADD => [ { type => $x64T, code => 0x5c70000000000000, rule => qr"^$pred?DADD$rnd $r0, $r8, $dr20;"o, } ],
DFMA => [ { type => $x64T, code => 0x5b70000000000000, rule => qr"^$pred?DFMA$rnd $r0, $r8, $dr20, $r39;"o, } ],
DMNMX => [ { type => $cmpT, code => 0x5c50000000000000, rule => qr"^$pred?DMNMX $r0, $r8, $dr20, $p39;"o, } ],
DMUL => [ { type => $x64T, code => 0x5c80000000000000, rule => qr"^$pred?DMUL$rnd $r0, $r8, $dr20;"o, } ],
DSET => [ { type => $cmpT, code => 0x5900000000000000, rule => qr"^$pred?DSET$fcmp$bool $r0, $r8, $dr20, $p39;"o, } ],
DSETP => [ { type => $cmpT, code => 0x5b80000000000000, rule => qr"^$pred?DSETP$fcmp$bool $p3, $p0, $r8, $dr20, $p39;"o, } ],
FSWZADD => [ { type => $x32T, code => 0x0000000000000000, rule => qr"^$pred?FSWZADD[^;]*;"o, } ], #TODO
HADD2 => [ { type => $x32T, code => 0x5d10000000000000, rule => qr"^$pred?HADD2$hmode$fmz$ftz$sat $r0, $r8, $r20;"o, } ],
HMUL2 => [ { type => $x32T, code => 0x5d08000000000000, rule => qr"^$pred?HMUL2$hmode$fmz$ftz$sat $r0, $r8, $r20;"o, } ],
HFMA2 => [ { type => $x32T, code => 0x5d00000000000000, rule => qr"^$pred?HFMA2$hmode$fmz$ftz$sat $r0, $r8, $r20, $r39;"o, } ],
HSETP2 => [ { type => $cmpT, code => 0x5d20000000000000, rule => qr"^$pred?HSETP2$fcmp$bool $p3, $p0, $r8, $fcr20, $p39;"o, } ], #Partial
#Integer Instructions
BFE => [ { type => $shftT, code => 0x5c01000000000000, rule => qr"^$pred?BFE$u32 $r0, $r8, $icr20;"o, } ],
BFI => [ { type => $shftT, code => 0x5bf0000000000000, rule => qr"^$pred?BFI $r0, $r8, $ir20, $cr39;"o, } ],
FLO => [ { type => $s2rT, code => 0x5c30000000000000, rule => qr"^$pred?FLO\.U32 $r0, $icr20;"o, } ],
IADD => [ { type => $x32T, code => 0x5c10000000000000, rule => qr"^$pred?IADD$sat$X $r0cc, $r8, $icr20;"o, } ],
IADD32I => [ { type => $x32T, code => 0x1c00000000000000, rule => qr"^$pred?IADD32I$X $r0cc, $r8, $i20w32;"o, } ],
IADD3 => [ { type => $x32T, code => 0x5cc0000000000000, rule => qr"^$pred?IADD3$add3 $r0cc, $r8, $icr20, $r39;"o, } ],
ICMP => [ { type => $cmpT, code => 0x5b41000000000000, rule => qr"^$pred?ICMP$icmp$u32 $r0, $r8, $icr20, $r39;"o, } ],
IMNMX => [ { type => $shftT, code => 0x5c21000000000000, rule => qr"^$pred?IMNMX$u32$hilo $r0cc, $r8, $icr20, $p39;"o, } ],
ISET => [ { type => $shftT, code => 0x5b51000000000000, rule => qr"^$pred?ISET$icmp$u32$X$bool $r0, $r8, $icr20, $p39;"o, } ],
ISETP => [ { type => $cmpT, code => 0x5b61000000000000, rule => qr"^$pred?ISETP$icmp$u32$X$bool $p3, $p0, $r8, $icr20, $p39;"o, } ],
ISCADD => [ { type => $shftT, code => 0x5c18000000000000, rule => qr"^$pred?ISCADD $r0, $r8, $icr20, $i39w8;"o, } ],
ISCADD32I => [ { type => $shftT, code => 0x1400000000000000, rule => qr"^$pred?ISCADD32I $r0, $r8, $i20w32, $i53w5;"o, } ],
LEA => [
{ type => $cmpT, code => 0x5bd0000000000000, rule => qr"^$pred?LEA $p48, $r0cc, $r8, $icr20;"o, },
{ type => $shftT, code => 0x5bd7000000000000, rule => qr"^$pred?LEA $r0cc, $r8, $icr20, $i39w8;"o, },
{ type => $shftT, code => 0x5bdf004000000000, rule => qr"^$pred?LEA\.HI$X $r0cc, $r8, $r20, $r39, $i28w8;"o, },
{ type => $shftT, code => 0x0a07000000000000, rule => qr"^$pred?LEA\.HI$X $r0cc, $r8, $c20, $r39, $i51w5;"o, },
],
LOP => [ { type => $x32T, code => 0x5c40000000000000, rule => qr"^$pred?LOP$bool$lopz $r0, $r8, (?<INV>~)?$icr20(?<INV>\.INV)?;"o, } ],
LOP32I => [ { type => $x32T, code => 0x0400000000000000, rule => qr"^$pred?LOP32I$bool $r0, $r8, $i20w32;"o, } ],
LOP3 => [
{ type => $x32T, code => 0x5be7000000000000, rule => qr"^$pred?LOP3\.LUT $r0, $r8, $r20, $r39, $i28w8;"o, },
{ type => $x32T, code => 0x3c00000000000000, rule => qr"^$pred?LOP3\.LUT $r0, $r8, $i20, $r39, $i48w8;"o, },
],
POPC => [ { type => $s2rT, code => 0x5c08000000000000, rule => qr"^$pred?POPC $r0, $r20;"o, } ],
SHF => [
{ type => $shftT, code => 0x5bf8000000000000, rule => qr"^$pred?SHF\.L$shf $r0, $r8, $ir20, $r39;"o, },
{ type => $shftT, code => 0x5cf8000000000000, rule => qr"^$pred?SHF\.R$shf $r0, $r8, $ir20, $r39;"o, },
],
SHL => [ { type => $shftT, code => 0x5c48000000000000, rule => qr"^$pred?SHL(?<W>\.W)? $r0, $r8, $icr20;"o, } ],
SHR => [ { type => $shftT, code => 0x5c29000000000000, rule => qr"^$pred?SHR$u32 $r0, $r8, $icr20;"o, } ],
XMAD => [
{ type => $x32T, code => 0x5b00000000000000, rule => qr"^$pred?XMAD$xmad $r0cc, $r8, $ir20, $r39;"o, },
{ type => $x32T, code => 0x5900000000000000, rule => qr"^$pred?XMAD$xmad $r0cc, $r8, $r39s20, $c20s39;"o, },
{ type => $x32T, code => 0x5e00000000000000, rule => qr"^$pred?XMAD$xmadc $r0cc, $r8, $c20x, $r39;"o, },
],
# XMAD replaces these
IMAD => [ { type => $x32T, code => 0x0000000000000000, rule => qr"^$pred?IMAD[^;]*;"o, } ], #TODO
IMADSP => [ { type => $x32T, code => 0x0000000000000000, rule => qr"^$pred?IMADSP[^;]*;"o, } ], #TODO
IMUL => [ { type => $x32T, code => 0x0000000000000000, rule => qr"^$pred?IMUL[^;]*;"o, } ], #TODO
#Conversion Instructions
F2F => [ { type => $qtrT, code => 0x5ca8000000000000, rule => qr"^$pred?F2F$ftz$x2x$rnd$round$sat $r0, $cr20;"o, } ],
F2I => [ { type => $qtrT, code => 0x5cb0000000000000, rule => qr"^$pred?F2I$ftz$x2x$round $r0, $cr20;"o, } ],
I2F => [ { type => $qtrT, code => 0x5cb8000000000000, rule => qr"^$pred?I2F$x2x$rnd $r0, $cr20;"o, } ],
I2I => [ { type => $qtrT, code => 0x5ce0000000000000, rule => qr"^$pred?I2I$x2x$sat $r0, $cr20;"o, } ],
#Movement Instructions
MOV => [ { type => $x32T, code => 0x5c98078000000000, rule => qr"^$pred?MOV $r0, $icr20;"o, } ],
MOV32I => [ { type => $x32T, code => 0x010000000000f000, rule => qr"^$pred?MOV32I $r0, (?:$i20w32|$f20w32);"o, } ],
PRMT => [ { type => $x32T, code => 0x5bc0000000000000, rule => qr"^$pred?PRMT$prmt $r0, $r8, $icr20, $cr39;"o, } ],
SEL => [ { type => $x32T, code => 0x5ca0000000000000, rule => qr"^$pred?SEL $r0, $r8, $icr20, $p39;"o, } ],
SHFL => [ { type => $smemT, code => 0xef10000000000000, rule => qr"^$pred?SHFL$shfl $p48, $r0, $r8, (?:$i20w8|$r20), (?:$i34w13|$r39);"o, } ],
#Predicate/CC Instructions
PSET => [ { type => $cmpT, code => 0x5088000000000000, rule => qr"^$pred?PSET$bool2$bool $r0, $p12, $p29, $p39;"o, } ],
PSETP => [ { type => $cmpT, code => 0x5090000000000000, rule => qr"^$pred?PSETP$bool2$bool $p3, $p0, $p12, $p29, $p39;"o, } ],
CSET => [ { type => $x32T, code => 0x0000000000000000, rule => qr"^$pred?CSET[^;]*;"o, } ], #TODO
CSETP => [ { type => $x32T, code => 0x0000000000000000, rule => qr"^$pred?CSETP[^;]*;"o, } ], #TODO
P2R => [ { type => $x32T, code => 0x38e8000000000000, rule => qr"^$pred?P2R $r0, PR, $r8, $i20w7;"o, } ],
R2P => [ { type => $shftT, code => 0x38f0000000000000, rule => qr"^$pred?R2P PR, $r8, $i20w7;"o, } ],
#Texture Instructions
# Handle the commonly used 1D texture functions.. but save the others for later
TLD => [ { type => $gmemT, code => 0xdd38000000000000, rule => qr"^$pred?TLD\.B\.LZ\.$tld $r0, $r8, $r20, $hex, \dD, $i31w4;"o, } ], #Partial
TLDS => [ { type => $gmemT, code => 0xda0000000ff00000, rule => qr"^$pred?TLDS\.LZ\.$tld $r28, $r0, $r8, $i36w20, \dD, $chnls;"o,} ], #Partial
TEX => [ { type => $gmemT, code => 0x0000000000000000, rule => qr"^$pred?TEX[^;]*;"o, } ], #TODO
TLD4 => [ { type => $gmemT, code => 0x0000000000000000, rule => qr"^$pred?TLD4[^;]*;"o, } ], #TODO
TXQ => [ { type => $gmemT, code => 0x0000000000000000, rule => qr"^$pred?TXQ[^;]*;"o, } ], #TODO
TEXS => [ { type => $gmemT, code => 0x0000000000000000, rule => qr"^$pred?TEXS[^;]*;"o, } ], #TODO
TLD4S => [ { type => $gmemT, code => 0x0000000000000000, rule => qr"^$pred?TLD4S[^;]*;"o, } ], #TODO
#Compute Load/Store Instructions
LD => [ { type => $gmemT, code => 0x8000000000000000, rule => qr"^$pred?LD$memCache$memType $r0, $addr, $p58;"o, } ],
ST => [ { type => $gmemT, code => 0xa000000000000000, rule => qr"^$pred?ST$memCache$memType $addr, $r0, $p58;"o, } ],
LDG => [ { type => $gmemT, code => 0xeed0000000000000, rule => qr"^$pred?LDG$memCache$memType $r0, $addr;"o, } ],
STG => [ { type => $gmemT, code => 0xeed8000000000000, rule => qr"^$pred?STG$memCache$memType $addr, $r0;"o, } ],
LDS => [ { type => $smemT, code => 0xef48000000000000, rule => qr"^$pred?LDS$memCache$memType $r0, $addr;"o, } ],
STS => [ { type => $smemT, code => 0xef58000000000000, rule => qr"^$pred?STS$memCache$memType $addr, $r0;"o, } ],
LDL => [ { type => $gmemT, code => 0xef40000000000000, rule => qr"^$pred?LDL$memCache$memType $r0, $addr;"o, } ],
STL => [ { type => $gmemT, code => 0xef50000000000000, rule => qr"^$pred?STL$memCache$memType $addr, $r0;"o, } ],
LDC => [ { type => $gmemT, code => 0xef90000000000000, rule => qr"^$pred?LDC$memCache$memType $r0, $ldc;"o, } ],
# Note for ATOM(S).CAS operations the last register needs to be in sequence with the second to last (as it's not encoded).
ATOM => [ { type => $gmemT, code => 0xed00000000000000, rule => qr"^$pred?ATOM$atom $r0, $addr2, $r20(?:, $r39a)?;"o, } ],
ATOMS => [ { type => $smemT, code => 0xec00000000000000, rule => qr"^$pred?ATOMS$atom $r0, $addr2, $r20(?:, $r39a)?;"o, } ],
RED => [ { type => $gmemT, code => 0xebf8000000000000, rule => qr"^$pred?RED$atom $addr2, $r0;"o, } ],
CCTL => [ { type => $x32T, code => 0x5c88000000000000, rule => qr"^$pred?CCTL[^;]*;"o, } ], #TODO
CCTLL => [ { type => $x32T, code => 0x5c88000000000000, rule => qr"^$pred?CCTLL[^;]*;"o, } ], #TODO
CCTLT => [ { type => $x32T, code => 0x5c88000000000000, rule => qr"^$pred?CCTLT[^;]*;"o, } ], #TODO
#Surface Memory Instructions (haven't gotten to these yet..)
SUATOM => [ { type => $x32T, code => 0x0000000000000000, rule => qr"^$pred?SUATOM[^;]*;"o, } ], #TODO
SULD => [ { type => $x32T, code => 0x0000000000000000, rule => qr"^$pred?SULD[^;]*;"o, } ], #TODO
SURED => [ { type => $x32T, code => 0x0000000000000000, rule => qr"^$pred?SURED[^;]*;"o, } ], #TODO
SUST => [ { type => $x32T, code => 0x0000000000000000, rule => qr"^$pred?SUST[^;]*;"o, } ], #TODO
#Control Instructions
BRA => [
{ type => $x32T, code => 0xe24000000000000f, rule => qr"^$pred?BRA(?<U>\.U)? $i20w24;"o, },
{ type => $x32T, code => 0xe240000000000002, rule => qr"^$pred?BRA(?<U>\.U)? CC\.EQ, $i20w24;"o, },
],
BRX => [ { type => $x32T, code => 0x0000000000000000, rule => qr"^$pred?BRX[^;]*;"o, } ], #TODO
JMP => [ { type => $x32T, code => 0x0000000000000000, rule => qr"^$pred?JMP[^;]*;"o, } ], #TODO
JMX => [ { type => $x32T, code => 0x0000000000000000, rule => qr"^$pred?JMX[^;]*;"o, } ], #TODO
SSY => [ { type => $x32T, code => 0xe290000000000000, rule => qr"^$noPred?SSY $i20w24;"o, } ],
SYNC => [ { type => $x32T, code => 0xf0f800000000000f, rule => qr"^$pred?SYNC;"o, } ],
CAL => [ { type => $x32T, code => 0xe260000000000040, rule => qr"^$noPred?CAL $i20w24;"o, } ],
JCAL => [ { type => $x32T, code => 0xe220000000000040, rule => qr"^$noPred?JCAL $i20w24;"o, } ],
PRET => [ { type => $x32T, code => 0x0000000000000000, rule => qr"^$pred?PRET[^;]*;"o, } ], #TODO
RET => [ { type => $x32T, code => 0xe32000000000000f, rule => qr"^$pred?RET;"o, } ],
BRK => [ { type => $x32T, code => 0xe34000000000000f, rule => qr"^$pred?BRK;"o, } ],
PBK => [ { type => $x32T, code => 0xe2a0000000000000, rule => qr"^$noPred?PBK $i20w24;"o, } ],
CONT => [ { type => $x32T, code => 0xe35000000000000f, rule => qr"^$pred?CONT;"o, } ],
PCNT => [ { type => $x32T, code => 0xe2b0000000000000, rule => qr"^$noPred?PCNT $i20w24;"o, } ],
EXIT => [ { type => $x32T, code => 0xe30000000000000f, rule => qr"^$pred?EXIT;"o, } ],
PEXIT => [ { type => $x32T, code => 0x0000000000000000, rule => qr"^$pred?PEXIT[^;]*;"o, } ], #TODO
BPT => [ { type => $x32T, code => 0xe3a00000000000c0, rule => qr"^$noPred?BPT\.TRAP $i20w24;"o, } ],
#Miscellaneous Instructions
NOP => [ { type => $x32T, code => 0x50b0000000000f00, rule => qr"^$pred?NOP;"o, } ],
CS2R => [ { type => $x32T, code => 0x50c8000000000000, rule => qr"^$pred?CS2R $r0, $sr;"o, } ],
S2R => [ { type => $s2rT, code => 0xf0c8000000000000, rule => qr"^$pred?S2R $r0, $sr;"o, } ],
B2R => [ { type => $x32T, code => 0xf0b800010000ff00, rule => qr"^$pred?B2R$b2r;"o, } ],
BAR => [ { type => $gmemT, code => 0xf0a8000000000000, rule => qr"^$pred?BAR$bar;"o, } ],
DEPBAR => [
{ type => $gmemT, code => 0xf0f0000000000000, rule => qr"^$pred?DEPBAR$icmp $dbar, $i20w6;"o, },
{ type => $gmemT, code => 0xf0f0000000000000, rule => qr"^$pred?DEPBAR$dbar2;"o, },
],
MEMBAR => [ { type => $x32T, code => 0xef98000000000000, rule => qr"^$pred?MEMBAR$mbar;"o, } ],
VOTE => [ { type => $voteT, code => 0x50d8000000000000, rule => qr"^$pred?VOTE$vote (?:$r0, |(?<nor0>))$p45, $p39;"o, } ],
R2B => [ { type => $x32T, code => 0x0000000000000000, rule => qr"^$pred?R2B[^;]*;"o, } ], #TODO
#Video Instructions... Need to finish
VADD => [ { type => $shftT, code => 0x2044000000000000, rule => qr"^$pred?VADD$vaddType$sat$vaddMode $r0, $r8, $r20, $r39;"o, } ], #Partial 0x2044000000000000
VMAD => [
{ type => $x32T, code => 0x5f04000000000000, rule => qr"^$pred?VMAD$vmad16 $r0, $r8, $r20, $r39;"o, },
{ type => $shftT, code => 0x5f04000000000000, rule => qr"^$pred?VMAD$vmad8 $r0, $r8, $r20, $r39;"o, },
],
VABSDIFF => [ { type => $shftT, code => 0x5427000000000000, rule => qr"^$pred?VABSDIFF$vaddType$sat$vaddMode $r0, $r8, $r20, $r39;"o, } ], #Partial 0x2044000000000000
VMNMX => [ { type => $shftT, code => 0x3a44000000000000, rule => qr"^$pred?VMNMX$vaddType$vmnmx$sat$vaddMode $r0, $r8, $r20, $r39;"o, } ], #Partial 0x2044000000000000
VSET => [ { type => $shftT, code => 0x4004000000000000, rule => qr"^$pred?VSET$icmp$vaddType$vaddMode $r0, $r8, $r20, $r39;"o, } ], #Partial 0x2044000000000000
DP4A => [ { type => $x32T, code => 0x53f8000000000000, rule => qr"^$pred?DP4A$dptype $r0, $r8, $icr20, $r39;"o, } ],
DP2A => [ { type => $x32T, code => 0x53f9000000000000, rule => qr"^$pred?DP2A$dpmode$dptype $r0, $r8, $icr20, $r39;"o, } ],
);
# Create map of capture groups to op code flags that need to be added (or removed)
my @flags = grep /\S/, split "\n", q{;
BFE, BFI, FLO, IADD, IADD3, ICMP, IMNMX, ISCADD, ISET, ISETP, LEA, LOP, LOP3, MOV, PRMT, SEL, SHF, SHL, SHR, XMAD
0x0100000000000000 neg
FADD, FCMP, FFMA, FMNMX, FMUL, FSET, FSETP, DADD, DFMA, DMNMX, DMUL, DSET, DSETP
0x0100000000000000 neg
PSET, PSETP
0x0000000000008000 p12not
0x0000000100000000 p29not
FMNMX, FSET, FSETP, DMNMX, DSET, DSETP, IMNMX, ISET, ISETP, SEL, PSET, PSETP, BAR, VOTE
0x0000040000000000 p39not
IADD, IADD3, XMAD, LEA, IMNMX
0x0000800000000000 CC
IADD32I
0x0010000000000000 CC
LEA
0x0000000000000000 X
SHF
0x0004000000000000 W
0x0001000000000000 HI
SHF: type
0x0000004000000000 U64
0x0000006000000000 S64
SHR, IMNMX, ISETP, ISET, ICMP, BFE
0x0001000000000000 U32
SHL
0x0000008000000000 W
SHFL
0x0000000010000000 i20w8
0x0000000020000000 i34w13
SHFL: mode
0x0000000000000000 IDX
0x0000000040000000 UP
0x0000000080000000 DOWN
0x00000000c0000000 BFLY
IMNMX: mode
0x0000080000000000 XLO
0x0000180000000000 XHI
ISETP, ISET, ICMP: cmp
0x0002000000000000 LT
0x0004000000000000 EQ
0x0006000000000000 LE
0x0008000000000000 GT
0x000a000000000000 NE
0x000c000000000000 GE
ISETP, ISET, PSETP, PSET: bool
0x0000000000000000 AND
0x0000200000000000 OR
0x0000400000000000 XOR
PSETP, PSET: bool2
0x0000000000000000 AND
0x0000000001000000 OR
0x0000000002000000 XOR
ISETP, ISET
0x0000080000000000 X
LOP: bool
0x0000000000000000 AND
0x0000020000000000 OR
0x0000040000000000 XOR
0x0000060000000000 PASS_B
LOP:
0x0000010000000000 INV
LOP: z
0x0000200000000000 Z
0x0000300000000000 NZ
LOP
0x0007000000000000 noz
LOP32I: bool
0x0000000000000000 AND
0x0020000000000000 OR
0x0040000000000000 XOR
PRMT: mode
0x0001000000000000 F4E
0x0002000000000000 B4E
0x0003000000000000 RC8
0x0004000000000000 ECL
0x0005000000000000 ECR
0x0006000000000000 RC16
XMAD: type1
0x0000000000000000 U16
0x0001000000000000 S16
XMAD: type2
0x0000000000000000 U16
0x0002000000000000 S16
XMAD: mode
0x0000002000000000 MRG
0x0000001000000000 PSL
0x0008000000000000 CHI
0x0004000000000000 CLO
0x000c000000000000 CSFU
0x0004001000000000 PSL.CLO
XMAD: modec
0x0004000000000000 CLO
0x0008000000000000 CHI
0x000c000000000000 CSFU
0x0040000000000000 X
0x0080000000000000 PSL
0x0100000000000000 MRG
0x0084000000000000 PSL.CLO
XMAD
0x0010000000000000 CBCC
XMAD: r8part
0x0000000000000000 H0
0x0020000000000000 H1
XMAD: r20part
0x0000000000000000 H0
0x0000000800000000 H1
XMAD: r20partx
0x0000000000000000 H0
0x0010000000000000 H1
XMAD: r39part
0x0000000000000000 H0
0x0010000000000000 H1
VMAD, VADD, VABSDIFF, VMNMX, VSET: r8part
0x0000000000000000 B0
0x0000001000000000 B1
0x0000002000000000 B2
0x0000003000000000 B3
0x0000001000000000 H1
0x0000000000000000 H0
VMAD, VADD, VABSDIFF, VMNMX, VSET: r20part
0x0000000000000000 B0
0x0000000010000000 B1
0x0000000020000000 B2
0x0000000030000000 B3
0x0000000010000000 H1
0x0000000000000000 H0
VMAD
0x0040000000000000 r8neg
0x0020000000000000 r39neg
0x0008000000000000 SHR_7
0x0010000000000000 SHR_15
0x0060000000000000 PO
0x0080000000000000 SAT
VMNMX
0x0100000000000000 MX
VADD, VABSDIFF, VMNMX
0x0080000000000000 SAT
0x0040000000000000 UD
0x0040000000000000 SD
VSET: cmp
0x0040000000000000 LT
0x0080000000000000 EQ
0x00c0000000000000 LE
0x0100000000000000 GT
0x0140000000000000 NE
0x0180000000000000 GE
VADD, VSET: mode
0x0020000000000000 ACC
0x0028000000000000 MIN
0x0030000000000000 MAX
0x0000000000000000 MRG_16H
0x0008000000000000 MRG_16L
0x0010000000000000 MRG_8B0
0x0000000000000000 MRG_8B1
0x0018000000000000 MRG_8B2
0x0000000000000000 MRG_8B3
VABSDIFF: mode
0x0003000000000000 ACC
0x000b000000000000 MIN
0x0013000000000000 MAX
0x0023000000000000 MRG_16H
0x002b000000000000 MRG_16L
0x0033000000000000 MRG_8B0
0x0000000000000000 MRG_8B1
0x003b000000000000 MRG_8B2
0x0000000000000000 MRG_8B3
VMNMX: mode
0x0020000000000000 ACC
0x0028000000000000 MIN
0x0030000000000000 MAX
0x0000000000000000 MRG_16H
0x0008000000000000 MRG_16L
0x0010000000000000 MRG_8B0
0x0000000000000000 MRG_8B1
0x0018000000000000 MRG_8B2
0x0000000000000000 MRG_8B3
VMAD, VADD, VABSDIFF, VMNMX, VSET: sign1
0x0000000000000000 U
0x0001000000000000 S
VMAD, VADD, VABSDIFF, VMNMX, VSET: sign2
0x0000000000000000 U
0x0002000000000000 S
VMAD, VADD, VABSDIFF, VMNMX, VSET: size1
0x0000000000000000 8
0x0000004000000000 16
0x0000006000000000 32
VMAD, VADD, VABSDIFF, VMNMX, VSET: size2
0x0000000000000000 8
0x0000000040000000 16
0x0000000060000000 32
IADD3: type
0x0001000000000000 X
0x0000002000000000 RS
0x0000004000000000 LS
IADD3: r8part
0x0000000000000000 H0
0x0000001000000000 H1
IADD3: r20part
0x0000000080000000 H0
IADD3: r39part
0x0000000200000000 H0
IADD3
0x0008000000000000 r8neg
0x0004000000000000 r20neg
0x0002000000000000 r39neg
IADD
0x0000080000000000 X
0x0004000000000000 SAT
IADD, ISCADD
0x0002000000000000 r8neg
0x0001000000000000 r20neg
IADD32I
0x0100000000000000 r8neg
0x0020000000000000 X
DEPBAR: SB
0x0000000000000000 SB0
0x0000000004000000 SB1
0x0000000008000000 SB2
0x000000000c000000 SB3
0x0000000010000000 SB4
0x0000000014000000 SB5
DEPBAR: cmp
0x0000000020000000 LE
DEPBAR
0x0000000000000001 db0
0x0000000000000002 db1
0x0000000000000004 db2
0x0000000000000008 db3
0x0000000000000010 db4
0x0000000000000020 db5
F2F, F2I, I2F, I2I: destWidth
0x0000000000000000 8
0x0000000000000100 16
0x0000000000000200 32
0x0000000000000300 64
F2F, F2I, I2F, I2I: srcWidth
0x0000000000000000 8
0x0000000000000400 16
0x0000000000000800 32
0x0000000000000c00 64
F2F, F2I, I2F, I2I: destSign
0x0000000000000000 F
0x0000000000000000 U
0x0000000000001000 S
F2F, F2I, I2F, I2I: srcSign
0x0000000000000000 F
0x0000000000000000 U
0x0000000000002000 S
F2I, I2F, I2I: r20part
0x0000000000000000 H0
0x0000040000000000 H1
0x0000000000000000 B0
0x0000020000000000 B1
0x0000040000000000 B2
0x0000060000000000 B3
F2F: r20part
0x0000000000000000 H0
0x0000020000000000 H1
F2F: round
0x0000040000000000 ROUND
0x0000048000000000 FLOOR
0x0000050000000000 CEIL
0x0000058000000000 TRUNC
F2I: round
0x0000000000000000 ROUND
0x0000008000000000 FLOOR
0x0000010000000000 CEIL
0x0000018000000000 TRUNC
HADD2, HMUL2, HFMA2: r8part
0x0001000000000000 H0_H0
0x0001800000000000 H1_H1
0x0000800000000000 F32
HADD2, HMUL2, HFMA2: r20part
0x0000000020000000 H0_H0
0x0000000030000000 H1_H1
HFMA2: r39part
0x0000000800000000 F32
0x0000001000000000 H0_H0
0x0000001800000000 H1_H1
HADD2, HMUL2, HFMA2
0x0000000080000000 r20neg
0x0000000040000000 r39neg
HADD2, HMUL2, HFMA2: mode
0x0002000000000000 F32
0x0004000000000000 MRG_H0
0x0006000000000000 MRG_H1
HADD2, HMUL2
0x0000008000000000 FTZ
HFMA2
0x0000002000000000 FTZ
HFMA2
0x0000004000000000 FMZ
HADD2, HMUL2, HFMA2
0x0000000100000000 SAT
FADD, DADD, FMUL, DMUL, F2F, I2F: rnd
0x0000000000000000 RN
0x0000008000000000 RM
0x0000010000000000 RP
0x0000018000000000 RZ
DFMA: rnd
0x0000000000000000 RN
0x0004000000000000 RM
0x0008000000000000 RP
0x000c000000000000 RZ
FFMA: rnd
0x0000000000000000 RN
0x0008000000000000 RM
0x0010000000000000 RP
0x0018000000000000 RZ
FFMA
0x0020000000000000 FTZ
F2F, F2I, FADD, FMUL, FMNMX
0x0000100000000000 FTZ
FADD32I
0x0080000000000000 FTZ
FMUL32I
0x0020000000000000 FTZ
FSET
0x0080000000000000 FTZ
FSETP, FCMP
0x0000800000000000 FTZ
FADD, FFMA, FMUL, F2F, I2I
0x0004000000000000 SAT
FADD, DADD, FMNMX, DMNMX, MUFU
0x0001000000000000 r8neg
FADD, DADD, FMNMX, DMNMX, RRO, F2F, F2I, I2F, I2I
0x0000200000000000 r20neg
FMUL, DMUL, FFMA, DFMA
0x0001000000000000 r20neg
FFMA, DFMA
0x0002000000000000 r39neg
FADD, DADD, FMNMX, DMNMX
0x0000400000000000 r8abs
FADD, DADD, FMNMX, DMNMX, F2F, F2I, I2F, I2I
0x0002000000000000 r20abs
FSETP, DSETP, FSET, DSET
0x0000080000000000 r8neg
0x0000000000000040 r20neg
0x0000000000000080 r8abs
0x0000100000000000 r20abs
RRO: func
0x0000000000000000 SINCOS
0x0000008000000000 EX2
MUFU: func
0x0000000000000000 COS
0x0000000000100000 SIN
0x0000000000200000 EX2
0x0000000000300000 LG2
0x0000000000400000 RCP
0x0000000000500000 RSQ
0x0000000000600000 RCP64H
0x0000000000700000 RSQ64H
FSETP, DSETP, FSET, DSET, FCMP: cmp
0x0001000000000000 .LT
0x0002000000000000 .EQ
0x0003000000000000 .LE
0x0004000000000000 .GT
0x0004000000000000
0x0005000000000000 .NE
0x0006000000000000 .GE
0x0007000000000000 .NUM
0x0008000000000000 .NAN
0x0009000000000000 .LTU
0x000a000000000000 .EQU
0x000b000000000000 .LEU
0x000c000000000000 .GTU
0x000d000000000000 .NEU
0x000e000000000000 .GEU
FSETP, DSETP, FSET, DSET: bool
0x0000000000000000 AND
0x0000200000000000 OR
0x0000400000000000 XOR
HSETP2: cmp
0x0000002800000000 .NE
HSETP2: bool
0x0000000000000000 AND
S2R: sr
0x0000000000000000 LANEID
0x0000000000200000 VIRTCFG
0x0000000000300000 VIRTID
0x0000000002100000 TID.X
0x0000000002200000 TID.Y
0x0000000002300000 TID.Z
0x0000000002500000 CTAID.X
0x0000000002600000 CTAID.Y
0x0000000002700000 CTAID.Z
0x0000000003800000 EQMASK
0x0000000003900000 LTMASK
0x0000000003a00000 LEMASK
0x0000000003b00000 GTMASK
0x0000000003c00000 GEMASK
CS2R: sr
0x0000000005000000 CLOCKLO
0x0000000005100000 CLOCKHI
0x0000000005200000 GLOBALTIMERLO
0x0000000005300000 GLOBALTIMERHI
B2R
0x0000e00000000000 nop45
BAR
0x0000100000000000 i8w4
0x0000080000000000 nor20
0x0000038000000000 nop39
BAR: mode
0x0000000000000000 SYNC
0x0000000100000000 ARV
0x0000000200000000 RED
BAR: red
0x0000000000000000 POPC
0x0000000800000000 AND
0x0000001000000000 OR
MEMBAR: mode
0x0000000000000000 CTA
0x0000000000000100 GL
0x0000000000000200 SYS
VOTE: mode
0x0000000000000000 ALL
0x0001000000000000 ANY
0x0002000000000000 EQ
VOTE
0x00000000000000ff nor0
BRA
0x0000000000000080 U
TLDS: chnls
0x0010000000000000 RGBA
TLDS
0x0002000000000000 NODEP
LD, ST, LDG, STG, LDS, STS, LDL, STL, LDC, RED, ATOM, ATOMS
0x000000000000ff00 nor8
LD, ST: type
0x0000000000000000 .U8
0x0020000000000000 .S8
0x0040000000000000 .U16
0x0060000000000000 .S16
0x0080000000000000
0x0080000000000000 .32
0x00a0000000000000 .64
0x00c0000000000000 .128
LD, ST: cache
0x0100000000000000 CG
0x0200000000000000 CS
0x0300000000000000 CV
0x0300000000000000 WT
LDG, STG, LDS, STS, LDL, STL, LDC: type
0x0000000000000000 .U8
0x0001000000000000 .S8
0x0002000000000000 .U16
0x0003000000000000 .S16
0x0004000000000000
0x0004000000000000 .32
0x0005000000000000 .64
0x0006000000000000 .128
LDG, STG: cache
0x0000400000000000 CG
0x0000800000000000 CI
0x0000800000000000 CS
0x0000c00000000000 CV
0x0000c00000000000 WT
LDL: cache
0x0000200000000000 CI
LDC: cache
0x0000100000000000 IL
LDG, STG, LDS, STS, LDL, STL, LDC
0x0000200000000000 E
LDS
0x0000100000000000 U
RED: type
0x0000000000000000
0x0000000000100000 .S32
0x0000000000200000 .U64
0x0000000000300000 .F32.FTZ.RN
0x0000000000400000 .F16x2.FTZ.RN
0x0000000000500000 .S64
RED: mode
0x0000000000000000 ADD
0x0000000000800000 MIN
0x0000000001000000 MAX
0x0000000001800000 INC
0x0000000002000000 DEC
0x0000000002800000 AND
0x0000000003000000 OR
0x0000000003800000 XOR
ATOM: type
0x0000000000000000
0x0002000000000000 .S32
0x0004000000000000 .U64
0x0006000000000000 .F32.FTZ.RN
0x0008000000000000 .F16x2.FTZ.RN
0x000a000000000000 .S64
0x0002000000000000 .64
ATOM, RED
0x0001000000000000 E
ATOM: mode
0x0000000000000000 ADD
0x0010000000000000 MIN
0x0020000000000000 MAX
0x0030000000000000 INC
0x0040000000000000 DEC
0x0050000000000000 AND
0x0060000000000000 OR
0x0070000000000000 XOR
0x0080000000000000 EXCH
0x03f0000000000000 CAS
ATOMS: type
0x0000000000000000
0x0000000010000000 .S32
0x0000000020000000 .U64
0x0000000030000000 .S64
0x0010000000000000 .64
ATOMS: mode
0x0000000000000000 ADD
0x0010000000000000 MIN
0x0020000000000000 MAX
0x0030000000000000 INC
0x0040000000000000 DEC
0x0050000000000000 AND
0x0060000000000000 OR
0x0070000000000000 XOR
0x0080000000000000 EXCH
0x0240000000000000 CAS
DP4A, DP2A: type1
0x0000000000000000 U32
0x0002000000000000 S32
DP4A, DP2A: type2
0x0000000000000000 U32
0x0000800000000000 S32
DP2A: mode
0x0000000000000000 LO
0x0004000000000000 HI
};
# The existence of a capture group can map directly to an op code adjustment, or...
# The named capture group value can map the op code adjustmemt from among several options
our %flags;
my (@ops, $flag);
foreach my $line (@flags)
{
if ($line =~ m'^(0x[0-9a-z]+)\s*(.*)')
{
my $val = hex($1);
# named rules (op: name)
if ($flag)
{ $flags{$_}{$flag}{$2} = $val foreach @ops; }
# simple existence check rules
else
{ $flags{$_}{$2} = $val foreach @ops; }
}
else
{
my ($ops, $name) = split ':\s*', $line;
@ops = split ',\s*', $ops;
$flag = $name;
}
}
sub parseInstruct
{
my ($inst, $grammar) = @_;
return unless $inst =~ $grammar->{rule};
my %capData = %+;
return \%capData;
}
# for immediate or constant operands and a given opcode, bits 56-63 get transformed
my %immedOps = map { $_ => 1 } qw(i20 f20 d20);
my %immedCodes =
(
0x5c => 0x64,
0x5b => 0x6d,
0x59 => 0x6b,
0x58 => 0x68,
);
my %constCodes =
(
c20 => 0x10,
c39 => 0x08,
);
my %reuseCodes = (reuse1 => 1, reuse2 => 2, reuse3 => 4);
# just pick out the reuse code and nothing else
sub genReuseCode
{
my $capData = shift;
my $reuse = 0;
$reuse |= $reuseCodes{$_} foreach grep $capData->{$_}, keys %reuseCodes;
return $reuse;
}
# Generate an op code from regex capture data
# if you pass in a test array ref it will populate it with the matching capture groups
sub genCode
{
my ($op, $grammar, $capData, $test) = @_;
my $flags = $flags{$op};
my $code = $grammar->{code};
my $reuse = 0;
my $immedCode = $immedCodes{$code >> 56};
#print map "$_: $capData->{$_}\n", keys %capData if $op eq 'I2I';
# process the instruction predicate (if valid for this instuction)
if (exists $capData->{noPred})
{
delete $capData->{noPred};
push @$test, 'noPred' if $test;
}
else
{
my $p = defined($capData->{predNum}) ? $capData->{predNum} : 7;
push @$test, 'predNum' if $test;
if (exists $capData->{predNot})
{
$p |= 8;
push @$test, 'predNot' if $test;
}
$code ^= $p << 16;
delete @{$capData}{qw(predNum predNot)};
}
# process the register reuse flags
foreach my $rcode (qw(reuse1 reuse2 reuse3))
{
if (delete $capData->{$rcode})
{
$reuse |= $reuseCodes{$rcode};
push @$test, $rcode if $test;
}
}
foreach my $capture (keys %$capData)
{
# change the base code for immediate versions of the op
if (exists $immedOps{$capture})
{ $code ^= $immedCode << 56; }
# change the base code for constant versions of the op
elsif (exists $constCodes{$capture})
{ $code ^= $constCodes{$capture} << 56; }
# if capture group is an operand then process and add that data to code
if (exists $operands{$capture})
{
# don't process the r20 that comes with the r39s20 capture
unless ($capture eq 'r20' && exists $capData->{r39s20})
{
$code ^= $operands{$capture}->($capData->{$capture});
push @$test, $capture if $test;
}
}
# Add matching flags (an operand might also add/remove a flag)
if (exists $flags->{$capture})
{
# a named multivalue flag
if (ref $flags->{$capture})
{
$code ^= $flags->{$capture}{$capData->{$capture}};
push @$test, "$capture:$capData->{$capture}" if $test;
}
# a simple exists flag
else
{
$code ^= $flags->{$capture};
push @$test, $capture if $test;
}
}
elsif (!exists $operands{$capture} && !$test)
{
# Every capture group should be acted upon. Missing one is a bug.
warn "UNUSED: $op: $capture: $capData->{$capture}\n";
warn Dumper($flags);
}
}
return $code, $reuse;
}
my $CtrlRe = qr'(?<ctrl>[0-9a-fA-F\-]{2}:[1-6\-]:[1-6\-]:[\-yY]:[0-9a-fA-F])';
my $PredRe = qr'(?<pred>@!?(?<predReg>P\d)\s+)';
my $InstRe = qr"$PredRe?(?<op>\w+)(?<rest>[^;]*;)"o;
my $CommRe = qr'(?<comment>.*)';
sub processAsmLine
{
my ($line, $lineNum) = @_;
if ($line =~ m"^$CtrlRe(?<space>\s+)$InstRe$CommRe"o)
{
return {
lineNum => $lineNum,
pred => $+{pred},
predReg => $+{predReg},
space => $+{space},
op => $+{op},
comment => $+{comment},
inst => normalizeSpacing($+{pred} . $+{op} . $+{rest}),
ctrl => readCtrl($+{ctrl}, $line),
};
}
return undef;
}
sub processSassLine
{
my $line = shift;
if ($line =~ m"^\s+/\*(?<num>[0-9a-f]+)\*/\s+$InstRe\s+/\* (?<code>0x[0-9a-f]+)"o)
{
return {
num => hex($+{num}),
pred => $+{pred},
op => $+{op},
ins => normalizeSpacing($+{op} . $+{rest}),
inst => normalizeSpacing($+{pred} . $+{op} . $+{rest}),
code => hex($+{code}),
};
}
return undef;
}
sub processSassCtrlLine
{
my ($line, $ctrl, $ruse) = @_;
return 0 unless $line =~ m'^\s+\/\* (0x[0-9a-f]+)';
my $code = hex($1);
if (ref $ctrl)
{
push @$ctrl, ($code & 0x000000000001ffff) >> 0;
push @$ctrl, ($code & 0x0000003fffe00000) >> 21;
push @$ctrl, ($code & 0x07fffc0000000000) >> 42;
}
if (ref $ruse)
{
push @$ruse, ($code & 0x00000000001e0000) >> 17;
push @$ruse, ($code & 0x000003c000000000) >> 38;
push @$ruse, ($code & 0x7800000000000000) >> 59;
}
return 1;
}
sub replaceXMADs
{
my $file = shift;
# XMAD.LO d, a, b, c, x;
# ----------------------
# XMAD.MRG x, a, b.H1, RZ;
# XMAD d, a, b, c;
# XMAD.PSL.CBCC d, a.H1, x.H1, d;
# ----------------------
# XMAD d, a, 0xffff, c;
# XMAD.PSL d, a.H1, 0xffff, d;
$file =~ s/\n\s*$CtrlRe(?<space>\s+)($PredRe)?XMAD\.LO\s+(?<d>\w+)\s*,\s*(?<a>\w+)\s*,\s*(?<b>c\[$hex\]\[$hex\]|\w+)\s*,\s*(?<c>c\[$hex\]\[$hex\]|\w+)\s*,\s*(?<x>\w+)\s*;$CommRe/
die "XMAD.LO: Destination and first operand cannot be the same register ($+{d})." if $+{d} eq $+{a};
sprintf '
%1$s%2$s%3$sXMAD.MRG %8$s, %5$s, %6$s.H1, RZ;%9$s
%1$s%2$s%3$sXMAD %4$s, %5$s, %6$s, %7$s;
%1$s%2$s%3$sXMAD.PSL.CBCC %4$s, %5$s.H1, %8$s.H1, %4$s;',
@+{qw(ctrl space pred d a b c x comment)}
/egmos;
$file =~ s/\n\s*$CtrlRe(?<space>\s+)($PredRe)?XMAD(?<mod>(?:\.[SU]16)(?:\.[SU]16))?\.LO2\s+(?<d>\w+)\s*,\s*(?<a>\w+)\s*,\s*(?<b>-?$immed|\w+)\s*,\s*(?<c>c\[$hex\]\[$hex\]|\w+)\s*;$CommRe/
die "XMAD.LO2: Destination and first operand cannot be the same register ($+{d})." if $+{d} eq $+{a};
sprintf '
%1$s%2$s%3$sXMAD%9$s %4$s, %5$s, %6$s, %7$s;%8$s
%1$s%2$s%3$sXMAD%9$s.PSL %4$s, %5$s.H1, %6$s, %4$s;',
@+{qw(ctrl space pred d a b c comment mod)}
/egmos;
$file =~ s/\n\s*$CtrlRe(?<space>\s+)($PredRe)?XMAD(?<mod>(?:\.[SU]16)(?:\.[SU]16))?\.LO2C\s+(?<d>\w+)\s*,\s*(?<a>\w+)\s*,\s*(?<b>c\[$hex\]\[$hex\]|\w+)\s*,\s*(?<c>\w+)\s*;$CommRe/
die "XMAD.LO2C: Destination and first operand cannot be the same register ($+{d})." if $+{d} eq $+{a};
sprintf '
%1$s%2$s%3$sXMAD%9$s %4$s, %5$s, %6$s, %7$s;%8$s
%1$s%2$s%3$sXMAD%9$s.PSL %4$s, %5$s, %6$s.H1, %4$s;',
@+{qw(ctrl space pred d a b c comment mod)}
/egmos;
#TODO: add more XMAD macros
return $file;
}
# convert extra spaces to single spacing to make our re's simplier
sub normalizeSpacing
{
my $inst = shift;
$inst =~ s/\t/ /g;
$inst =~ s/\s{2,}/ /g;
return $inst;
}
# map binary control notation on to easier to work with format.
sub printCtrl
{
my $code = shift;
my $stall = ($code & 0x0000f) >> 0;
my $yield = ($code & 0x00010) >> 4;
my $wrtdb = ($code & 0x000e0) >> 5; # write dependency barier
my $readb = ($code & 0x00700) >> 8; # read dependency barier
my $watdb = ($code & 0x1f800) >> 11; # wait on dependency barier
$yield = $yield ? '-' : 'Y';
$wrtdb = $wrtdb == 7 ? '-' : $wrtdb + 1;
$readb = $readb == 7 ? '-' : $readb + 1;
$watdb = $watdb ? sprintf('%02x', $watdb) : '--';
return sprintf '%s:%s:%s:%s:%x', $watdb, $readb, $wrtdb, $yield, $stall;
}
sub readCtrl
{
my ($ctrl, $context) = @_;
my ($watdb, $readb, $wrtdb, $yield, $stall) = split ':', $ctrl;
$watdb = $watdb eq '--' ? 0 : hex $watdb;
$readb = $readb eq '-' ? 7 : $readb - 1;
$wrtdb = $wrtdb eq '-' ? 7 : $wrtdb - 1;
$yield = $yield eq 'y' || $yield eq 'Y' ? 0 : 1;
$stall = hex $stall;
die sprintf('wait dep out of range(0x00-0x3f): %x at %s', $watdb, $context) if $watdb != ($watdb & 0x3f);
return
$watdb << 11 |
$readb << 8 |
$wrtdb << 5 |
$yield << 4 |
$stall << 0;
}
sub getRegNum
{
my ($regMap, $regName) = @_;
return !exists($regMap->{$regName}) || ref($regMap->{$regName}) ? $regName : $regMap->{$regName};
}
sub getVecRegisters
{
my ($vectors, $capData) = @_;
my $regName = $capData->{r0} or return;
return if $regName eq 'RZ';
if ($capData->{type} eq '.64' || $capData->{i31w4} eq '0x3')
{
if ($regName =~ m'^R(\d+)$')
{
return map "R$_", ($1 .. $1+1);
}
confess "$regName not a 64bit vector register" unless exists $vectors->{$regName};
return @{$vectors->{$regName}}[0,1];
}
if ($capData->{type} eq '.128' || $capData->{i31w4} eq '0xf')
{
if ($regName =~ m'^R(\d+)$')
{
return map "R$_", ($1 .. $1+3);
}
confess "$regName not a 128bit vector register" unless exists($vectors->{$regName}) && @{$vectors->{$regName}} == 4;
return @{$vectors->{$regName}};
}
return $regName;
}
sub getAddrVecRegisters
{
my ($vectors, $capData) = @_;
my $regName = $capData->{r8} or return;
return if $regName eq 'RZ';
if (exists $capData->{E})
{
if ($regName =~ m'^R(\d+)$')
{
return map "R$_", ($1 .. $1+1);
}
print Dumper($vectors) unless exists $vectors->{$regName};
confess "$regName not a 64bit vector register" unless exists $vectors->{$regName};
return @{$vectors->{$regName}}[0,1];
}
return $regName;
}
__END__