Browse Source

* 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 -

sergei 12 years ago
parent
commit
d82387ff72
2 changed files with 26 additions and 61 deletions
  1. 7 58
      compiler/mips/cgcpu.pas
  2. 19 3
      compiler/mips/cpupara.pas

+ 7 - 58
compiler/mips/cgcpu.pas

@@ -49,8 +49,6 @@ type
     procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
     procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
 
 
     { parameter }
     { 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_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_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;
     procedure a_loadfpu_ref_cgpara(list: tasmlist; size: tcgsize; const ref: treference; const paraloc: TCGPara); override;
@@ -543,60 +541,6 @@ begin
 end;
 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);
 procedure TCGMIPS.a_loadaddr_ref_cgpara(list: tasmlist; const r: TReference; const paraloc: TCGPara);
 var
 var
   Ref:    TReference;
   Ref:    TReference;
@@ -630,6 +574,9 @@ var
   href, href2: treference;
   href, href2: treference;
   hloc: pcgparalocation;
   hloc: pcgparalocation;
 begin
 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;
   href := ref;
   hloc := paraloc.location;
   hloc := paraloc.location;
   while assigned(hloc) do
   while assigned(hloc) do
@@ -642,8 +589,10 @@ begin
         a_loadfpu_ref_reg(list,hloc^.size,hloc^.size,href,hloc^.register);
         a_loadfpu_ref_reg(list,hloc^.size,hloc^.size,href,hloc^.register);
       LOC_REFERENCE:
       LOC_REFERENCE:
         begin
         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;
         end;
       else
       else
         internalerror(200408241);
         internalerror(200408241);

+ 19 - 3
compiler/mips/cpupara.pas

@@ -384,6 +384,17 @@ implementation
                   paraloc^.size:=OS_32
                   paraloc^.size:=OS_32
                 else
                 else
                   paraloc^.size:=paracgsize;
                   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? }
                 { ret in param? }
                 if (vo_is_funcret in hp.varoptions) and
                 if (vo_is_funcret in hp.varoptions) and
                   is_abi_record(hp.vardef) then
                   is_abi_record(hp.vardef) then
@@ -393,7 +404,7 @@ implementation
                       begin
                       begin
                         TMIPSProcInfo(current_procinfo).register_used[0]:=true;
                         TMIPSProcInfo(current_procinfo).register_used[0]:=true;
                         TMIPSProcInfo(current_procinfo).register_name[0]:='result';
                         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;
                         TMIPSProcInfo(current_procinfo).register_offset[0]:=0;
                       end;
                       end;
                     //if (intparareg<>1) then
                     //if (intparareg<>1) then
@@ -453,7 +464,7 @@ implementation
                          begin
                          begin
                            TMIPSProcInfo(current_procinfo).register_used[intparareg]:=true;
                            TMIPSProcInfo(current_procinfo).register_used[intparareg]:=true;
                            TMIPSProcInfo(current_procinfo).register_name[intparareg]:=hp.prettyname;
                            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;
                            TMIPSProcInfo(current_procinfo).register_offset[intparareg]:=intparareg*mips_sizeof_register_param;
                          end;
                          end;
                        if side=callerside then
                        if side=callerside then
@@ -481,14 +492,18 @@ implementation
                 else
                 else
                   begin
                   begin
                     paraloc^.loc:=LOC_REFERENCE;
                     paraloc^.loc:=LOC_REFERENCE;
+                    paraloc^.size:=int_cgsize(paralen);
+
                     { Force size to multiple of 4 for records passed by value,
                     { Force size to multiple of 4 for records passed by value,
                       to obtain correct memory layout for big endian }
                       to obtain correct memory layout for big endian }
+(*
                     if (paradef.typ = recorddef) and 
                     if (paradef.typ = recorddef) and 
                        (tcgsize2size[paraloc^.size] < tcgsize2size[OS_32]) then
                        (tcgsize2size[paraloc^.size] < tcgsize2size[OS_32]) then
                       begin
                       begin
                         inc(paralen,tcgsize2size[OS_32]-tcgsize2size[paraloc^.size]);
                         inc(paralen,tcgsize2size[OS_32]-tcgsize2size[paraloc^.size]);
                         paraloc^.size := OS_32;
                         paraloc^.size := OS_32;
                       end;
                       end;
+*)
                     if side=callerside then
                     if side=callerside then
                       begin
                       begin
                         paraloc^.reference.index := NR_STACK_POINTER_REG;
                         paraloc^.reference.index := NR_STACK_POINTER_REG;
@@ -506,7 +521,8 @@ implementation
                           end;
                           end;
                         paraloc^.reference.offset:=intparasize;
                         paraloc^.reference.offset:=intparasize;
                       end;
                       end;
-                    inc(intparasize,align(tcgsize2size[paraloc^.size],mips_sizeof_register_param));
+                    inc(intparasize,align(paralen,mips_sizeof_register_param));
+                    paralen:=0;
                   end;
                   end;
                 dec(paralen,tcgsize2size[paraloc^.size]);
                 dec(paralen,tcgsize2size[paraloc^.size]);
               end;
               end;