* first draft to support the popcnt instruction, works so far for x86 with a real popcnt instruction

git-svn-id: trunk@22289 -
This commit is contained in:
florian 2012-09-02 20:59:39 +00:00
parent 728f53daa6
commit b782918434
9 changed files with 120 additions and 7 deletions

View File

@ -86,6 +86,7 @@ const
in_default_x = 76;
in_box_x = 77; { managed platforms: wrap in class instance }
in_unbox_x_y = 78; { manage platforms: extract from class instance }
in_popcnt_x = 79;
{ Internal constant functions }
in_const_sqr = 100;

View File

@ -58,6 +58,7 @@ interface
procedure second_new; virtual;
procedure second_setlength; virtual; abstract;
procedure second_box; virtual; abstract;
procedure second_popcnt; virtual;
end;
implementation
@ -177,6 +178,8 @@ implementation
second_setlength;
in_box_x:
second_box;
in_popcnt_x:
second_popcnt;
else internalerror(9);
end;
end;
@ -734,6 +737,12 @@ implementation
end;
procedure tcginlinenode.second_popcnt;
begin
internalerror(2012082601);
end;
begin
cinlinenode:=tcginlinenode;
end.
end. s

View File

@ -3046,6 +3046,14 @@ implementation
resultdef:=u32inttype
end;
in_popcnt_x:
begin
set_varstate(left,vs_read,[vsf_must_be_valid]);
if not is_integer(left.resultdef) then
CGMessage1(type_e_integer_expr_expected,left.resultdef.typename);
resultdef:=left.resultdef;
end;
in_objc_selector_x:
begin
result:=cobjcselectornode.create(left);
@ -3467,7 +3475,8 @@ implementation
in_sar_x,
in_sar_x_y,
in_bsf_x,
in_bsr_x:
in_bsr_x,
in_popcnt_x:
expectloc:=LOC_REGISTER;
in_new_x:
result:=first_new;

View File

@ -2781,6 +2781,11 @@ begin
def_system_macro('FPC_HAS_INTERNAL_BSX');
{$endif}
{ inline bsf/bsr implementation }
{$if defined(x86) or defined(x86_64)}
def_system_macro('FPC_HAS_INTERNAL_POPCNT');
{$endif}
{$ifdef powerpc64}
def_system_macro('FPC_HAS_LWSYNC');
{$endif}

View File

@ -60,6 +60,7 @@ interface
procedure second_prefetch;override;
procedure second_abs_long;override;
procedure second_popcnt;override;
private
procedure load_fpu_location;
end;
@ -542,4 +543,27 @@ implementation
end;
procedure tx86inlinenode.second_popcnt;
var
opsize: tcgsize;
begin
secondpass(left);
opsize:=tcgsize2unsigned[left.location.size];
{ no 8 Bit popcont }
if opsize=OS_8 then
opsize:=OS_16;
if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER,LOC_REFERENCE,LOC_CREFERENCE]) or
(left.location.size<>opsize) then
hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,hlcg.tcgsize2orddef(opsize),true);
location_reset(location,LOC_REGISTER,opsize);
location.register:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_POPCNT,TCGSize2OpSize[opsize],left.location.register,location.register))
else
current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_POPCNT,TCGSize2OpSize[opsize],left.location.reference,location.register));
end;
end.

View File

@ -2444,3 +2444,13 @@ function BsrQWord(Const AValue : QWord): cardinal;
end;
{$endif}
{$endif}
{$ifndef FPC_HAS_INTERNAL_POPCNT_QWORD}
{$ifndef FPC_SYSTEM_HAS_POPCNT_QWORD}
function PopCnt(Const AValue : QWord): QWord;
begin
Result:=PopCnt(lo(AValue))+PopCnt(hi(AValue))
end;
{$endif}
{$endif}

View File

@ -87,6 +87,7 @@ const
fpc_in_default_x = 76;
fpc_in_box_x = 77; { managed platforms: wrap in class instance }
fpc_in_unbox_x_y = 78; { manage platforms: extract from class instance }
fpc_in_popcnt_x = 79;
{ Internal constant functions }
fpc_in_const_sqr = 100;

View File

