mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-20 19:09:23 +02:00
+ internal bsr/bsf support for ppc32 and ppc64
git-svn-id: trunk@30152 -
This commit is contained in:
parent
00642288b8
commit
6a70c84258
@ -3850,7 +3850,7 @@ if (target_info.abi = abi_eabihf) then
|
||||
{$endif ARM}
|
||||
|
||||
{ inline bsf/bsr implementation }
|
||||
{$if defined(i386) or defined(x86_64) or defined(aarch64)}
|
||||
{$if defined(i386) or defined(x86_64) or defined(aarch64) or defined(powerpc) or defined(powerpc64)}
|
||||
def_system_macro('FPC_HAS_INTERNAL_BSF');
|
||||
def_system_macro('FPC_HAS_INTERNAL_BSR');
|
||||
{$endif}
|
||||
|
@ -35,6 +35,8 @@ unit cgppc;
|
||||
tcgppcgen = class(tcg)
|
||||
procedure a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara); override;
|
||||
|
||||
procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: tcgsize; src, dst: TRegister); override;
|
||||
|
||||
procedure a_call_reg(list : TAsmList;reg: tregister); override;
|
||||
|
||||
{ stores the contents of register reg to the memory location described by
|
||||
@ -216,6 +218,54 @@ unit cgppc;
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgppcgen.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: tcgsize; src, dst: TRegister);
|
||||
var
|
||||
tmpreg: tregister;
|
||||
cntlzop: tasmop;
|
||||
bitsizem1: longint;
|
||||
begin
|
||||
{ we only have a cntlz(w|d) instruction, which corresponds to bsr(x)
|
||||
(well, regsize_in_bits - bsr(x), as x86 numbers bits in reverse).
|
||||
Fortunately, bsf(x) can be calculated easily based on that, see
|
||||
"Figure 5-13. Number of Powers of 2 Code Sequence" in the PowerPC
|
||||
Compiler Writer's Guide
|
||||
}
|
||||
if srcsize in [OS_64,OS_S64] then
|
||||
begin
|
||||
{$ifdef powerpc64}
|
||||
cntlzop:=A_CNTLZD;
|
||||
{$else}
|
||||
internalerror(2015022601);
|
||||
{$endif}
|
||||
bitsizem1:=63;
|
||||
end
|
||||
else
|
||||
begin
|
||||
cntlzop:=A_CNTLZW;
|
||||
bitsizem1:=31;
|
||||
end;
|
||||
if not reverse then
|
||||
begin
|
||||
{ cntlzw(src and -src) }
|
||||
tmpreg:=getintregister(list,srcsize);
|
||||
{ don't use a_op_reg_reg, as this will adjust the result
|
||||
after the neg in case of a non-32/64 bit operation, which
|
||||
is not necessary since we're only using it as an
|
||||
AND-mask }
|
||||
list.concat(taicpu.op_reg_reg(A_NEG,tmpreg,src));
|
||||
a_op_reg_reg(list,OP_AND,srcsize,src,tmpreg);
|
||||
end
|
||||
else
|
||||
tmpreg:=src;
|
||||
{ count leading zeroes }
|
||||
list.concat(taicpu.op_reg_reg(cntlzop,dst,tmpreg));
|
||||
{ (bitsize-1) - cntlz (which is 32/64 in case src was 0) }
|
||||
list.concat(taicpu.op_reg_reg_const(A_SUBFIC,dst,dst,bitsizem1));
|
||||
{ set to 255 is source was 0 }
|
||||
a_op_const_reg(list,OP_AND,dstsize,255,dst);
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgppcgen.g_maybe_got_init(list: TAsmList);
|
||||
var
|
||||
instr: taicpu;
|
||||
|
@ -987,23 +987,23 @@ function fpc_SarInt64(Const AValue : Int64;const Shift : Byte): Int64;compilerpr
|
||||
{$endif FPC_HAS_INTERNAL_SAR_QWORD}
|
||||
|
||||
{$ifdef FPC_HAS_INTERNAL_BSF}
|
||||
{$if defined(cpui386) or defined(cpux86_64) or defined(cpuarm) or defined(cpuaarch64)}
|
||||
{$if defined(cpui386) or defined(cpux86_64) or defined(cpuarm) or defined(cpuaarch64) or defined(cpupowerpc32) or defined(cpupowerpc64)}
|
||||
{$define FPC_HAS_INTERNAL_BSF_BYTE}
|
||||
{$define FPC_HAS_INTERNAL_BSF_WORD}
|
||||
{$define FPC_HAS_INTERNAL_BSF_DWORD}
|
||||
{$endif}
|
||||
{$if defined(cpux86_64) or defined(cpuaarch64)}
|
||||
{$if defined(cpux86_64) or defined(cpuaarch64) or defined(cpupowerpc64)}
|
||||
{$define FPC_HAS_INTERNAL_BSF_QWORD}
|
||||
{$endif}
|
||||
{$endif}
|
||||
|
||||
{$ifdef FPC_HAS_INTERNAL_BSR}
|
||||
{$if defined(cpui386) or defined(cpux86_64) or defined(cpuarm) or defined(cpuaarch64)}
|
||||
{$if defined(cpui386) or defined(cpux86_64) or defined(cpuarm) or defined(cpuaarch64) or defined(cpupowerpc32) or defined(cpupowerpc64)}
|
||||
{$define FPC_HAS_INTERNAL_BSR_BYTE}
|
||||
{$define FPC_HAS_INTERNAL_BSR_WORD}
|
||||
{$define FPC_HAS_INTERNAL_BSR_DWORD}
|
||||
{$endif}
|
||||
{$if defined(cpux86_64) or defined(cpuaarch64)}
|
||||
{$if defined(cpux86_64) or defined(cpuaarch64) or defined(cpupowerpc64)}
|
||||
{$define FPC_HAS_INTERNAL_BSR_QWORD}
|
||||
{$endif}
|
||||
{$endif}
|
||||
|
Loading…
Reference in New Issue
Block a user