Преглед изворни кода

* split create_paraloc_info_intern for sparc32 and sparc64
* fixed several sparc64 calling convention issues

git-svn-id: trunk@36947 -

florian пре 8 година
родитељ
комит
9c3f5db022
3 измењених фајлова са 548 додато и 254 уклоњено
  1. 207 0
      compiler/sparc/cpupara.pas
  2. 317 0
      compiler/sparc64/cpupara.pas
  3. 24 254
      compiler/sparcgen/sppara.pas

+ 207 - 0
compiler/sparc/cpupara.pas

@@ -33,6 +33,10 @@ interface
 
 
     type
     type
       tcpuparamanager=class(TSparcParaManager)
       tcpuparamanager=class(TSparcParaManager)
+        procedure create_paraloc_info_intern(p : tabstractprocdef; side : tcallercallee; paras : tparalist;
+                                             var curintreg: LongInt; curfloatreg: tsuperregister; var cur_stack_offset: aword);override;
+        function push_addr_param(varspez : tvarspez; def : tdef; calloption : tproccalloption) : boolean;override;
+        function  get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
       end;
       end;
 
 
 implementation
 implementation
@@ -42,6 +46,209 @@ implementation
       defutil,
       defutil,
       cgobj;
       cgobj;
 
 
+    { true if a parameter is too large to copy and only the address is pushed }
+    function tcpuparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+      begin
+        result:=false;
+        { var,out,constref always require address }
+        if varspez in [vs_var,vs_out,vs_constref] then
+          begin
+            result:=true;
+            exit;
+          end;
+        case def.typ of
+          arraydef:
+            result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
+                             is_open_array(def) or
+                             is_array_of_const(def) or
+                             is_array_constructor(def);
+          recorddef,
+          variantdef,
+          formaldef :
+            result:=true;
+          objectdef :
+            result:=is_object(def);
+          stringdef :
+            result:=(tstringdef(def).stringtype in [st_shortstring,st_longstring]);
+          procvardef :
+            result:=not tprocvardef(def).is_addressonly;
+          setdef :
+            result:=not is_smallset(def);
+        end;
+      end;
+
+
+    procedure tcpuparamanager.create_paraloc_info_intern(p : tabstractprocdef; side : tcallercallee; paras : tparalist;
+                                                         var curintreg : LongInt; curfloatreg : tsuperregister;
+                                                         var cur_stack_offset : aword);
+      var
+        paraloc      : pcgparalocation;
+        i            : integer;
+        hp           : tparavarsym;
+        paradef      : tdef;
+        paracgsize   : tcgsize;
+        hparasupregs : pparasupregs;
+        paralen      : longint;
+      begin
+        if side=callerside then
+          hparasupregs:=@paraoutsupregs
+        else
+          hparasupregs:=@parainsupregs;
+        for i:=0 to paras.count-1 do
+          begin
+            hp:=tparavarsym(paras[i]);
+            paradef:=hp.vardef;
+            { 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_G0;
+                paraloc^.size:=OS_ADDR;
+                paraloc^.def:=voidpointertype;
+                break;
+              end;
+
+            if push_addr_param(hp.varspez,paradef,p.proccalloption) then
+              begin
+                paracgsize:=OS_ADDR;
+                paradef:=cpointerdef.getreusable_no_free(paradef);
+              end
+            else
+              begin
+                paracgsize:=def_cgsize(paradef);
+                { for formaldef }
+                if paracgsize=OS_NO then
+                  begin
+                    paracgsize:=OS_ADDR;
+                    paradef:=voidpointertype;
+                  end;
+              end;
+            hp.paraloc[side].reset;
+            hp.paraloc[side].size:=paracgsize;
+            hp.paraloc[side].def:=paradef;
+            if (side = callerside) then
+              hp.paraloc[side].Alignment:=std_param_align
+            else
+              hp.paraloc[side].Alignment:=paradef.alignment;
+            paralen:=tcgsize2size[paracgsize];
+            hp.paraloc[side].intsize:=paralen;
+            while paralen>0 do
+              begin
+                paraloc:=hp.paraloc[side].add_location;
+                { Floats are passed in int registers,
+                  We can allocate at maximum 32 bits per register }
+                if paracgsize in [OS_64,OS_S64,OS_F32,OS_F64] then
+                  begin
+                    paraloc^.size:=OS_32;
+                    paraloc^.def:=u32inttype;
+                  end
+                else
+                  begin
+                    paraloc^.size:=paracgsize;
+                    paraloc^.def:=paradef;
+                  end;
+                { ret in param? }
+                if vo_is_funcret in hp.varoptions then
+                  begin
+                    paraloc^.loc:=LOC_REFERENCE;
+                    paraloc^.reference.offset:=64;
+                    if side=callerside then
+                      paraloc^.reference.index:=NR_STACK_POINTER_REG
+                    else
+                      paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+                  end
+                { In case of po_delphi_nested_cc, the parent frame pointer
+                  is always passed on the stack. }
+                else if (curintreg<=high(tparasupregs)) 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,hparasupregs^[curintreg],R_SUBWHOLE);
+                    inc(curintreg);
+                  end
+                else
+                  begin
+                    paraloc^.loc:=LOC_REFERENCE;
+                    paraloc^.reference.offset:=target_info.first_parm_offset+cur_stack_offset;
+                    if side=callerside then
+                      paraloc^.reference.index:=NR_STACK_POINTER_REG
+                    else
+                      paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+                    if (target_info.endian=endian_big) and
+                       (paralen<tcgsize2size[OS_INT]) and
+                       (paradef.typ<>recorddef) then
+                      inc(paraloc^.reference.offset,4-paralen);
+
+                    { Parameters are aligned at 4 bytes }
+                    inc(cur_stack_offset,align(tcgsize2size[paraloc^.size],sizeof(pint)));
+                  end;
+                dec(paralen,tcgsize2size[paraloc^.size]);
+              end;
+          end;
+      end;
+
+
+    function tcpuparamanager.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
+            paraloc^.loc:=LOC_FPUREGISTER;
+            paraloc^.register:=NR_FPU_RESULT_REG;
+            if retcgsize=OS_F64 then
+              setsubreg(paraloc^.register,R_SUBFD);
+            paraloc^.size:=retcgsize;
+            paraloc^.def:=result.def;
+          end
+        else
+         { Return in register }
+          begin
+            if retcgsize in [OS_64,OS_S64] then
+              begin
+                paraloc^.loc:=LOC_REGISTER;
+                { high }
+                if side=callerside then
+                  paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
+                else
+                  paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
+                paraloc^.size:=OS_32;
+                paraloc^.def:=u32inttype;
+                { low }
+                paraloc:=result.add_location;
+                paraloc^.loc:=LOC_REGISTER;
+                if side=callerside then
+                  paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
+                else
+                  paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
+                paraloc^.size:=OS_32;
+                paraloc^.def:=u32inttype;
+              end
+            else
+              begin
+                paraloc^.loc:=LOC_REGISTER;
+                paraloc^.size:=retcgsize;
+                paraloc^.def:=result.def;
+                if (side=callerside) then
+                  paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
+                else
+                  paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
+              end;
+          end;
+      end;
+
+
 begin
 begin
    ParaManager:=tcpuparamanager.create;
    ParaManager:=tcpuparamanager.create;
 end.
 end.

