summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
authorflorian <florian@3ad0048d-3df7-0310-abae-a5850022a9f2>2012-11-18 20:42:11 +0000
committerflorian <florian@3ad0048d-3df7-0310-abae-a5850022a9f2>2012-11-18 20:42:11 +0000
commit20e70296884a062d76d386867e841e23a4908756 (patch)
treeb0c7924cec966b33c6706db1c569ca6f2336b313 /compiler
parent63afd3896fa8327c49b8582de562d8d8570f3889 (diff)
downloadfpc-20e70296884a062d76d386867e841e23a4908756.tar.gz
+ started cpupara for aarch64
git-svn-id: http://svn.freepascal.org/svn/fpc/trunk@23029 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'compiler')
-rw-r--r--compiler/aarch64/cpupara.pas705
1 files changed, 705 insertions, 0 deletions
diff --git a/compiler/aarch64/cpupara.pas b/compiler/aarch64/cpupara.pas
new file mode 100644
index 0000000000..4f0e032fc4
--- /dev/null
+++ b/compiler/aarch64/cpupara.pas
@@ -0,0 +1,705 @@
+{
+ Copyright (c) 2003-2012 by Florian Klaempfl and others
+
+ AArch64 specific calling conventions
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ AArch64 specific calling conventions are handled by this unit
+}
+unit cpupara;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,globals,
+ aasmtai,aasmdata,
+ cpuinfo,cpubase,cgbase,cgutils,
+ symconst,symbase,symtype,symdef,parabase,paramgr;
+
+ type
+ taarch64paramanager = class(tparamanager)
+ function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
+ function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
+ function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
+ function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
+ function ret_in_param(def : tdef;calloption : tproccalloption) : boolean;override;
+ procedure getintparaloc(calloption : tproccalloption; nr : longint; def : tdef; var cgpara : tcgpara);override;
+ function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
+ function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
+ function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
+ private
+ procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister);
+ function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
+ var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister; isvariadic: boolean):longint;
+ end;
+
+ implementation
+
+ uses
+ verbose,systems,cutils,
+ rgobj,
+ defutil,symsym,symtable;
+
+
+ function taarch64paramanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=VOLATILE_INTREGISTERS
+ end;
+
+
+ function taarch64paramanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=[];
+ end;
+
+
+ function taarch64paramanager.get_volatile_registers_mm(calloption: tproccalloption): tcpuregisterset;
+ begin
+ result:=VOLATILE_MMREGISTERS;
+ end;
+
+
+ procedure taarch64paramanager.getintparaloc(calloption : tproccalloption; nr : longint; def : tdef; var cgpara : tcgpara);
+ var
+ paraloc : pcgparalocation;
+ begin
+ if nr<1 then
+ internalerror(2002070801);
+ cgpara.reset;
+ cgpara.size:=def_cgsize(def);
+ cgpara.intsize:=tcgsize2size[cgpara.size];
+ cgpara.alignment:=std_param_align;
+ cgpara.def:=def;
+ paraloc:=cgpara.add_location;
+ with paraloc^ do
+ begin
+ size:=OS_INT;
+ { the four first parameters are passed into registers }
+ if nr<=8 then
+ begin
+ loc:=LOC_REGISTER;
+ register:=newreg(R_INTREGISTER,RS_X0+nr-1,R_SUBWHOLE);
+ end
+ else
+ begin
+ { the other parameters are passed on the stack }
+ loc:=LOC_REFERENCE;
+ reference.index:=NR_STACK_POINTER_REG;
+ reference.offset:=(nr-9)*8;
+ end;
+ end;
+ end;
+
+
+ function Is_HFA(p : tdef) : boolean;
+ begin
+ result:=false;
+ end;
+
+
+ function getparaloc(calloption : tproccalloption; p : tdef; isvariadic: boolean) : tcgloc;
+ begin
+ { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
+ if push_addr_param for the def is true
+ }
+ case p.typ of
+ orddef:
+ getparaloc:=LOC_REGISTER;
+ floatdef:
+ getparaloc:=LOC_MMREGISTER
+ enumdef:
+ getparaloc:=LOC_REGISTER;
+ pointerdef:
+ getparaloc:=LOC_REGISTER;
+ formaldef:
+ getparaloc:=LOC_REGISTER;
+ classrefdef:
+ getparaloc:=LOC_REGISTER;
+ recorddef:
+ getparaloc:=LOC_REGISTER;
+ objectdef:
+ getparaloc:=LOC_REGISTER;
+ stringdef:
+ if is_shortstring(p) or is_longstring(p) then
+ getparaloc:=LOC_REFERENCE
+ else
+ getparaloc:=LOC_REGISTER;
+ procvardef:
+ getparaloc:=LOC_REGISTER;
+ filedef:
+ getparaloc:=LOC_REGISTER;
+ arraydef:
+ getparaloc:=LOC_REFERENCE;
+ setdef:
+ if is_smallset(p) then
+ getparaloc:=LOC_REGISTER
+ else
+ getparaloc:=LOC_REFERENCE;
+ variantdef:
+ getparaloc:=LOC_REGISTER;
+ { avoid problems with errornous definitions }
+ errordef:
+ getparaloc:=LOC_REGISTER;
+ else
+ internalerror(2002071001);
+ end;
+ end;
+
+
+ function taarch64paramanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+ begin
+ result:=false;
+ if varspez in [vs_var,vs_out,vs_constref] then
+ begin
+ result:=true;
+ exit;
+ end;
+ case def.typ of
+ objectdef:
+ result:=not(Is_HFA(def) and (is_object(def) and ((varspez=vs_const) or (def.size=0));
+ recorddef:
+ { note: should this ever be changed, make sure that const records
+ are always passed by reference for calloption=pocall_mwpascal }
+ result:=(varspez=vs_const) or (def.size=0);
+ variantdef,
+ formaldef:
+ result:=true;
+ arraydef:
+ result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
+ is_open_array(def) or
+ is_array_of_const(def) or
+ is_array_constructor(def);
+ setdef :
+ result:=def.size>16;
+ stringdef :
+ result:=tstringdef(def).stringtype in [st_shortstring,st_longstring];
+ end;
+ end;
+
+
+ function taarch64paramanager.ret_in_param(def : tdef;calloption : tproccalloption) : boolean;
+ var
+ i: longint;
+ sym: tsym;
+ fpufield: boolean;
+ begin
+ case def.typ of
+ recorddef:
+ begin
+ result:=def.size>4;
+ if not result and
+ (target_info.abi in [abi_default,abi_armeb]) then
+ begin
+ { in case of the old ARM abi (APCS), a struct is returned in
+ a register only if it is simple. And what is a (non-)simple
+ struct:
+
+ "A non-simple type is any non-floating-point type of size
+ greater than one word (including structures containing only
+ floating-point fields), and certain single-word structured
+ types."
+ (-- ARM APCS documentation)
+
+ So only floating point types or more than one word ->
+ definitely non-simple (more than one word is already
+ checked above). This includes unions/variant records with
+ overlaid floating point and integer fields.
+
+ Smaller than one word struct types are simple if they are
+ "integer-like", and:
+
+ "A structure is termed integer-like if its size is less than
+ or equal to one word, and the offset of each of its
+ addressable subfields is zero."
+ (-- ARM APCS documentation)
+
+ An "addressable subfield" is a field of which you can take
+ the address, which in practive means any non-bitfield.
+ In Pascal, there is no way to express the difference that
+ you can have in C between "char" and "int :8". In this
+ context, we use the fake distinction that a type defined
+ inside the record itself (such as "a: 0..255;") indicates
+ a bitpacked field while a field using a different type
+ (such as "a: byte;") is not.
+ }
+ for i:=0 to trecorddef(def).symtable.SymList.count-1 do
+ begin
+ sym:=tsym(trecorddef(def).symtable.SymList[i]);
+ if sym.typ<>fieldvarsym then
+ continue;
+ { bitfield -> ignore }
+ if (trecordsymtable(trecorddef(def).symtable).usefieldalignment=bit_alignment) and
+ (tfieldvarsym(sym).vardef.typ in [orddef,enumdef]) and
+ (tfieldvarsym(sym).vardef.owner.defowner=def) then
+ continue;
+ { all other fields must be at offset zero }
+ if tfieldvarsym(sym).fieldoffset<>0 then
+ begin
+ result:=true;
+ exit;
+ end;
+ { floating point field -> also by reference }
+ if tfieldvarsym(sym).vardef.typ=floatdef then
+ begin
+ result:=true;
+ exit;
+ end;
+ end;
+ end;
+ end;
+ procvardef:
+ if not tprocvardef(def).is_addressonly then
+ result:=true
+ else
+ result:=false
+ else
+ result:=inherited ret_in_param(def,calloption);
+ end;
+ end;
+
+
+ procedure taarch64paramanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister);
+ begin
+ curintreg:=RS_R0;
+ curfloatreg:=RS_F0;
+ curmmreg:=RS_D0;
+ cur_stack_offset:=0;
+ sparesinglereg := NR_NO;
+ end;
+
+
+ function taarch64paramanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
+ var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister; isvariadic: boolean):longint;
+
+ var
+ nextintreg,nextfloatreg,nextmmreg : tsuperregister;
+ paradef : tdef;
+ paraloc : pcgparalocation;
+ stack_offset : aword;
+ hp : tparavarsym;
+ loc : tcgloc;
+ paracgsize : tcgsize;
+ paralen : longint;
+ i : integer;
+ firstparaloc: boolean;
+
+ procedure assignintreg;
+ begin
+ { In case of po_delphi_nested_cc, the parent frame pointer
+ is always passed on the stack. }
+ if (nextintreg<=RS_R3) and
+ (not(vo_is_parentfp in hp.varoptions) or
+ not(po_delphi_nested_cc in p.procoptions)) then
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
+ inc(nextintreg);
+ end
+ else
+ begin
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.reference.index:=NR_STACK_POINTER_REG;
+ paraloc^.reference.offset:=stack_offset;
+ inc(stack_offset,4);
+ end;
+ end;
+
+
+ begin
+ result:=0;
+ nextintreg:=curintreg;
+ nextfloatreg:=curfloatreg;
+ nextmmreg:=curmmreg;
+ stack_offset:=cur_stack_offset;
+
+ for i:=0 to paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ paradef:=hp.vardef;
+
+ hp.paraloc[side].reset;
+
+ { currently only support C-style array of const,
+ there should be no location assigned to the vararg array itself }
+ if (p.proccalloption in cstylearrayofconst) and
+ is_array_of_const(paradef) then
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ { hack: the paraloc must be valid, but is not actually used }
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_R0;
+ paraloc^.size:=OS_ADDR;
+ break;
+ end;
+
+ if push_addr_param(hp.varspez,paradef,p.proccalloption) then
+ begin
+ paradef:=getpointerdef(paradef);
+ loc:=LOC_REGISTER;
+ paracgsize := OS_ADDR;
+ paralen := tcgsize2size[OS_ADDR];
+ end
+ else
+ begin
+ if not is_special_array(paradef) then
+ paralen := paradef.size
+ else
+ paralen := tcgsize2size[def_cgsize(paradef)];
+ loc := getparaloc(p.proccalloption,paradef,isvariadic);
+ if (paradef.typ in [objectdef,arraydef,recorddef]) and
+ not is_special_array(paradef) and
+ (hp.varspez in [vs_value,vs_const]) then
+ paracgsize := int_cgsize(paralen)
+ else
+ begin
+ paracgsize:=def_cgsize(paradef);
+ { for things like formaldef }
+ if (paracgsize=OS_NO) then
+ begin
+ paracgsize:=OS_ADDR;
+ paralen:=tcgsize2size[OS_ADDR];
+ paradef:=voidpointertype;
+ end;
+ end
+ end;
+
+ hp.paraloc[side].size:=paracgsize;
+ hp.paraloc[side].Alignment:=std_param_align;
+ hp.paraloc[side].intsize:=paralen;
+ hp.paraloc[side].def:=paradef;
+ firstparaloc:=true;
+
+{$ifdef EXTDEBUG}
+ if paralen=0 then
+ internalerror(200410311);
+{$endif EXTDEBUG}
+ while paralen>0 do
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+
+ if (loc=LOC_REGISTER) and (paracgsize in [OS_F32,OS_F64,OS_F80]) then
+ case paracgsize of
+ OS_F32:
+ paraloc^.size:=OS_32;
+ OS_F64:
+ paraloc^.size:=OS_32;
+ else
+ internalerror(2005082901);
+ end
+ else if (paracgsize in [OS_NO,OS_64,OS_S64]) then
+ paraloc^.size := OS_32
+ else
+ paraloc^.size:=paracgsize;
+ case loc of
+ LOC_REGISTER:
+ begin
+ { align registers for eabi }
+ if (target_info.abi in [abi_eabi,abi_eabihf]) and
+ firstparaloc and
+ (paradef.alignment=8) then
+ begin
+ if (nextintreg in [RS_R1,RS_R3]) then
+ inc(nextintreg)
+ else if nextintreg>RS_R3 then
+ stack_offset:=align(stack_offset,8);
+ end;
+ { this is not abi compliant
+ why? (FK) }
+ if nextintreg<=RS_R3 then
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
+ inc(nextintreg);
+ end
+ else
+ begin
+ { LOC_REFERENCE always contains everything that's left }
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=int_cgsize(paralen);
+ if (side=callerside) then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG;
+ paraloc^.reference.offset:=stack_offset;
+ inc(stack_offset,align(paralen,4));
+ paralen:=0;
+ end;
+ end;
+ LOC_FPUREGISTER:
+ begin
+ if nextfloatreg<=RS_F3 then
+ begin
+ paraloc^.loc:=LOC_FPUREGISTER;
+ paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
+ inc(nextfloatreg);
+ end
+ else
+ begin
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.reference.index:=NR_STACK_POINTER_REG;
+ paraloc^.reference.offset:=stack_offset;
+ case paraloc^.size of
+ OS_F32:
+ inc(stack_offset,4);
+ OS_F64:
+ inc(stack_offset,8);
+ OS_F80:
+ inc(stack_offset,10);
+ OS_F128:
+ inc(stack_offset,16);
+ else
+ internalerror(200403201);
+ end;
+ end;
+ end;
+ LOC_MMREGISTER:
+ begin
+ if (nextmmreg<=RS_D7) or
+ ((paraloc^.size = OS_F32) and
+ (sparesinglereg<>NR_NO)) then
+ begin
+ paraloc^.loc:=LOC_MMREGISTER;
+ case paraloc^.size of
+ OS_F32:
+ if sparesinglereg = NR_NO then
+ begin
+ paraloc^.register:=newreg(R_MMREGISTER,nextmmreg,R_SUBFS);
+ sparesinglereg:=newreg(R_MMREGISTER,nextmmreg-RS_S0+RS_S1,R_SUBFS);
+ inc(nextmmreg);
+ end
+ else
+ begin
+ paraloc^.register:=sparesinglereg;
+ sparesinglereg := NR_NO;
+ end;
+ OS_F64:
+ begin
+ paraloc^.register:=newreg(R_MMREGISTER,nextmmreg,R_SUBFD);
+ inc(nextmmreg);
+ end;
+ else
+ internalerror(2012031601);
+ end;
+ end
+ else
+ begin
+ { once a floating point parameters has been placed
+ on the stack we must not pass any more in vfp regs
+ even if there is a single precision register still
+ free}
+ sparesinglereg := NR_NO;
+ { LOC_REFERENCE always contains everything that's left }
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=int_cgsize(paralen);
+ if (side=callerside) then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG;
+ paraloc^.reference.offset:=stack_offset;
+ inc(stack_offset,align(paralen,4));
+ paralen:=0;
+ end;
+ end;
+ LOC_REFERENCE:
+ begin
+ if push_addr_param(hp.varspez,paradef,p.proccalloption) then
+ begin
+ paraloc^.size:=OS_ADDR;
+ assignintreg
+ end
+ else
+ begin
+ { align stack for eabi }
+ if (target_info.abi in [abi_eabi,abi_eabihf]) and
+ firstparaloc and
+ (paradef.alignment=8) then
+ stack_offset:=align(stack_offset,8);
+
+ paraloc^.size:=paracgsize;
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.reference.index:=NR_STACK_POINTER_REG;
+ paraloc^.reference.offset:=stack_offset;
+ inc(stack_offset,align(paralen,4));
+ paralen:=0
+ end;
+ end;
+ else
+ internalerror(2002071002);
+ end;
+ if side=calleeside then
+ begin
+ if paraloc^.loc=LOC_REFERENCE then
+ begin
+ paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+ { on non-Darwin, the framepointer contains the value
+ of the stack pointer on entry. On Darwin, the
+ framepointer points to the previously saved
+ framepointer (which is followed only by the saved
+ return address -> framepointer + 4 = stack pointer
+ on entry }
+ if not(target_info.system in systems_darwin) then
+ inc(paraloc^.reference.offset,4)
+ else
+ inc(paraloc^.reference.offset,8);
+ end;
+ end;
+ dec(paralen,tcgsize2size[paraloc^.size]);
+ firstparaloc:=false
+ end;
+ end;
+ curintreg:=nextintreg;
+ curfloatreg:=nextfloatreg;
+ curmmreg:=nextmmreg;
+ cur_stack_offset:=stack_offset;
+ result:=cur_stack_offset;
+ end;
+
+
+ function taarch64paramanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
+ var
+ paraloc : pcgparalocation;
+ retcgsize : tcgsize;
+ begin
+ if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
+ exit;
+
+ paraloc:=result.add_location;
+ { Return in FPU register? }
+ if result.def.typ=floatdef then
+ begin
+ if target_info.abi = abi_eabihf then
+ begin
+ paraloc^.loc:=LOC_MMREGISTER;
+ case retcgsize of
+ OS_64,
+ OS_F64:
+ begin
+ paraloc^.register:=NR_MM_RESULT_REG;
+ end;
+ OS_32,
+ OS_F32:
+ begin
+ paraloc^.register:=NR_S0;
+ end;
+ else
+ internalerror(2012032501);
+ end;
+ paraloc^.size:=retcgsize;
+ end
+ else if (p.proccalloption in [pocall_softfloat]) or
+ (cs_fp_emulation in current_settings.moduleswitches) or
+ (current_settings.fputype in [fpu_vfpv2,fpu_vfpv3,fpu_vfpv3_d16,fpu_fpv4_s16]) then
+ begin
+ case retcgsize of
+ OS_64,
+ OS_F64:
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ if target_info.endian = endian_big then
+ paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
+ else
+ paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
+ paraloc^.size:=OS_32;
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REGISTER;
+ if target_info.endian = endian_big then
+ paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
+ else
+ paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
+ paraloc^.size:=OS_32;
+ end;
+ OS_32,
+ OS_F32:
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_FUNCTION_RETURN_REG;
+ paraloc^.size:=OS_32;
+ end;
+ else
+ internalerror(2005082603);
+ end;
+ end
+ else
+ begin
+ paraloc^.loc:=LOC_FPUREGISTER;
+ paraloc^.register:=NR_FPU_RESULT_REG;
+ paraloc^.size:=retcgsize;
+ end;
+ end
+ { Return in register }
+ else
+ begin
+ if retcgsize in [OS_64,OS_S64] then
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ if target_info.endian = endian_big then
+ paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
+ else
+ paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
+ paraloc^.size:=OS_32;
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REGISTER;
+ if target_info.endian = endian_big then
+ paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
+ else
+ paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
+ paraloc^.size:=OS_32;
+ end
+ else
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_FUNCTION_RETURN_REG;
+ if (result.intsize<>3) then
+ paraloc^.size:=retcgsize
+ else
+ paraloc^.size:=OS_32;
+ end;
+ end;
+ end;
+
+
+ function taarch64paramanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
+ var
+ cur_stack_offset: aword;
+ curintreg, curfloatreg, curmmreg: tsuperregister;
+ sparesinglereg:tregister;
+ begin
+ init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg);
+
+ result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg,false);
+
+ create_funcretloc_info(p,side);
+ end;
+
+
+ function taarch64paramanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
+ var
+ cur_stack_offset: aword;
+ curintreg, curfloatreg, curmmreg: tsuperregister;
+ sparesinglereg:tregister;
+ begin
+ init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg);
+
+ result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg,true);
+ if (p.proccalloption in cstylearrayofconst) then
+ { just continue loading the parameters in the registers }
+ result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg,true)
+ else
+ internalerror(200410231);
+ end;
+
+begin
+ paramanager:=taarch64paramanager.create;
+end.