@ -860,6 +860,42 @@ function BsfQWord(Const AValue : QWord): cardinal;{$ifdef SYSTEMINLINE}inline;{$
function BsrQWord(Const AValue : QWord): cardinal;{$ifdef SYSTEMINLINE}inline;{$endif}
{$endif FPC_HAS_INTERNAL_BSF_QWORD}
{$ifdef FPC_HAS_INTERNAL_POPCNT}
{$if defined(cpui386) or defined(cpux86_64)}
{$define FPC_HAS_INTERNAL_POPCNT_BYTE}
{$define FPC_HAS_INTERNAL_POPCNT_WORD}
{$define FPC_HAS_INTERNAL_POPCNT_DWORD}
{$endif}
{$if defined(cpux86_64)}
{$define FPC_HAS_INTERNAL_POPCNT_QWORD}
{$endif}
{$endif}
{$ifdef FPC_HAS_INTERNAL_POPCNT_BYTE}
function PopCnt(Const AValue: Byte): Byte;[internproc:fpc_in_popcnt_x];
{$else}
function PopCnt(Const AValue: Byte): Byte;{$ifdef SYSTEMINLINE}inline;{$endif}
{$endif FPC_HAS_INTERNAL_POPCNT_BYTE}
{$ifdef FPC_HAS_INTERNAL_POPCNT_WORD}
function PopCnt(Const AValue: Word): Word;[internproc:fpc_in_popcnt_x];
{$else}
function PopCnt(Const AValue: Word): Word;{$ifdef SYSTEMINLINE}inline;{$endif}
{$endif FPC_HAS_INTERNAL_POPCNT_WORD}
{$ifdef FPC_HAS_INTERNAL_POPCNT_DWORD}
function PopCnt(Const AValue : DWord): DWord;[internproc:fpc_in_popcnt_x];
{$else}
function PopCnt(Const AValue : DWord): DWord;
{$endif FPC_HAS_INTERNAL_POPCNT_DWORD}
{$ifdef FPC_HAS_INTERNAL_POPCNT_QWORD}
function PopCnt(Const AValue : QWord): QWord;[internproc:fpc_in_popcnt_x];
{$else}
function PopCnt(Const AValue : QWord): QWord;
{$endif FPC_HAS_INTERNAL_POPCNT_QWORD}
{$ifndef FPUNONE}
{ float math routines }
{$I mathh.inc}

View File

@ -5,7 +5,7 @@ var
i : integer;
d : dword;
li : longint;
q : qword
q : qword;
i64 : int64;
begin
@ -23,6 +23,9 @@ begin
if popcnt(b)<>1 then
halt(1);
writeln('popcnt(<byte>); passed');
{
si:=$54;
if popcnt(si)<>3 then
halt(1);
@ -34,6 +37,7 @@ begin
si:=$20;
if popcnt(si)<>1 then
halt(1);
}
{ 16 Bit }
@ -49,6 +53,9 @@ begin
if popcnt(w)<>2 then
halt(1);
writeln('popcnt(<word>); passed');
{
i:=$5454;
if popcnt(i)<>6 then
halt(1);
@ -60,11 +67,12 @@ begin
i:=$2020;
if popcnt(i)<>2 then
halt(1);
}
{ 32 Bit }
d:=$a4a4a4a4;
if popcnt(w)<>12 then
if popcnt(d)<>12 then
halt(1);
d:=$0;
@ -75,6 +83,9 @@ begin
if popcnt(d)<>4 then
halt(1);
writeln('popcnt(<dword>); passed');
{
li:=$54545454;
if popcnt(li)<>12 then
halt(1);
@ -86,11 +97,11 @@ begin
li:=$20402080;
if popcnt(li)<>4 then
halt(1);
}
{ 64 Bit }
q:=$a4a4a4a4a4a4a4a4;
q:=qword($a4a4a4a4a4a4a4a4);
if popcnt(q)<>24 then
halt(1);
@ -102,6 +113,13 @@ begin
if popcnt(q)<>8 then
halt(1);
q:=qword($a4a4a4a400000000);
if popcnt(q)<>12 then
halt(1);
writeln('popcnt(<qword>); passed');
{
i64:=$5454545454545454;
if popcnt(i64)<>24 then
halt(1);
@ -113,7 +131,7 @@ begin
i64:=$2040208020402080;
if popcnt(li)<>8 then
halt(1);
}
writeln('ok');
end.