+ 317 - 0
compiler/sparc64/cpupara.pas

@@ -33,6 +33,15 @@ interface
 
 
     type
     type
       tcpuparamanager=class(TSparcParaManager)
       tcpuparamanager=class(TSparcParaManager)
+        procedure create_paraloc_info_intern(p : tabstractprocdef; side : tcallercallee; paras : tparalist; var curintreg : LongInt;
+          curfloatreg : tsuperregister; var cur_stack_offset : aword);override;
+        function push_addr_param(varspez : tvarspez; def : tdef; calloption : tproccalloption) : boolean;override;
+        function ret_in_param(def : tdef; pd : tabstractprocdef) : boolean;override;
+        function get_funcretloc(p : tabstractprocdef; side : tcallercallee; forcetempdef : tdef) : tcgpara;override;
+      private
+        function push_addr_param_intern(varspez : tvarspez; def : tdef; calloption : tproccalloption; recsizelimit : aword) : boolean;
+        procedure create_paraloc1_info_intern(p : tabstractprocdef; side : tcallercallee; paradef : tdef; var loc : TCGPara; varspez : tvarspez; varoptions : tvaroptions; recsizelimit : aword;
+          var curintreg : LongInt; var curfloatreg : tsuperregister; var cur_stack_offset : aword);
       end;
       end;
 
 
 implementation
 implementation
