mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-18 23:09:18 +02:00
* tcg.a_load_cgparaloc_ref checks the size of the ref exactly to avoid overwriting of adjacent data
git-svn-id: trunk@36951 -
This commit is contained in:
parent
9b3e0a80df
commit
43b017bde0
@ -1091,57 +1091,129 @@ implementation
|
|||||||
hreg : tregister;
|
hreg : tregister;
|
||||||
cgsize: tcgsize;
|
cgsize: tcgsize;
|
||||||
begin
|
begin
|
||||||
case paraloc.loc of
|
case paraloc.loc of
|
||||||
LOC_REGISTER :
|
LOC_REGISTER :
|
||||||
begin
|
begin
|
||||||
hreg:=paraloc.register;
|
hreg:=paraloc.register;
|
||||||
cgsize:=paraloc.size;
|
cgsize:=paraloc.size;
|
||||||
if paraloc.shiftval>0 then
|
if paraloc.shiftval>0 then
|
||||||
a_op_const_reg_reg(list,OP_SHL,OS_INT,paraloc.shiftval,paraloc.register,paraloc.register)
|
a_op_const_reg_reg(list,OP_SHL,OS_INT,paraloc.shiftval,paraloc.register,paraloc.register)
|
||||||
{ in case the original size was 3 or 5/6/7 bytes, the value was
|
{ in case the original size was 3 or 5/6/7 bytes, the value was
|
||||||
shifted to the top of the to 4 resp. 8 byte register on the
|
shifted to the top of the to 4 resp. 8 byte register on the
|
||||||
caller side and needs to be stored with those bytes at the
|
caller side and needs to be stored with those bytes at the
|
||||||
start of the reference -> don't shift right }
|
start of the reference -> don't shift right }
|
||||||
else if (paraloc.shiftval<0) and
|
else if (paraloc.shiftval<0) and
|
||||||
((-paraloc.shiftval) in [1,2,4]) then
|
((-paraloc.shiftval) in [8,16,32]) then
|
||||||
begin
|
begin
|
||||||
a_op_const_reg_reg(list,OP_SHR,OS_INT,-paraloc.shiftval,paraloc.register,paraloc.register);
|
a_op_const_reg_reg(list,OP_SHR,OS_INT,-paraloc.shiftval,paraloc.register,paraloc.register);
|
||||||
{ convert to a register of 1/2/4 bytes in size, since the
|
{ convert to a register of 1/2/4 bytes in size, since the
|
||||||
original register had to be made larger to be able to hold
|
original register had to be made larger to be able to hold
|
||||||
the shifted value }
|
the shifted value }
|
||||||
cgsize:=int_cgsize(tcgsize2size[OS_INT]-(-paraloc.shiftval div 8));
|
cgsize:=int_cgsize(tcgsize2size[OS_INT]-(-paraloc.shiftval div 8));
|
||||||
hreg:=getintregister(list,cgsize);
|
hreg:=getintregister(list,cgsize);
|
||||||
a_load_reg_reg(list,OS_INT,cgsize,paraloc.register,hreg);
|
a_load_reg_reg(list,OS_INT,cgsize,paraloc.register,hreg);
|
||||||
end;
|
end;
|
||||||
a_load_reg_ref(list,paraloc.size,cgsize,hreg,ref);
|
{ use the exact size to avoid overwriting of adjacent data }
|
||||||
end;
|
if tcgsize2size[cgsize]<=sizeleft then
|
||||||
LOC_MMREGISTER :
|
a_load_reg_ref(list,paraloc.size,cgsize,hreg,ref)
|
||||||
begin
|
else
|
||||||
case paraloc.size of
|
case sizeleft of
|
||||||
OS_F32,
|
1,2,4,8:
|
||||||
OS_F64,
|
a_load_reg_ref(list,paraloc.size,int_cgsize(sizeleft),hreg,ref);
|
||||||
OS_F128:
|
3:
|
||||||
a_loadmm_reg_ref(list,paraloc.size,paraloc.size,paraloc.register,ref,mms_movescalar);
|
begin
|
||||||
OS_M8..OS_M128,
|
if target_info.endian=endian_big then
|
||||||
OS_MS8..OS_MS128:
|
begin
|
||||||
a_loadmm_reg_ref(list,paraloc.size,paraloc.size,paraloc.register,ref,nil);
|
href:=ref;
|
||||||
else
|
inc(href.offset,2);
|
||||||
internalerror(2010053102);
|
a_load_reg_ref(list,paraloc.size,OS_8,hreg,href);
|
||||||
end;
|
a_op_const_reg_reg(list,OP_SHR,OS_INT,8,hreg,hreg);
|
||||||
end;
|
a_load_reg_ref(list,paraloc.size,OS_16,hreg,ref);
|
||||||
LOC_FPUREGISTER :
|
end
|
||||||
a_loadfpu_reg_ref(list,paraloc.size,paraloc.size,paraloc.register,ref);
|
else
|
||||||
LOC_REFERENCE :
|
{ little endian not implemented yet }
|
||||||
begin
|
Internalerror(2017081301);
|
||||||
reference_reset_base(href,paraloc.reference.index,paraloc.reference.offset,align,[]);
|
end;
|
||||||
{ use concatcopy, because it can also be a float which fails when
|
5:
|
||||||
load_ref_ref is used. Don't copy data when the references are equal }
|
begin
|
||||||
if not((href.base=ref.base) and (href.offset=ref.offset)) then
|
if target_info.endian=endian_big then
|
||||||
g_concatcopy(list,href,ref,sizeleft);
|
begin
|
||||||
end;
|
href:=ref;
|
||||||
else
|
inc(href.offset,4);
|
||||||
internalerror(2002081302);
|
a_load_reg_ref(list,paraloc.size,OS_8,hreg,href);
|
||||||
end;
|
a_op_const_reg_reg(list,OP_SHR,OS_INT,8,hreg,hreg);
|
||||||
|
a_load_reg_ref(list,paraloc.size,OS_32,hreg,ref);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
{ little endian not implemented yet }
|
||||||
|
Internalerror(2017081302);
|
||||||
|
end;
|
||||||
|
6:
|
||||||
|
begin
|
||||||
|
if target_info.endian=endian_big then
|
||||||
|
begin
|
||||||
|
href:=ref;
|
||||||
|
inc(href.offset,4);
|
||||||
|
a_load_reg_ref(list,paraloc.size,OS_16,hreg,href);
|
||||||
|
a_op_const_reg_reg(list,OP_SHR,OS_INT,16,hreg,hreg);
|
||||||
|
a_load_reg_ref(list,paraloc.size,OS_32,hreg,ref);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
{ little endian not implemented yet }
|
||||||
|
Internalerror(2017081303);
|
||||||
|
end;
|
||||||
|
7:
|
||||||
|
begin
|
||||||
|
if target_info.endian=endian_big then
|
||||||
|
begin
|
||||||
|
href:=ref;
|
||||||
|
inc(href.offset,6);
|
||||||
|
a_load_reg_ref(list,paraloc.size,OS_8,hreg,href);
|
||||||
|
|
||||||
|
a_op_const_reg_reg(list,OP_SHR,OS_INT,8,hreg,hreg);
|
||||||
|
href:=ref;
|
||||||
|
inc(href.offset,4);
|
||||||
|
a_load_reg_ref(list,paraloc.size,OS_16,hreg,href);
|
||||||
|
|
||||||
|
a_op_const_reg_reg(list,OP_SHR,OS_INT,16,hreg,hreg);
|
||||||
|
a_load_reg_ref(list,paraloc.size,OS_32,hreg,ref);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
{ little endian not implemented yet }
|
||||||
|
Internalerror(2017081304);
|
||||||
|
end;
|
||||||
|
else
|
||||||
|
{ other sizes not allowed }
|
||||||
|
Internalerror(2017080901);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
LOC_MMREGISTER :
|
||||||
|
begin
|
||||||
|
case paraloc.size of
|
||||||
|
OS_F32,
|
||||||
|
OS_F64,
|
||||||
|
OS_F128:
|
||||||
|
a_loadmm_reg_ref(list,paraloc.size,paraloc.size,paraloc.register,ref,mms_movescalar);
|
||||||
|
OS_M8..OS_M128,
|
||||||
|
OS_MS8..OS_MS128:
|
||||||
|
a_loadmm_reg_ref(list,paraloc.size,paraloc.size,paraloc.register,ref,nil);
|
||||||
|
else
|
||||||
|
internalerror(2010053102);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
LOC_FPUREGISTER :
|
||||||
|
a_loadfpu_reg_ref(list,paraloc.size,paraloc.size,paraloc.register,ref);
|
||||||
|
LOC_REFERENCE :
|
||||||
|
begin
|
||||||
|
reference_reset_base(href,paraloc.reference.index,paraloc.reference.offset,align,[]);
|
||||||
|
{ use concatcopy, because it can also be a float which fails when
|
||||||
|
load_ref_ref is used. Don't copy data when the references are equal }
|
||||||
|
if not((href.base=ref.base) and (href.offset=ref.offset)) then
|
||||||
|
g_concatcopy(list,href,ref,sizeleft);
|
||||||
|
end;
|
||||||
|
else
|
||||||
|
internalerror(2002081302);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user