mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-19 23:39:31 +02:00
+ is_shifter_const() function to determine whether a constant can be encoded
as an immediate operand for a logical operation git-svn-id: trunk@29850 -
This commit is contained in:
parent
d23299af1e
commit
e6d7c6a62a
@ -320,6 +320,9 @@ unit cpubase;
|
||||
|
||||
function dwarf_reg(r:tregister):shortint;
|
||||
|
||||
function is_shifter_const(d: aint; size: tcgsize): boolean;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
@ -481,4 +484,112 @@ unit cpubase;
|
||||
end;
|
||||
|
||||
|
||||
function is_shifter_const(d: aint; size: tcgsize): boolean;
|
||||
var
|
||||
pattern, checkpattern: qword;
|
||||
patternlen, maxbits, replicatedlen: longint;
|
||||
rightmostone, rightmostzero, checkbit, secondrightmostbit: longint;
|
||||
begin
|
||||
result:=false;
|
||||
{ patterns with all bits 0 or 1 cannot be represented this way }
|
||||
if (d=0) then
|
||||
exit;
|
||||
case size of
|
||||
OS_64,
|
||||
OS_S64:
|
||||
begin
|
||||
if d=-1 then
|
||||
exit;
|
||||
maxbits:=64;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if longint(d)=-1 then
|
||||
exit;
|
||||
{ we'll generate a 32 bit pattern -> ignore upper sign bits in
|
||||
case of negative longint value }
|
||||
d:=cardinal(d);
|
||||
maxbits:=32;
|
||||
end;
|
||||
end;
|
||||
{ "The Logical (immediate) instructions accept a bitmask immediate value
|
||||
that is a 32-bit pattern or a 64-bit pattern viewed as a vector of
|
||||
identical elements of size e = 2, 4, 8, 16, 32 or, 64 bits. Each
|
||||
element contains the same sub-pattern, that is a single run of
|
||||
1 to (e - 1) nonzero bits from bit 0 followed by zero bits, then
|
||||
rotated by 0 to (e - 1) bits." (ARMv8 ARM)
|
||||
|
||||
Rather than generating all possible patterns and checking whether they
|
||||
match our constant, we check whether the lowest 2/4/8/... bits are
|
||||
a valid pattern, and if so whether the constant consists of a
|
||||
replication of this pattern. Such a valid pattern has the form of
|
||||
either (regexp notation)
|
||||
* 1+0+1*
|
||||
* 0+1+0* }
|
||||
patternlen:=2;
|
||||
while patternlen<=maxbits do
|
||||
begin
|
||||
{ try lowest <patternlen> bits of d as pattern }
|
||||
if patternlen<>64 then
|
||||
pattern:=qword(d) and ((qword(1) shl patternlen)-1)
|
||||
else
|
||||
pattern:=qword(d);
|
||||
{ valid pattern? If it contains too many 1<->0 transitions, larger
|
||||
parts of d cannot be a valid pattern either }
|
||||
rightmostone:=BsfQWord(pattern);
|
||||
rightmostzero:=BsfQWord(not(pattern));
|
||||
{ pattern all ones or zeroes -> not a valid pattern (but larger ones
|
||||
can still be valid, since we have too few transitions) }
|
||||
if (rightmostone<patternlen) and
|
||||
(rightmostzero<patternlen) then
|
||||
begin
|
||||
if rightmostone>rightmostzero then
|
||||
begin
|
||||
{ we have .*1*0* -> check next zero position by shifting
|
||||
out the existing zeroes (shr rightmostone), inverting and
|
||||
then again looking for the rightmost one position }
|
||||
checkpattern:=not(pattern);
|
||||
checkbit:=rightmostone;
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ same as above, but for .*0*1* }
|
||||
checkpattern:=pattern;
|
||||
checkbit:=rightmostzero;
|
||||
end;
|
||||
secondrightmostbit:=BsfQWord(checkpattern shr checkbit)+checkbit;
|
||||
{ if this position is >= patternlen -> ok (1 transition),
|
||||
otherwise we now have 2 transitions and have to check for a
|
||||
third (if there is one, abort)
|
||||
|
||||
bsf returns 255 if no 1 bit is found, so in that case it's
|
||||
also ok
|
||||
}
|
||||
if secondrightmostbit<patternlen then
|
||||
begin
|
||||
secondrightmostbit:=BsfQWord(not(checkpattern) shr secondrightmostbit)+secondrightmostbit;
|
||||
if secondrightmostbit<patternlen then
|
||||
exit;
|
||||
end;
|
||||
{ ok, this is a valid pattern, now does d consist of a
|
||||
repetition of this pattern? }
|
||||
replicatedlen:=patternlen;
|
||||
checkpattern:=pattern;
|
||||
while replicatedlen<maxbits do
|
||||
begin
|
||||
{ douplicate current pattern }
|
||||
checkpattern:=checkpattern or (checkpattern shl replicatedlen);
|
||||
replicatedlen:=replicatedlen*2;
|
||||
end;
|
||||
if qword(d)=checkpattern then
|
||||
begin
|
||||
{ yes! }
|
||||
result:=true;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
patternlen:=patternlen*2;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user