line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package # Hide from CPAN, since this module is not terribly re-usable (yet) |
2
|
|
|
|
|
|
|
CPU::x86_64::InstructionWriter::_int32; |
3
|
17
|
|
|
17
|
|
12397
|
use strict; |
|
17
|
|
|
|
|
43
|
|
|
17
|
|
|
|
|
502
|
|
4
|
17
|
|
|
17
|
|
90
|
use warnings; |
|
17
|
|
|
|
|
48
|
|
|
17
|
|
|
|
|
454
|
|
5
|
17
|
|
|
17
|
|
85
|
use Exporter 'import'; |
|
17
|
|
|
|
|
36
|
|
|
17
|
|
|
|
|
9653
|
|
6
|
|
|
|
|
|
|
our @EXPORT_OK = qw( pack int64 ); |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
# ABSTRACT: Handle 64-bit integer operations on 32-bit perl |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
# This wrapper only handles the specific use ELF::Writer makes of the pack |
11
|
|
|
|
|
|
|
# function which are not supported on all perls: |
12
|
|
|
|
|
|
|
# - 5.8 perl does not support ">" "<" modifiers. |
13
|
|
|
|
|
|
|
# - Perl compiled without 64-bit integers doesn't support "Q". |
14
|
|
|
|
|
|
|
# It would be nice if there were a standalone module that enhances 'pack' on |
15
|
|
|
|
|
|
|
# those old perls. |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
# On 5.8, a 64-bit big-endian system needs to byte-swap 'Q<' fields |
18
|
|
|
|
|
|
|
sub _pack_wrapper_64_5_8_be { |
19
|
0
|
|
|
0
|
|
0
|
my $fmt= shift; |
20
|
0
|
|
|
|
|
0
|
my $new_fmt= ''; |
21
|
0
|
|
|
|
|
0
|
my @new_args; |
22
|
0
|
|
|
|
|
0
|
for (split / +/, $fmt) { # ELF::Writer uses spaces between all fields |
23
|
0
|
0
|
|
|
|
0
|
if ($_ eq 'Q<') { |
|
|
0
|
|
|
|
|
|
24
|
|
|
|
|
|
|
# Convert 64-bit integer into two 32-bit little-endian arguments |
25
|
0
|
|
|
|
|
0
|
$new_fmt .= 'VV'; |
26
|
0
|
|
|
|
|
0
|
my $qw= shift; |
27
|
0
|
|
|
|
|
0
|
push @new_args, ($qw & '4294967295'), ($qw >> 32); |
28
|
|
|
|
|
|
|
} elsif ($_ eq 'Q>') { |
29
|
0
|
|
|
|
|
0
|
$new_fmt .= 'Q'; |
30
|
0
|
|
|
|
|
0
|
push @new_args, shift; |
31
|
|
|
|
|
|
|
} else { |
32
|
0
|
|
|
|
|
0
|
$new_fmt .= $_; |
33
|
0
|
|
|
|
|
0
|
push @new_args, shift; |
34
|
|
|
|
|
|
|
} |
35
|
|
|
|
|
|
|
} |
36
|
0
|
|
|
|
|
0
|
return pack $new_fmt, @new_args; |
37
|
|
|
|
|
|
|
} |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
# On 5.8, a 64-bit little-endian system needs to byte-swap 'Q>' fields |
40
|
|
|
|
|
|
|
sub _pack_wrapper_64_5_8_le { |
41
|
0
|
|
|
0
|
|
0
|
my $fmt= shift; |
42
|
0
|
|
|
|
|
0
|
my $new_fmt= ''; |
43
|
0
|
|
|
|
|
0
|
my @new_args; |
44
|
0
|
|
|
|
|
0
|
for (split / +/, $fmt) { |
45
|
0
|
0
|
|
|
|
0
|
if ($_ eq 'Q>') { |
|
|
0
|
|
|
|
|
|
46
|
|
|
|
|
|
|
# Convert 64-bit integer into two 32-bit big-endian arguments |
47
|
0
|
|
|
|
|
0
|
$new_fmt .= 'NN'; |
48
|
0
|
|
|
|
|
0
|
my $qw= shift; |
49
|
0
|
|
|
|
|
0
|
push @new_args, ($qw >> 32), ($qw & '4294967295'); |
50
|
|
|
|
|
|
|
} elsif ($_ eq 'Q<') { |
51
|
0
|
|
|
|
|
0
|
$new_fmt .= 'Q'; |
52
|
0
|
|
|
|
|
0
|
push @new_args, shift; |
53
|
|
|
|
|
|
|
} else { |
54
|
0
|
|
|
|
|
0
|
$new_fmt .= $_; |
55
|
0
|
|
|
|
|
0
|
push @new_args, shift; |
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
} |
58
|
0
|
|
|
|
|
0
|
return pack $new_fmt, @new_args; |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# On perl without 64-bit support, replace all 'Q' with 32-bit operations |
62
|
|
|
|
|
|
|
sub _pack_wrapper_32 { |
63
|
0
|
|
|
0
|
|
0
|
my $fmt= shift; |
64
|
0
|
|
|
|
|
0
|
my $new_fmt= ''; |
65
|
0
|
|
|
|
|
0
|
my @new_args; |
66
|
0
|
|
|
|
|
0
|
my $mask32= Math::BigInt->new('4294967295'); |
67
|
0
|
|
|
|
|
0
|
for (split / *(?=[A-Za-z])/, $fmt) { |
68
|
0
|
0
|
|
|
|
0
|
if ($_ eq 'Q>') { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
69
|
|
|
|
|
|
|
# Convert a 64-bit integer into two 32-bit big-endian arguments |
70
|
0
|
|
|
|
|
0
|
$new_fmt .= 'NN'; |
71
|
0
|
|
|
|
|
0
|
my $qw= Math::BigInt->new(shift); |
72
|
0
|
|
|
|
|
0
|
push @new_args, ($qw >> 32)->numify(), ($qw & $mask32)->numify(); |
73
|
|
|
|
|
|
|
} elsif ($_ eq 'Q<') { |
74
|
|
|
|
|
|
|
# Convert 64-bit integer into two 32-bit little-endian arguments |
75
|
0
|
|
|
|
|
0
|
$new_fmt .= 'VV'; |
76
|
0
|
|
|
|
|
0
|
my $qw= Math::BigInt->new(shift); |
77
|
0
|
|
|
|
|
0
|
push @new_args, ($qw & $mask32)->numify(), ($qw >> 32)->numify(); |
78
|
|
|
|
|
|
|
} elsif ($_ eq 'Q') { |
79
|
0
|
|
|
|
|
0
|
Carp::croak("Ambiguous 64-bit value"); |
80
|
|
|
|
|
|
|
} else { |
81
|
0
|
|
|
|
|
0
|
$new_fmt .= $_; |
82
|
0
|
|
|
|
|
0
|
push @new_args, shift; |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
} |
85
|
0
|
|
|
|
|
0
|
return pack $new_fmt, @new_args; |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
sub _int64_native { |
89
|
17
|
|
|
17
|
|
143
|
no warnings 'portable'; |
|
17
|
|
|
|
|
65
|
|
|
17
|
|
|
|
|
2402
|
|
90
|
46
|
100
|
|
46
|
|
47156
|
$_[0] =~ /^(-?)0x(.*)/? hex($2)*($1? -1 : 1) : 0+$_[0] |
|
|
50
|
|
|
|
|
|
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
sub _int64_bigint { |
93
|
0
|
|
|
0
|
|
|
Math::BigInt->new($_[0]) |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
|
96
|
17
|
|
|
17
|
|
140
|
no strict 'refs'; |
|
17
|
|
|
|
|
37
|
|
|
17
|
|
|
|
|
4448
|
|
97
|
|
|
|
|
|
|
# Do we have full support? |
98
|
|
|
|
|
|
|
if (eval { pack('Q<', 1) }) { |
99
|
|
|
|
|
|
|
*pack= CORE->can('pack')? \*CORE::pack : sub { pack(@_) }; |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
# Do we have 64bit? |
102
|
|
|
|
|
|
|
elsif (eval { pack('Q', 1) }) { |
103
|
|
|
|
|
|
|
# choose correct endian |
104
|
|
|
|
|
|
|
*pack= (pack('Q', 1) eq "\x01\0\0\0\0\0\0\0") |
105
|
|
|
|
|
|
|
? \&_pack_wrapper_64_5_8_le |
106
|
|
|
|
|
|
|
: \&_pack_wrapper_64_5_8_be; |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
# else need BigInteger implementation |
109
|
|
|
|
|
|
|
else { |
110
|
|
|
|
|
|
|
require Math::BigInt; |
111
|
|
|
|
|
|
|
*pack= \&_pack_wrapper_32; |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
# Can scalars hold 64-bit ints natively? |
115
|
|
|
|
|
|
|
if ((0x7FFFFFFE << 31) > 0 && (0x7FFFFFFE << 63) == 0) { # 64-bit scalar support |
116
|
|
|
|
|
|
|
*int64= \&_int64_native; |
117
|
|
|
|
|
|
|
} else { |
118
|
|
|
|
|
|
|
*int64= \&_int64_bigint; |
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
__END__ |