@@ -42,6 +51,314 @@ implementation
       defutil,
       defutil,
       cgobj;
       cgobj;
 
 
+    { true if a parameter is too large to copy and only the address is pushed }
+    function tcpuparamanager.push_addr_param_intern(varspez:tvarspez;def : tdef;calloption : tproccalloption;recsizelimit : aword) : boolean;
+      begin
+        result:=false;
+        { var,out,constref always require address }
+        if varspez in [vs_var,vs_out,vs_constref] then
+          begin
+            result:=true;
+            exit;
+          end;
+        case def.typ of
+          arraydef:
+            result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
+                             is_open_array(def) or
+                             is_array_of_const(def) or
+                             is_array_constructor(def);
+          recorddef:
+            result:=def.size>recsizelimit;
+          variantdef:
+            result:=false;
+          formaldef :
+            result:=true;
+          objectdef :
+            result:=(is_object(def) and (def.size>recsizelimit));
+          stringdef :
+            result:=(tstringdef(def).stringtype in [st_shortstring,st_longstring]);
+          procvardef :
+            result:=false;
+          setdef :
+            result:=not is_smallset(def);
+        end;
+      end;
+
+
+    { true if a parameter is too large to copy and only the address is pushed }
+    function tcpuparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+      begin
+        result:=push_addr_param_intern(varspez,def,calloption,16);
+      end;
+
+
+    function tcpuparamanager.ret_in_param(def:tdef;pd:tabstractprocdef):boolean;
+      begin
+        if handle_common_ret_in_param(def,pd,result) then
+          exit;
+
+        case def.typ of
+          { it is a matter of interpretation, if objects should be returned in registers according to the abi as the
+            abi talks only about structures and unions
+
+            at least for the compiler, it is a problem, if an object is returned in registers
+
+            consider
+            tobject1 = object
+              function f : tobject1;
+              ...
+              contructor init;
+            end;
+
+            the constructor changes the size of tobject1, so its return location might change from register to memory, this
+            is something the compiler could not handle currently, so we do not return objects in registers yet
+          objectdef:
+            begin
+              result:=is_object(def) and (def.size>32);
+              exit;
+            end;}
+          recorddef:
+            begin
+              result:=def.size>32;
+              exit;
+            end;
+        end;
+        result:=inherited ret_in_param(def,pd);
+      end;
+
+
+    procedure tcpuparamanager.create_paraloc1_info_intern(
+      p : tabstractprocdef; side: tcallercallee;paradef:tdef;var loc : TCGPara;varspez : tvarspez;varoptions : tvaroptions;recsizelimit : aword;
+      var curintreg: LongInt; var curfloatreg: tsuperregister; var cur_stack_offset : aword);
+
+      procedure nextloc(currsize : TCgSize);
+        begin
+          if curintreg>high(tparasupregs) then
+            begin
+              if (currsize<low(tcgsize2size)) or (currsize>high(tcgsize2size)) then
+                internalerror(2017080101);
+              { Parameters are aligned at 8 bytes }
+              inc(cur_stack_offset,align(tcgsize2size[currsize],sizeof(pint)));
+            end;
+          inc(curintreg);
+          if currsize=OS_F128 then
+            inc(curfloatreg,4)
+          else
+            inc(curfloatreg,2);
+        end;
+
+      var
+        paraloc      : pcgparalocation;
+        paracgsize   : tcgsize;
+        hparasupregs : pparasupregs;
+        paralen      : longint;
+      begin
+        if side=callerside then
+          hparasupregs:=@paraoutsupregs
+        else
+          hparasupregs:=@parainsupregs;
+        { 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:=loc.add_location;
+            { hack: the paraloc must be valid, but is not actually used }
+            paraloc^.loc:=LOC_REGISTER;
+            paraloc^.register:=NR_G0;
+            paraloc^.size:=OS_ADDR;
+            paraloc^.def:=voidpointertype;
+            exit;
+          end;
+
+        if push_addr_param_intern(varspez,paradef,p.proccalloption,recsizelimit) then
+          begin
+            paracgsize:=OS_ADDR;
+            paradef:=cpointerdef.getreusable_no_free(paradef);
+          end
+        else
+          begin
+            paracgsize:=def_cgsize(paradef);
+            if paradef.typ=formaldef then
+              begin
+                paracgsize:=OS_ADDR;
+                paradef:=voidpointertype;
+              end;
+          end;
+        loc.reset;
+        loc.size:=paracgsize;
+        loc.def:=paradef;
+        if side=callerside then
+          loc.Alignment:=std_param_align
+        else
+          loc.Alignment:=paradef.alignment;
+        { sparc64 returns records up to a size of 32 in register, we cannot encode this
+          in paracgsize, so paracgsize is OS_NO in this case }
+        if paracgsize=OS_NO then
+          paralen:=paradef.size
+        else
+          paralen:=tcgsize2size[paracgsize];
+        loc.intsize:=paralen;
+        while paralen>0 do
+          begin
+            paraloc:=loc.add_location;
+            paraloc^.size:=paracgsize;
+            paraloc^.def:=paradef;
+
+            { ret in param? }
+            if vo_is_funcret in varoptions then
+              begin
+                paraloc^.loc:=LOC_REFERENCE;
+                paraloc^.reference.offset:=128;
+                if side=callerside then
+                  paraloc^.reference.index:=NR_STACK_POINTER_REG
+                else
+                  paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+                inc(paraloc^.reference.offset,STACK_BIAS);
+              end
+            { In case of po_delphi_nested_cc, the parent frame pointer
+              is always passed on the stack. }
+            else if (curintreg<=high(tparasupregs)) and
+               (not(vo_is_parentfp in varoptions) or
+                not(po_delphi_nested_cc in p.procoptions)) then
+              begin
+                if paraloc^.size in [OS_F32,OS_F64,OS_F128] then
+                  begin
+                    paraloc^.loc:=LOC_FPUREGISTER;
+                    case paraloc^.size of
+                      OS_F32:
+                        { singles are put into the uneven register }
+                        paraloc^.register:=newreg(R_FPUREGISTER,curfloatreg+1,R_SUBFS);
+                      OS_F64:
+                        paraloc^.register:=newreg(R_FPUREGISTER,curfloatreg,R_SUBFD);
+                      OS_F128:
+                        paraloc^.register:=newreg(R_FPUREGISTER,curfloatreg,R_SUBFQ);
+                      else
+                        Internalerror(2017072301);
+                    end;
+                  end
+                else
+                  begin
+                    if paracgsize in [OS_NO,OS_128,OS_S128] then
+                      begin
+                        if paralen>4 then
+                          begin
+                            paraloc^.size:=OS_INT;
+                            paraloc^.def:=u64inttype;
+                          end
+                        else
+                          begin
+                            { for 3-byte records }
+                            paraloc^.size:=OS_32;
+                            paraloc^.def:=u32inttype;
+                          end;
+                      end;
+
+                    paraloc^.loc:=LOC_REGISTER;
+                    paraloc^.register:=newreg(R_INTREGISTER,hparasupregs^[curintreg],R_SUBWHOLE);
+                    { left align }
+                    if (target_info.endian=endian_big) and
+                       not(paraloc^.size in [OS_64,OS_S64]) and
+                       (paradef.typ in [setdef,recorddef,arraydef,objectdef]) then
+                      begin
+                        paraloc^.shiftval:=-(8-tcgsize2size[paraloc^.size])*8;
+                        paraloc^.Size:=OS_64;
+                      end;
+                  end;
+                nextloc(paraloc^.Size);
+              end
+            else
+              begin
+                paraloc^.loc:=LOC_REFERENCE;
+                paraloc^.reference.offset:=target_info.first_parm_offset+cur_stack_offset;
+                if side=callerside then
+                  paraloc^.reference.index:=NR_STACK_POINTER_REG
+                else
+                  paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+                inc(paraloc^.reference.offset,STACK_BIAS);
+
+                if (target_info.endian=endian_big) and
+                   (paralen<tcgsize2size[OS_INT]) and
+                   (paradef.typ<>recorddef) then
+                  inc(paraloc^.reference.offset,4-paralen);
+
+                { Parameters are aligned to 8 byte boundaries }
+                inc(cur_stack_offset,align(paralen,8));
+
+                { a stack location covers always the remainder of a parameter }
+                exit;
+              end;
+            dec(paralen,tcgsize2size[paraloc^.size]);
+          end;
+      end;
+
+
+    procedure tcpuparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee;paras:tparalist;
+                                                  var curintreg: LongInt; curfloatreg: tsuperregister; var cur_stack_offset : aword);
+      var
+        i : integer;
+      begin
+        for i:=0 to paras.count-1 do
+          create_paraloc1_info_intern(p,side,tparavarsym(paras[i]).vardef,tparavarsym(paras[i]).paraloc[side],tparavarsym(paras[i]).varspez,
+            tparavarsym(paras[i]).varoptions,16,curintreg,curfloatreg,cur_stack_offset);
+      end;
+
+
+    function tcpuparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
+      var
+        paraloc : pcgparalocation;
+        retcgsize  : tcgsize;
+        curintreg : LongInt;
+        curfloatreg : tsuperregister;
+        cur_stack_offset : aword;
+      begin
+        if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
+          exit;
+
+        if ret_in_param(result.def,p) then
+          Internalerror(2017080601);
+
+        if is_record(result.def) or is_object(result.def) then
+          begin
+            curintreg:=0;
+            curfloatreg:=RS_F0;
+            cur_stack_offset:=0;
+
+            create_paraloc1_info_intern(p,side,result.def,result,vs_value,
+              [],32,curintreg,curfloatreg,cur_stack_offset);
+
+            { sparc64 calling conventions are difficult, so better check if everything is ok }
+            if result.location^.loc=LOC_INVALID then
+              Internalerror(2017080501);
+          end
+        else
+          begin
+            paraloc:=result.add_location;
+            { Return in FPU register? }
+            if result.def.typ=floatdef then
+              begin
+                paraloc^.loc:=LOC_FPUREGISTER;
+                paraloc^.register:=NR_FPU_RESULT_REG;
+                if retcgsize=OS_F64 then
+                  setsubreg(paraloc^.register,R_SUBFD);
+                paraloc^.size:=retcgsize;
+                paraloc^.def:=result.def;
+              end
+            else
+             { Return in register }
+              begin
+                paraloc^.loc:=LOC_REGISTER;
+                paraloc^.size:=retcgsize;
+                paraloc^.def:=result.def;
+                if (side=callerside) then
+                  paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
+                else
+                  paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
+              end;
+          end;
+      end;
+
+
 begin
 begin
    ParaManager:=tcpuparamanager.create;
    ParaManager:=tcpuparamanager.create;
 end.
 end.

