* don't convert the fpu parameters size from tcgsize -> int -> float_tcgsize

if not required, to avoid translating OS_C64 into OS_F64 (fix for x86
    test failures after r45205)

git-svn-id: trunk@45221 -
(cherry picked from commit 3f6ad30b69)
This commit is contained in:
Jonas Maebe 2020-05-02 13:17:21 +00:00
parent 8a31764a7b
commit 1c3fc6e2df
2 changed files with 171 additions and 133 deletions

View File

@ -433,10 +433,12 @@ interface
the source } the source }
procedure removeshuffles(var shuffle : tmmshuffle); procedure removeshuffles(var shuffle : tmmshuffle);
function is_float_cgsize(size: tcgsize): boolean;{$ifdef USEINLINE}inline;{$endif}
implementation implementation
uses uses
verbose; cutils,verbose;
{****************************************************************************** {******************************************************************************
tsuperregisterworklist tsuperregisterworklist
@ -815,6 +817,25 @@ implementation
end; end;
function is_float_cgsize(size: tcgsize): boolean;{$ifdef USEINLINE}inline;{$endif}
begin
result:=size in [OS_F32..OS_F128];
end;
procedure Initmms(var p : pmmshuffle;len : ShortInt);
var
i : Integer;
begin
Getmem(p,sizeof(tmmshuffle)+(max(len,0)-1)*2);
p^.len:=len;
for i:=1 to len do
{$push}
{$R-}
p^.shuffles[i]:=i;
{$pop}
end;
initialization initialization
new(mms_movescalar); new(mms_movescalar);
mms_movescalar^.len:=0; mms_movescalar^.len:=0;

View File

@ -1029,144 +1029,151 @@ implementation
location: pcgparalocation; location: pcgparalocation;
orgsizeleft, orgsizeleft,
sizeleft: tcgint; sizeleft: tcgint;
usesize: tcgsize;
reghasvalue: boolean; reghasvalue: boolean;
begin begin
location:=cgpara.location; location:=cgpara.location;
tmpref:=r; tmpref:=r;
sizeleft:=cgpara.intsize; sizeleft:=cgpara.intsize;
while assigned(location) do repeat
begin paramanager.allocparaloc(list,location);
paramanager.allocparaloc(list,location); case location^.loc of
case location^.loc of LOC_REGISTER,LOC_CREGISTER:
LOC_REGISTER,LOC_CREGISTER: begin
begin { Parameter locations are often allocated in multiples of
{ Parameter locations are often allocated in multiples of entire registers. If a parameter only occupies a part of
entire registers. If a parameter only occupies a part of such a register (e.g. a 16 bit int on a 32 bit
such a register (e.g. a 16 bit int on a 32 bit architecture), the size of this parameter can only be
architecture), the size of this parameter can only be determined by looking at the "size" parameter of this
determined by looking at the "size" parameter of this method -> if the size parameter is <= sizeof(aint), then
method -> if the size parameter is <= sizeof(aint), then we check that there is only one parameter location and
we check that there is only one parameter location and then use this "size" to load the value into the parameter
then use this "size" to load the value into the parameter location }
location } if (size<>OS_NO) and
if (size<>OS_NO) and (tcgsize2size[size]<=sizeof(aint)) then
(tcgsize2size[size]<=sizeof(aint)) then begin
begin cgpara.check_simple_location;
cgpara.check_simple_location; a_load_ref_reg(list,size,location^.size,tmpref,location^.register);
a_load_ref_reg(list,size,location^.size,tmpref,location^.register); if location^.shiftval<0 then
if location^.shiftval<0 then a_op_const_reg(list,OP_SHL,location^.size,-location^.shiftval,location^.register);
a_op_const_reg(list,OP_SHL,location^.size,-location^.shiftval,location^.register); end
end { there's a lot more data left, and the current paraloc's
{ there's a lot more data left, and the current paraloc's register is entirely filled with part of that data }
register is entirely filled with part of that data } else if (sizeleft>sizeof(aint)) then
else if (sizeleft>sizeof(aint)) then begin
begin a_load_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
a_load_ref_reg(list,location^.size,location^.size,tmpref,location^.register); end
end { we're at the end of the data, and it can be loaded into
{ we're at the end of the data, and it can be loaded into the current location's register with a single regular
the current location's register with a single regular load }
load } else if sizeleft in [1,2,4,8] then
else if sizeleft in [1,2,4,8] then begin
begin a_load_ref_reg(list,int_cgsize(sizeleft),location^.size,tmpref,location^.register);
a_load_ref_reg(list,int_cgsize(sizeleft),location^.size,tmpref,location^.register); if location^.shiftval<0 then
if location^.shiftval<0 then a_op_const_reg(list,OP_SHL,location^.size,-location^.shiftval,location^.register);
a_op_const_reg(list,OP_SHL,location^.size,-location^.shiftval,location^.register); end
end { we're at the end of the data, and we need multiple loads
{ we're at the end of the data, and we need multiple loads to get it in the register because it's an irregular size }
to get it in the register because it's an irregular size } else
else begin
begin { should be the last part }
{ should be the last part } if assigned(location^.next) then
if assigned(location^.next) then internalerror(2010052907);
internalerror(2010052907); { load the value piecewise to get it into the register }
{ load the value piecewise to get it into the register } orgsizeleft:=sizeleft;
orgsizeleft:=sizeleft; reghasvalue:=false;
reghasvalue:=false;
{$ifdef cpu64bitalu} {$ifdef cpu64bitalu}
if sizeleft>=4 then if sizeleft>=4 then
begin begin
a_load_ref_reg(list,OS_32,location^.size,tmpref,location^.register); a_load_ref_reg(list,OS_32,location^.size,tmpref,location^.register);
dec(sizeleft,4); dec(sizeleft,4);
if target_info.endian=endian_big then if target_info.endian=endian_big then
a_op_const_reg(list,OP_SHL,location^.size,sizeleft*8,location^.register); a_op_const_reg(list,OP_SHL,location^.size,sizeleft*8,location^.register);
inc(tmpref.offset,4); inc(tmpref.offset,4);
reghasvalue:=true; reghasvalue:=true;
end; end;
{$endif cpu64bitalu} {$endif cpu64bitalu}
if sizeleft>=2 then if sizeleft>=2 then
begin begin
tmpreg:=getintregister(list,location^.size); tmpreg:=getintregister(list,location^.size);
a_load_ref_reg(list,OS_16,location^.size,tmpref,tmpreg); a_load_ref_reg(list,OS_16,location^.size,tmpref,tmpreg);
dec(sizeleft,2); dec(sizeleft,2);
if reghasvalue then if reghasvalue then
begin begin
if target_info.endian=endian_big then if target_info.endian=endian_big then
a_op_const_reg(list,OP_SHL,location^.size,sizeleft*8,tmpreg) a_op_const_reg(list,OP_SHL,location^.size,sizeleft*8,tmpreg)
else else
a_op_const_reg(list,OP_SHL,location^.size,(orgsizeleft-(sizeleft+2))*8,tmpreg); a_op_const_reg(list,OP_SHL,location^.size,(orgsizeleft-(sizeleft+2))*8,tmpreg);
a_op_reg_reg(list,OP_OR,location^.size,tmpreg,location^.register); a_op_reg_reg(list,OP_OR,location^.size,tmpreg,location^.register);
end end
else else
begin begin
if target_info.endian=endian_big then if target_info.endian=endian_big then
a_op_const_reg_reg(list,OP_SHL,location^.size,sizeleft*8,tmpreg,location^.register) a_op_const_reg_reg(list,OP_SHL,location^.size,sizeleft*8,tmpreg,location^.register)
else else
a_load_reg_reg(list,location^.size,location^.size,tmpreg,location^.register); a_load_reg_reg(list,location^.size,location^.size,tmpreg,location^.register);
end; end;
inc(tmpref.offset,2); inc(tmpref.offset,2);
reghasvalue:=true; reghasvalue:=true;
end; end;
if sizeleft=1 then if sizeleft=1 then
begin begin
tmpreg:=getintregister(list,location^.size); tmpreg:=getintregister(list,location^.size);
a_load_ref_reg(list,OS_8,location^.size,tmpref,tmpreg); a_load_ref_reg(list,OS_8,location^.size,tmpref,tmpreg);
dec(sizeleft,1); dec(sizeleft,1);
if reghasvalue then if reghasvalue then
begin begin
if target_info.endian=endian_little then if target_info.endian=endian_little then
a_op_const_reg(list,OP_SHL,location^.size,(orgsizeleft-(sizeleft+1))*8,tmpreg); a_op_const_reg(list,OP_SHL,location^.size,(orgsizeleft-(sizeleft+1))*8,tmpreg);
a_op_reg_reg(list,OP_OR,location^.size,tmpreg,location^.register) a_op_reg_reg(list,OP_OR,location^.size,tmpreg,location^.register)
end end
else else
a_load_reg_reg(list,location^.size,location^.size,tmpreg,location^.register); a_load_reg_reg(list,location^.size,location^.size,tmpreg,location^.register);
inc(tmpref.offset); inc(tmpref.offset);
end; end;
if location^.shiftval<0 then if location^.shiftval<0 then
a_op_const_reg(list,OP_SHL,location^.size,-location^.shiftval,location^.register); a_op_const_reg(list,OP_SHL,location^.size,-location^.shiftval,location^.register);
{ the loop will already adjust the offset and sizeleft } { the loop will already adjust the offset and sizeleft }
dec(tmpref.offset,orgsizeleft); dec(tmpref.offset,orgsizeleft);
sizeleft:=orgsizeleft; sizeleft:=orgsizeleft;
end;
end;
LOC_REFERENCE,LOC_CREFERENCE:
begin
reference_reset_base(ref,location^.reference.index,location^.reference.offset,ctempposinvalid,newalignment(cgpara.alignment,cgpara.intsize-sizeleft),[]);
a_load_ref_cgparalocref(list,size,sizeleft,tmpref,ref,cgpara,location);
end;
LOC_MMREGISTER,LOC_CMMREGISTER:
begin
case location^.size of
OS_F32,
OS_F64,
OS_F128:
a_loadmm_ref_reg(list,location^.size,location^.size,tmpref,location^.register,mms_movescalar);
OS_M8..OS_M512:
a_loadmm_ref_reg(list,location^.size,location^.size,tmpref,location^.register,nil);
else
internalerror(2010053101);
end; end;
end; end;
LOC_FPUREGISTER,LOC_CFPUREGISTER: LOC_REFERENCE,LOC_CREFERENCE:
begin begin
a_loadfpu_ref_reg(list,location^.size,location^.size,tmpref,location^.register); reference_reset_base(ref,location^.reference.index,location^.reference.offset,ctempposinvalid,newalignment(cgpara.alignment,cgpara.intsize-sizeleft),[]);
end a_load_ref_cgparalocref(list,size,sizeleft,tmpref,ref,cgpara,location);
else end;
internalerror(2010053111); LOC_MMREGISTER,LOC_CMMREGISTER:
end; begin
inc(tmpref.offset,tcgsize2size[location^.size]); case location^.size of
dec(sizeleft,tcgsize2size[location^.size]); OS_F32,
location:=location^.next; OS_F64,
OS_F128:
a_loadmm_ref_reg(list,location^.size,location^.size,tmpref,location^.register,mms_movescalar);
OS_M8..OS_M512:
a_loadmm_ref_reg(list,location^.size,location^.size,tmpref,location^.register,nil);
else
internalerror(2010053101);
end;
end;
LOC_FPUREGISTER,LOC_CFPUREGISTER:
begin
{ can be not a float size in case of a record passed in fpu registers }
{ the size comparison is to catch F128 passed in two 64 bit floating point registers }
if is_float_cgsize(size) and
(tcgsize2size[location^.size]>=tcgsize2size[size]) then
usesize:=size
else
usesize:=location^.size;
a_loadfpu_ref_reg(list,usesize,location^.size,tmpref,location^.register);
end
else
internalerror(2010053111);
end; end;
inc(tmpref.offset,tcgsize2size[location^.size]);
dec(sizeleft,tcgsize2size[location^.size]);
location:=location^.next;
until not assigned(location);
end; end;
procedure tcg.a_load_ref_cgparalocref(list: TAsmList; sourcesize: tcgsize; sizeleft: tcgint; const ref, paralocref: treference; const cgpara: tcgpara; const location: PCGParaLocation); procedure tcg.a_load_ref_cgparalocref(list: TAsmList; sourcesize: tcgsize; sizeleft: tcgint; const ref, paralocref: treference; const cgpara: tcgpara; const location: PCGParaLocation);
@ -1882,6 +1889,7 @@ implementation
var var
srcref, srcref,
href : treference; href : treference;
srcsize,
hsize: tcgsize; hsize: tcgsize;
paraloc: PCGParaLocation; paraloc: PCGParaLocation;
sizeleft: tcgint; sizeleft: tcgint;
@ -1894,9 +1902,18 @@ implementation
case paraloc^.loc of case paraloc^.loc of
LOC_FPUREGISTER,LOC_CFPUREGISTER: LOC_FPUREGISTER,LOC_CFPUREGISTER:
begin begin
{ force fpu size } { destination: can be something different in case of a record passed in fpu registers }
hsize:=int_float_cgsize(tcgsize2size[paraloc^.size]); if is_float_cgsize(paraloc^.size) then
a_loadfpu_ref_reg(list,hsize,hsize,srcref,paraloc^.register); hsize:=paraloc^.size
else
hsize:=int_float_cgsize(tcgsize2size[paraloc^.size]);
{ source: the size comparison is to catch F128 passed in two 64 bit floating point registers }
if is_float_cgsize(size) and
(tcgsize2size[size]<=tcgsize2size[paraloc^.size]) then
srcsize:=size
else
srcsize:=hsize;
a_loadfpu_ref_reg(list,srcsize,hsize,srcref,paraloc^.register);
end; end;
LOC_REFERENCE,LOC_CREFERENCE: LOC_REFERENCE,LOC_CREFERENCE:
begin begin