forked from envytools/envytools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bftool
executable file
·65 lines (65 loc) · 1.98 KB
/
bftool
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#!/usr/bin/perl -sw
#RE tool, decodes hex into bitfield descriptions {pos,len}
# supports disjoint bitfields
# supports mixed 64bit and 32bit (in envydis's endianness) hex words
# modes: and, or, xor (mask, diff)
#Examples:
# find a diff between two OPs:
# ./bftool -op=xor 8540dc00001c0002 8540dc00001c3c02
# or ./bftool -op=xor 8540dc00001c0002 001c3c02 8540dc00
# or ./bftool -op=xor 001c0002 8540dc00 001c3c02 8540dc00
# > x: U8{0x8540dc00001c0002} U4{0x001c0002,0x8540dc00}
# y: U8{0x8540dc00001c3c02} U4{0x001c3c02,0x8540dc00}
# z: U8{0x0000000000003c00} U4{0x00003c00,0x00000000}
# {pos,len} = {10,4} = {0xa,4}
# find a match against a mask:
# ./bftool -op=and 3fc0000000000000 8540dc00001c0002
# or ./bftool -op=and 3fc0000000000000 001c0002 8540dc00
# ...
# U8{0x0540000000000000} U4{0x00000000,0x05400000}
# 54,1
# 56,1
# 58,1
use Data::Dumper;
no warnings "portable";
my $op = $op || "nop";
sub readhex{
my $A = shift;
my $x = shift(@$A);
return undef if not defined($x);
return hex($x) if(length($x)>8 or scalar(@$A)==0 or length($A->[0])>8);
my $y = shift(@$A);
return hex($x)|hex($y) << 32;
}
my $x = readhex(\@ARGV) || undef;
my $y = readhex(\@ARGV) || undef;
my $z = 0;
if($op eq "nop"){
$z = $x;
}
elsif($op eq "and"){
$z = $x & $y;
}
elsif($op eq "xor"){
$z = $x ^ $y;
}
elsif($op eq "or"){
$z = $x | $y;
}
print sprintf("x: U8{0x%016x} U4{0x%08x,0x%08x}\n",$x,$x&0xFFFFFFFF,($x>>32)&0xFFFFFFFF);
print sprintf("y: U8{0x%016x} U4{0x%08x,0x%08x}\n",$y,$y&0xFFFFFFFF,($y>>32)&0xFFFFFFFF);
print sprintf("z: U8{0x%016x} U4{0x%08x,0x%08x}\n",$z,$z&0xFFFFFFFF,($z>>32)&0xFFFFFFFF);
my $pos=0;
while($z!=0){
while(($z&0x1) eq 0){
$pos++;
$z = $z >> 1;
}
my $len=0;
while(($z&0x1) eq 1){
$len++;
$z = $z >> 1;
}
print sprintf("{pos,len} = {%d,%d} = {0x%x,%d}\n",$pos,$len,$pos,$len);
$pos+=$len;
}