+ 24 - 254
compiler/sparcgen/sppara.pas

@@ -32,24 +32,14 @@ interface
 
 
     type
     type
       tsparcparamanager=class(TParaManager)
       tsparcparamanager=class(TParaManager)
-        function  push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
         function  get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;override;
         function  get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;override;
         function  get_volatile_registers_fpu(calloption : tproccalloption):TCpuRegisterSet;override;
         function  get_volatile_registers_fpu(calloption : tproccalloption):TCpuRegisterSet;override;
         function  create_paraloc_info(p : TAbstractProcDef; side: tcallercallee):longint;override;
         function  create_paraloc_info(p : TAbstractProcDef; side: tcallercallee):longint;override;
         function  create_varargs_paraloc_info(p : TAbstractProcDef; varargspara:tvarargsparalist):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 create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
         procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
-                                             var intparareg,parasize:longint);
+                                             var curintreg: longint; curfloatreg: tsuperregister; var cur_stack_offset: aword);virtual;abstract;
       end;
       end;
 
 
-implementation
-
-    uses
-      cutils,verbose,systems,
-      defutil,
-      cgobj;
-
     type
     type
       tparasupregs = array[0..5] of tsuperregister;
       tparasupregs = array[0..5] of tsuperregister;
       pparasupregs = ^tparasupregs;
       pparasupregs = ^tparasupregs;
