mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 05:08:06 +02:00
* MIPS: fixed parameter management to properly align records smaller than 32 bits on big-endian targets.
* Also changed parameter management to allocate a single LOC_REFERENCE location for any parameter (or part of a parameter) passed on stack. Such locations can now be handled by generic code. As a consequence, TGMIPS.a_load_const_cgpara and a_load_ref_cgpara methods are no longer necessary (moreover they were ignoring parameter shifting). * a_loadfpu_ref_cgpara patched to handle 64-bit location, which are now possible. * This change eliminates code generation madness where each word of a record was copied individually, thus passing by value a 32K-word sized record was bloating into 64K instructions, multiply this number by 2 for larger records due to limited immediate offsets, and by another 2 for global record in PIC mode :/ git-svn-id: trunk@23575 -
This commit is contained in:
parent
c6c67dc182
commit
d82387ff72
@ -49,8 +49,6 @@ type
|
||||
procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
|
||||
|
||||
{ parameter }
|
||||
procedure a_load_const_cgpara(list: tasmlist; size: tcgsize; a: tcgint; const paraloc: TCGPara); override;
|
||||
procedure a_load_ref_cgpara(list: tasmlist; sz: tcgsize; const r: TReference; const paraloc: TCGPara); override;
|
||||
procedure a_loadaddr_ref_cgpara(list: tasmlist; const r: TReference; const paraloc: TCGPara); override;
|
||||
procedure a_loadfpu_reg_cgpara(list: tasmlist; size: tcgsize; const r: tregister; const paraloc: TCGPara); override;
|
||||
procedure a_loadfpu_ref_cgpara(list: tasmlist; size: tcgsize; const ref: treference; const paraloc: TCGPara); override;
|
||||
@ -543,60 +541,6 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
procedure TCGMIPS.a_load_const_cgpara(list: tasmlist; size: tcgsize; a: tcgint; const paraloc: TCGPara);
|
||||
var
|
||||
Ref: TReference;
|
||||
begin
|
||||
paraloc.check_simple_location;
|
||||
paramanager.allocparaloc(list,paraloc.location);
|
||||
case paraloc.location^.loc of
|
||||
LOC_REGISTER, LOC_CREGISTER:
|
||||
a_load_const_reg(list, size, a, paraloc.location^.Register);
|
||||
LOC_REFERENCE:
|
||||
begin
|
||||
with paraloc.location^.Reference do
|
||||
begin
|
||||
if (Index = NR_SP) and (Offset < 0) then
|
||||
InternalError(2002081104);
|
||||
reference_reset_base(ref, index, offset, sizeof(aint));
|
||||
end;
|
||||
a_load_const_ref(list, size, a, ref);
|
||||
end;
|
||||
else
|
||||
InternalError(2002122200);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure TCGMIPS.a_load_ref_cgpara(list: tasmlist; sz: TCgSize; const r: TReference; const paraloc: TCGPara);
|
||||
var
|
||||
href, href2: treference;
|
||||
hloc: pcgparalocation;
|
||||
begin
|
||||
href := r;
|
||||
hloc := paraloc.location;
|
||||
while assigned(hloc) do
|
||||
begin
|
||||
paramanager.allocparaloc(list,hloc);
|
||||
case hloc^.loc of
|
||||
LOC_REGISTER,LOC_CREGISTER:
|
||||
a_load_ref_reg(list, hloc^.size, hloc^.size, href, hloc^.Register);
|
||||
LOC_FPUREGISTER,LOC_CFPUREGISTER :
|
||||
a_loadfpu_ref_reg(list,hloc^.size,hloc^.size,href,hloc^.register);
|
||||
LOC_REFERENCE:
|
||||
begin
|
||||
reference_reset_base(href2, hloc^.reference.index, hloc^.reference.offset, sizeof(aint));
|
||||
a_load_ref_ref(list, hloc^.size, hloc^.size, href, href2);
|
||||
end
|
||||
else
|
||||
internalerror(200408241);
|
||||
end;
|
||||
Inc(href.offset, tcgsize2size[hloc^.size]);
|
||||
hloc := hloc^.Next;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure TCGMIPS.a_loadaddr_ref_cgpara(list: tasmlist; const r: TReference; const paraloc: TCGPara);
|
||||
var
|
||||
Ref: TReference;
|
||||
@ -630,6 +574,9 @@ var
|
||||
href, href2: treference;
|
||||
hloc: pcgparalocation;
|
||||
begin
|
||||
{ TODO: inherited cannot deal with individual locations for each of OS_32 registers.
|
||||
Must change parameter management to allocate a single 64-bit register pair,
|
||||
then this method can be removed. }
|
||||
href := ref;
|
||||
hloc := paraloc.location;
|
||||
while assigned(hloc) do
|
||||
@ -642,8 +589,10 @@ begin
|
||||
a_loadfpu_ref_reg(list,hloc^.size,hloc^.size,href,hloc^.register);
|
||||
LOC_REFERENCE:
|
||||
begin
|
||||
reference_reset_base(href2, hloc^.reference.index, hloc^.reference.offset, sizeof(aint));
|
||||
a_load_ref_ref(list, hloc^.size, hloc^.size, href, href2);
|
||||
paraloc.check_simple_location;
|
||||
reference_reset_base(href2,paraloc.location^.reference.index,paraloc.location^.reference.offset,paraloc.alignment);
|
||||
{ concatcopy should choose the best way to copy the data }
|
||||
g_concatcopy(list,ref,href2,tcgsize2size[size]);
|
||||
end;
|
||||
else
|
||||
internalerror(200408241);
|
||||
|
@ -384,6 +384,17 @@ implementation
|
||||
paraloc^.size:=OS_32
|
||||
else
|
||||
paraloc^.size:=paracgsize;
|
||||
|
||||
{ big-endian targets require that record data stored in parameter
|
||||
registers is left-aligned }
|
||||
if (target_info.endian=endian_big) and
|
||||
(paradef.typ = recorddef) and
|
||||
(tcgsize2size[paraloc^.size] <> sizeof(aint)) then
|
||||
begin
|
||||
paraloc^.shiftval := (sizeof(aint)-tcgsize2size[paraloc^.size])*(-8);
|
||||
paraloc^.size := OS_INT;
|
||||
end;
|
||||
|
||||
{ ret in param? }
|
||||
if (vo_is_funcret in hp.varoptions) and
|
||||
is_abi_record(hp.vardef) then
|
||||
@ -393,7 +404,7 @@ implementation
|
||||
begin
|
||||
TMIPSProcInfo(current_procinfo).register_used[0]:=true;
|
||||
TMIPSProcInfo(current_procinfo).register_name[0]:='result';
|
||||
TMIPSProcInfo(current_procinfo).register_size[0]:=paracgsize;
|
||||
TMIPSProcInfo(current_procinfo).register_size[0]:=paraloc^.size;
|
||||
TMIPSProcInfo(current_procinfo).register_offset[0]:=0;
|
||||
end;
|
||||
//if (intparareg<>1) then
|
||||
@ -453,7 +464,7 @@ implementation
|
||||
begin
|
||||
TMIPSProcInfo(current_procinfo).register_used[intparareg]:=true;
|
||||
TMIPSProcInfo(current_procinfo).register_name[intparareg]:=hp.prettyname;
|
||||
TMIPSProcInfo(current_procinfo).register_size[intparareg]:=paracgsize;
|
||||
TMIPSProcInfo(current_procinfo).register_size[intparareg]:=paraloc^.size;
|
||||
TMIPSProcInfo(current_procinfo).register_offset[intparareg]:=intparareg*mips_sizeof_register_param;
|
||||
end;
|
||||
if side=callerside then
|
||||
@ -481,14 +492,18 @@ implementation
|
||||
else
|
||||
begin
|
||||
paraloc^.loc:=LOC_REFERENCE;
|
||||
paraloc^.size:=int_cgsize(paralen);
|
||||
|
||||
{ Force size to multiple of 4 for records passed by value,
|
||||
to obtain correct memory layout for big endian }
|
||||
(*
|
||||
if (paradef.typ = recorddef) and
|
||||
(tcgsize2size[paraloc^.size] < tcgsize2size[OS_32]) then
|
||||
begin
|
||||
inc(paralen,tcgsize2size[OS_32]-tcgsize2size[paraloc^.size]);
|
||||
paraloc^.size := OS_32;
|
||||
end;
|
||||
*)
|
||||
if side=callerside then
|
||||
begin
|
||||
paraloc^.reference.index := NR_STACK_POINTER_REG;
|
||||
@ -506,7 +521,8 @@ implementation
|
||||
end;
|
||||
paraloc^.reference.offset:=intparasize;
|
||||
end;
|
||||
inc(intparasize,align(tcgsize2size[paraloc^.size],mips_sizeof_register_param));
|
||||
inc(intparasize,align(paralen,mips_sizeof_register_param));
|
||||
paralen:=0;
|
||||
end;
|
||||
dec(paralen,tcgsize2size[paraloc^.size]);
|
||||
end;
|
||||
|
Loading…
Reference in New Issue
Block a user