+ internal bsr/bsf support for ppc32 and ppc64

git-svn-id: trunk@30152 -
This commit is contained in:
Jonas Maebe 2015-03-09 16:48:34 +00:00
parent 00642288b8
commit 6a70c84258
3 changed files with 55 additions and 5 deletions

View File

@ -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}

View File

@ -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;

View File

@ -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}