@@ -57,6 +47,12 @@ implementation
       paraoutsupregs : tparasupregs = (RS_O0,RS_O1,RS_O2,RS_O3,RS_O4,RS_O5);
       paraoutsupregs : tparasupregs = (RS_O0,RS_O1,RS_O2,RS_O3,RS_O4,RS_O5);
       parainsupregs  : tparasupregs = (RS_I0,RS_I1,RS_I2,RS_I3,RS_I4,RS_I5);
       parainsupregs  : tparasupregs = (RS_I0,RS_I1,RS_I2,RS_I3,RS_I4,RS_I5);
 
 
+implementation
+
+    uses
+      cutils,verbose,systems,
+      defutil,
+      cgobj;
 
 
     function tsparcparamanager.get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;
     function tsparcparamanager.get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;
       begin
       begin
@@ -70,263 +66,37 @@ implementation
       end;
       end;
 
 
 
 
-    { true if a parameter is too large to copy and only the address is pushed }
-    function tsparcparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
-      begin
-        result:=false;
-        { var,out,constref always require address }
-        if varspez in [vs_var,vs_out,vs_constref] then
-          begin
-            result:=true;
-            exit;
-          end;
-        case def.typ of
-          arraydef:
-            result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
-                             is_open_array(def) or
-                             is_array_of_const(def) or
-                             is_array_constructor(def);
-          recorddef,
-          variantdef,
-          formaldef :
-            result:=true;
-          objectdef :
-            result:=is_object(def);
-          stringdef :
-            result:=(tstringdef(def).stringtype in [st_shortstring,st_longstring]);
-          procvardef :
-            result:=not tprocvardef(def).is_addressonly;
-          setdef :
-            result:=not is_smallset(def);
-        end;
-      end;
-
-
-    function tsparcparamanager.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
-            paraloc^.loc:=LOC_FPUREGISTER;
-            paraloc^.register:=NR_FPU_RESULT_REG;
-            if retcgsize=OS_F64 then
-              setsubreg(paraloc^.register,R_SUBFD);
-            paraloc^.size:=retcgsize;
-            paraloc^.def:=result.def;
-          end
-        else
-         { Return in register }
-          begin
-{$ifndef cpu64bitaddr}
-            if retcgsize in [OS_64,OS_S64] then
-             begin
-               paraloc^.loc:=LOC_REGISTER;
-               { high }
-               if side=callerside then
-                 paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
-               else
-                 paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
-               paraloc^.size:=OS_32;
-               paraloc^.def:=u32inttype;
-               { low }
-               paraloc:=result.add_location;
-               paraloc^.loc:=LOC_REGISTER;
-               if side=callerside then
-                 paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
-               else
-                 paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
-               paraloc^.size:=OS_32;
-               paraloc^.def:=u32inttype;
-             end
-            else
-{$endif not cpu64bitaddr}
-             begin
-               paraloc^.loc:=LOC_REGISTER;
-               paraloc^.size:=retcgsize;
-               paraloc^.def:=result.def;
-               if (side=callerside) then
-                 paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
-               else
-                 paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
-             end;
-          end;
-      end;
-
-
-    procedure tsparcparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee;paras:tparalist;
-                                                           var intparareg,parasize:longint);
-      var
-        paraloc      : pcgparalocation;
-        i            : integer;
-        hp           : tparavarsym;
-        paradef      : tdef;
-        paracgsize   : tcgsize;
-        hparasupregs : pparasupregs;
-        paralen      : longint;
-      begin
-        if side=callerside then
-          hparasupregs:=@paraoutsupregs
-        else
-          hparasupregs:=@parainsupregs;
-        for i:=0 to paras.count-1 do
-          begin
-            hp:=tparavarsym(paras[i]);
-            paradef:=hp.vardef;
-            { 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_G0;
-                paraloc^.size:=OS_ADDR;
-                paraloc^.def:=voidpointertype;
-                break;
-              end;
-
-            if push_addr_param(hp.varspez,paradef,p.proccalloption) then
-              begin
-                paracgsize:=OS_ADDR;
-                paradef:=cpointerdef.getreusable_no_free(paradef);
-              end
-            else
-              begin
-                paracgsize:=def_cgsize(paradef);
-                { for formaldef }
-                if paracgsize=OS_NO then
-                  begin
-                    paracgsize:=OS_ADDR;
-                    paradef:=voidpointertype;
-                  end;
-              end;
-            hp.paraloc[side].reset;
-            hp.paraloc[side].size:=paracgsize;
-            hp.paraloc[side].def:=paradef;
-            if (side = callerside) then
-              hp.paraloc[side].Alignment:=std_param_align
-            else
-              hp.paraloc[side].Alignment:=paradef.alignment;
-            paralen:=tcgsize2size[paracgsize];
-            hp.paraloc[side].intsize:=paralen;
-            while paralen>0 do
-              begin
-                paraloc:=hp.paraloc[side].add_location;
-{$ifdef SPARC64}
-                { Floats are passed in int registers }
-                if paracgsize=OS_F32 then
-                  begin
-                    paraloc^.size:=OS_32;
-                    paraloc^.def:=u32inttype;
-                  end
-                else if paracgsize=OS_F64 then
-                  begin
-                    paraloc^.size:=OS_64;
-                    paraloc^.def:=u64inttype;
-                  end
-                else
-{$else SPARC64}
-                { Floats are passed in int registers,
-                  We can allocate at maximum 32 bits per register }
-                if paracgsize in [OS_64,OS_S64,OS_F32,OS_F64] then
-                  begin
-                    paraloc^.size:=OS_32;
-                    paraloc^.def:=u32inttype;
-                  end
-                else
-{$endif SPARC64}
-                  begin
-                    paraloc^.size:=paracgsize;
-                    paraloc^.def:=paradef;
-                  end;
-                { ret in param? }
-                if vo_is_funcret in hp.varoptions then
-                  begin
-                    paraloc^.loc:=LOC_REFERENCE;
-{$ifdef SPARC64}
-                    paraloc^.reference.offset:=128;
-{$else SPARC64}
-                    paraloc^.reference.offset:=64;
-{$endif SPARC64}
-                    if side=callerside then
-                      paraloc^.reference.index:=NR_STACK_POINTER_REG
-                    else
-                      paraloc^.reference.index:=NR_FRAME_POINTER_REG;
-{$ifdef SPARC64}
-                    inc(paraloc^.reference.offset,STACK_BIAS);
-{$endif SPARC64}
-                  end
-                { In case of po_delphi_nested_cc, the parent frame pointer
-                  is always passed on the stack. }
-                else if (intparareg<=high(tparasupregs)) 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,hparasupregs^[intparareg],R_SUBWHOLE);
-                    inc(intparareg);
-                  end
-                else
-                  begin
-                    paraloc^.loc:=LOC_REFERENCE;
-                    paraloc^.reference.offset:=target_info.first_parm_offset+parasize;
-                    if side=callerside then
-                      paraloc^.reference.index:=NR_STACK_POINTER_REG
-                    else
-                      paraloc^.reference.index:=NR_FRAME_POINTER_REG;
-{$ifdef SPARC64}
-                    inc(paraloc^.reference.offset,STACK_BIAS);
-{$endif SPARC64}
-                    if (target_info.endian=endian_big) and
-                       (paralen<tcgsize2size[OS_INT]) and
-                       (paradef.typ<>recorddef) then
-                      inc(paraloc^.reference.offset,4-paralen);
-
-                    { Parameters are aligned at 4 bytes }
-                    inc(parasize,align(tcgsize2size[paraloc^.size],sizeof(pint)));
-                  end;
-                dec(paralen,tcgsize2size[paraloc^.size]);
-              end;
-          end;
-      end;
-
-
     function tsparcparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
     function tsparcparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
       var
       var
