#!/usr/bin/perl -w
# vi: set ts=4:
#
$debug = 0;
$pedantic = 0;
sub get_flags
{
my @list = @insns;
my $exts = {};
my $s;
$debug && print "function: $func\n";
foreach $insn (@list) {
#$debug && print "checking instruction \"$insn\"\n";
$insn =~ m/^(\w+)\s+(.*)$/;
$opcode = $1;
$regs = $2;
if (grep { /^$opcode$/ } @normal_list) {
$debug && print " $opcode: normal\n";
}elsif (grep { /^$opcode$/ } @cmov_list) {
#$exts->{"cmov"} = 1;
$debug && print " $opcode: cmov\n";
}elsif (grep { /^$opcode$/ } @mmxsse_list) {
if (grep { /\%xmm/ } $regs) {
$exts->{"sse2"} = 1;
$debug && print " $opcode: sse2\n";
} else {
$exts->{"mmx"} = 1;
$debug && print " $opcode: mmx\n";
}
}elsif (grep { /^$opcode$/ } @mmx_list) {
$exts->{"mmx"} = 1;
$debug && print " $opcode: mmx\n";
}elsif (grep { /^$opcode$/ } @mmx_ext_list) {
$exts->{"mmxext"} = 1;
$debug && print " $opcode: mmxext\n";
}elsif (grep { /^$opcode$/ } @_3dnow_list) {
$exts->{"3dnow"} = 1;
$debug && print " $opcode: 3dnow\n";
}elsif (grep { /^$opcode$/ } @_3dnow_ext_list) {
$exts->{"3dnowext"} = 1;
$debug && print " $opcode: 3dnowext\n";
}elsif (grep { /^$opcode$/ } @sse_list) {
$exts->{"sse"} = 1;
$debug && print " $opcode: sse\n";
}elsif (grep { /^$opcode$/ } @sse2_list) {
$exts->{"sse2"} = 1;
$debug && print " $opcode: sse2\n";
}else {
print "FIXME:\t\"$opcode\",\n";
$error = 1;
}
}
if (!$pedantic) {
if ($exts->{"sse3"}) {
$exts->{"sse2"} = 1;
}
if ($exts->{"sse2"}) {
$exts->{"sse"} = 1;
$exts->{"mmxext"} = 1;
}
}
$s = join(" ",sort(keys(%$exts)));
$funcs->{"$func"} = $s;
$debug && print " FLAGS: $s\n";
}
sub check
{
foreach $insn (@normal_list) {
if (grep { /^$insn$/ } @mmx_list) {
print "FIXME: $insn is in mmx_list\n";
$error = 1;
} elsif (grep { /^$insn$/ } @mmx_ext_list) {
print "FIXME: $insn is in mmx_ext_list\n";
$error = 1;
} elsif (grep { /^$insn$/ } @_3dnow_list) {
print "FIXME: $insn is in _3dnow_list\n";
$error = 1;
} elsif (grep { /^$insn$/ } @_3dnow_ext_list) {
print "FIXME: $insn is in _3dnow_ext_list\n";
$error = 1;
} elsif (grep { /^$insn$/ } @sse_list) {
print "FIXME: $insn is in sse_list\n";
$error = 1;
} elsif (grep { /^$insn$/ } @sse2_list) {
print "FIXME: $insn is in sse2_list\n";
$error = 1;
}
}
}
# this list is not complete
@normal_list = (
"add",
"addl",
"and",
"andl",
"bswap",
"call",
"cld",
"cltd",
"cmp",
"cmpb",
"cmpl",
"cwtl",
"dec",
"decl",
"fabs",
"fadd",
"faddl",
"faddp",
"fadds",
"fchs",
"fcom",
"fcomp",
"fcompp",
"fdiv",
"fdivr",
"fdivrl",
"fdivrs",
"fdivs",
"fiaddl",
"fimull",
"fild",
"fildl",
"fildll",
"fistp",
"fistpl",
"fistpll",
"fld",
"fld1",
"fldcw",
"fldl",
"flds",
"fldt",
"fldz",
"fmul",
"fmull",
"fmulp",
"fmuls",
"fnstcw",
"fnstsw",
"frndint",
"fsqrt",
"fstl",
"fstp",
"fstpl",
"fstps",
"fstpt",
"fsts",
"fsub",
"fsubl",
"fsubp",
"fsubr",
"fsubrl",
"fsubrp",
"fsubrs",
"fsubs",
"fucom",
"fucomi",
"fucomp",
"fucompp",
"fxch",
"idiv",
"imul",
"imulb",
"inc",
"incl",
"ja",
"jae",
"jb",
"jbe",
"je",
"jg",
"jge",
"jl",
"jle",
"jmp",
"jne",
"jns",
"jp",
"js",
"lea",
"leave",
"mov",
"movb",
"movl",
"movsbl",
"movsbw",
"movswl",
"movsww",
"movw",
"movzbl",
"movzbw",
"movzwl",
"mul",
"mulb",
"neg",
"nop",
"not",
"or",
"pop",
"push",
"pushl",
"rep",
"repz",
"ret",
"rol",
"ror",
"sahf",
"sar",
"sarl",
"setl",
"shl",
"shll",
"shr",
"shrl",
"sub",
"subl",
"test",
"testb",
"testl",
"xchg",
"xor",
);
@cmov_list = (
"cmova",
"cmovae",
"cmovb",
"cmovg",
"cmovge",
"cmovl",
"cmovle",
"cmovbe",
"fcmovbe",
"fcmovnbe",
);
# verified
@mmx_list = (
"emms",
);
# verified
@_3dnow_list = (
"femms",
"pavgusb",
"pf2id",
"pfacc",
"pfadd",
"pfcmpeq",
"pfcmpge",
"pfcmpgt",
"pfmax",
"pfmin",
"pfmul",
"pfrcp",
"pfrcpit1",
"pfrcpit2",
"pfrsqit1",
"pfrsqrt",
"pfsub",
"pfsubr",
"pi2fd",
"pmulhrw",
"prefetch",
"prefetchw"
);
# verified
@_3dnow_ext_list = (
"pf2iw",
"pfnacc",
"pfpnacc",
"pi2fw",
"pswapd"
);
# verified
@mmx_ext_list = (
"maskmovq",
"movntq",
"pavgb",
"pavgw",
"pextrw",
"pinsrw",
"pmaxsw",
"pmaxub",
"pminsw",
"pminub",
"pmovmskb",
"pmulhuw",
"prefetchnta",
"prefetch0",
"prefetch1",
"prefetch2",
"psadbw",
"pshufw",
"sfence"
);
# verified
@sse_list = (
"addps",
"addss",
"andnps",
"andps",
"cmpps",
"cmpss",
"comiss",
"cvtpi2ps",
"cvtps2pi",
"cvtsi2ss",
"cvtss2si",
"cvttps2pi",
"cvttss2si",
"divps",
"divss",
"fxrstor",
"fxsave",
"ldmxcsr",
"maxps",
"maxss",
"minps",
"minss",
"movaps",
"movhlps",
"movhps",
"movlhps",
"movlps",
"movmskps",
"movss",
"movups",
"mulps",
"mulss",
"orps",
"rcpps",
"rcpss",
"rsqrtps",
"rsqrtss",
"shufps",
"sqrtps",
"sqrtss",
"stmxcsr",
"subps",
"subss",
"ucomiss",
"unpckhps",
"unpcklps",
"xorps"
);
@mmxsse_list = (
"movd",
"movq",
"packssdw",
"packsswb",
"packuswb",
"paddb",
"paddd",
"paddsb",
"paddsw",
"paddusb",
"paddusw",
"paddw",
"pand",
"pandn",
"pcmpeqb",
"pcmpeqd",
"pcmpeqw",
"pcmpgtb",
"pcmpgtd",
"pcmpgtw",
"pmaddwd",
"pmulhw",
"pmullw",
"pmulhuw",
"por",
"pslld",
"psllq",
"psllw",
"psrad",
"psraw",
"psrld",
"psrlq",
"psrlw",
"psubb",
"psubd",
"psubsb",
"psubsw",
"psubusb",
"psubusw",
"psubw",
"punpckhbw",
"punpckhdq",
"punpckhwd",
"punpcklbw",
"punpckldq",
"punpcklwd",
"pxor",
);
# verified
@sse2_list = (
"addpd",
"addsd",
"andnpd",
"andpd",
"cmppd",
"cmpsd",
"comisd",
"cvtpi2pd",
"cvtpd2pi",
"cvtsi2sd",
"cvtsd2si",
"cvttpd2pi",
"cvttsd2si",
"cvtpd2ps",
"cvtps2pd",
"cvtsd2ss",
"cvtss2sd",
"cvtps2dq",
"cvttpd2dq",
"cvtdq2pd",
"cvtps2dq",
"cvttps2dq",
"cvtdq2ps",
"divpd",
"divsd",
"maxpd",
"maxsd",
"minpd",
"minsd",
"movapd",
"movhpd",
"movlpd",
"movmskpd",
"movsd",
"movupd",
"mulpd",
"mulsd",
"orpd",
"shufpd",
"sqrtpd",
"sqrtsd",
"subpd",
"subsd",
"ucomisd",
"unpckhpd",
"unpcklpd",
"xorpd",
#"movd",
"movdqa",
"movdqu",
"movq2dq",
"movdq2q",
#"movq",
#"packssdw",
#"packsswb",
#"packuswb",
"paddq",
"padd",
"padds",
"paddus",
#"pand",
#"pandn",
"pavgb",
"pavgw",
"pcmpeq",
"pcmpgt",
"pextrw",
"pinsrw",
#"pmaddwd",
"pmaxsw",
"pmaxub",
"pminsw",
"pminub",
"pmovmskb",
"pmulhuw",
#"pmulhw",
#"pmullw",
"pmuludq",
#"por",
"psadbw",
"pshuflw",
"pshufhw",
"pshufd",
"pslldq",
"psll",
"psra",
"psrldq",
"psrl",
"psubq",
"psub",
"psubs",
"psubus",
"punpckh",
"punpckhqdq",
"punpckl",
"punpcklqdq",
#"pxor",
"maskmovdqu",
"movntpd",
"movntdq",
"movnti",
"pause",
"lfence",
"mfence",
);
#@clflush_list = (
# "clflush",
#);
$funcs = {};
$ARGV=shift @ARGV;
@output=`objdump -j .text -dr $ARGV`;
check();
$error = 0;
@insns = ();
while($_=shift @output){
chomp;
if(m/^0[0-9a-fA-F]+\s<[\.\w@]+>:$/){
$f = $_;
$f =~ s/^0[0-9a-fA-F]+\s<([\.\w]+)>:$/$1/;
if (@insns) {
get_flags ();
}
$func = $f;
@insns = ();
$debug && print "$func:\n";
} elsif(m/^[\s0-9a-f]+:\s[\s0-9a-f]{20}\s+([\w]+\s.*)$/){
push @insns, $1;
#print " $1\n";
} elsif(m/^[\s0-9a-f]+:\s[\s0-9a-f]{2,20}\s$/){
# ignore
} elsif (m/^$/) {
} elsif (m/^Disassembly of section/) {
} elsif (m/\sfile format\s/) {
} else {
print "FIXME: $_\n";
$error = 1;
}
}
@source = `./list-impls`;
while ($_ = shift @source) {
chomp;
if (m/^([\w\.]+):\s*([\w\s*]*)/) {
$func = $1;
$flags = $2;
$xflags = $funcs->{$func};
if (1) {
if ($flags ne $xflags) {
print "$func: \"$flags\" should be \"$xflags\"\n";
}
} else {
print "FIXME: function \"$func\" has no disassembly\n";
$error = 1;
}
} else {
print "FIXME: bad match: $_\n";
}
}
exit $error;
syntax highlighted by Code2HTML, v. 0.9.1