-        intparareg,
-        parasize : longint;
+        curintreg : LongInt;
+        curfloatreg : TSuperRegister;
+        cur_stack_offset : aword;
       begin
       begin
-        intparareg:=0;
-        parasize:=0;
+        curintreg:=0;
+        curfloatreg:=RS_F0;
+        cur_stack_offset:=0;
         { calculate the registers for the normal parameters }
         { calculate the registers for the normal parameters }
-        create_paraloc_info_intern(p,callerside,p.paras,intparareg,parasize);
+        create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,cur_stack_offset);
         { append the varargs }
         { append the varargs }
-        create_paraloc_info_intern(p,callerside,varargspara,intparareg,parasize);
-        result:=parasize;
+        create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,cur_stack_offset);
+        result:=cur_stack_offset;
       end;
       end;
 
 
 
 
-
     function tsparcparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
     function tsparcparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
       var
       var
-        intparareg,
-        parasize : longint;
+        curintreg : LongInt;
+        curfloatreg : TSuperRegister;
+        cur_stack_offset : aword;
       begin
       begin
-        intparareg:=0;
-        parasize:=0;
-        create_paraloc_info_intern(p,side,p.paras,intparareg,parasize);
+        curintreg:=0;
+        curfloatreg:=RS_F0;
+        cur_stack_offset:=0;
+        create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,cur_stack_offset);
         { Create Function result paraloc }
         { Create Function result paraloc }
         create_funcretloc_info(p,side);
         create_funcretloc_info(p,side);
         { We need to return the size allocated on the stack }
         { We need to return the size allocated on the stack }
-        result:=parasize;
+        result:=cur_stack_offset;
       end;
       end;