瀏覽代碼

* Stack setup for MIPS and MIPSEL

git-svn-id: trunk@21537 -
pierre 13 年之前
父節點
當前提交
22eae1b337
共有 2 個文件被更改,包括 106 次插入42 次删除
  1. 94 41
      compiler/mips/cpupara.pas
  2. 12 1
      compiler/mips/cpupi.pas

+ 94 - 41
compiler/mips/cpupara.pas

@@ -30,8 +30,25 @@ interface
       cpubase,cpuinfo,
       symconst,symbase,symsym,symtype,symdef,paramgr,parabase,cgbase;
 
+    const
+      MIPS_MAX_OFFSET = 20;
+      MIPS_MAX_REGISTERS_USED_IN_CALL = 6;
+      MIPS_FIRST_REGISTER_USED_IN_CALL = RS_R4;
+    type
+      tparasupregs = array[0..MIPS_MAX_REGISTERS_USED_IN_CALL-1] of tsuperregister;
+      tparasupregsused = array[0..MIPS_MAX_REGISTERS_USED_IN_CALL-1] of boolean;
+      tparasupregsoffset = array[0..MIPS_MAX_REGISTERS_USED_IN_CALL-1] of longint;
+      pparasupregs = ^tparasupregs;
+    const
+      paraoutsupregs : tparasupregs = (RS_R4, RS_R5, RS_R6, RS_R7, RS_R8, RS_R9);
+      parainsupregs  : tparasupregs = (RS_R4, RS_R5, RS_R6, RS_R7, RS_R8, RS_R9);
+
     type
       TMIPSParaManager=class(TParaManager)
+      var
+        param_offset:array[0..MIPS_MAX_OFFSET] of ^Aint;
+        intparareg,
+        parasize : longint;
         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_fpu(calloption : tproccalloption):TCpuRegisterSet;override;
@@ -44,23 +61,16 @@ interface
         function  get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;override;
       private
         procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
-        procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
-                                             var intparareg,parasize:longint);
+        procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist);
       end;
 
 implementation
 
     uses
       cutils,verbose,systems,
-      defutil,
+      defutil, cpupi, procinfo,
       cgutils,cgobj;
 
-    type
-      tparasupregs = array[0..5] of tsuperregister;
-      pparasupregs = ^tparasupregs;
-    const
-      paraoutsupregs : tparasupregs = (RS_R4, RS_R5, RS_R6, RS_R7, RS_R8, RS_R9);
-      parainsupregs  : tparasupregs = (RS_R4, RS_R5, RS_R6, RS_R7, RS_R8, RS_R9);
 
 
     function TMIPSParaManager.get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;
@@ -90,17 +100,22 @@ implementation
           begin
             { The six first parameters are passed into registers } {MIPS first four}
             dec(nr);
-            if nr<6 then //MIPSEL nr<6
+            if nr<MIPS_MAX_REGISTERS_USED_IN_CALL then //MIPSEL nr<6
               begin
                 loc:=LOC_REGISTER;
-                register:=newreg(R_INTREGISTER,(RS_R4+nr),R_SUBWHOLE);
+                register:=newreg(R_INTREGISTER,paraoutsupregs[nr],R_SUBWHOLE);
+                if assigned(current_procinfo) then
+                  begin
+                    TMIPSProcInfo(current_procinfo).register_used[nr]:=true;
+                    TMIPSProcInfo(current_procinfo).register_offset[nr]:=nr*4;
+                  end;
               end
             else
               begin
                 { The other parameters are passed on the stack }
                 loc:=LOC_REFERENCE;
                 reference.index:=NR_STACK_POINTER_REG;
-                reference.offset:=92+(nr-6)*4;
+                reference.offset:={92+(nr-6)*4;} nr*4;
               end;
             size:=OS_INT;
           end;
@@ -169,12 +184,26 @@ implementation
             result.intsize:=def.size;
           end;
         result.size:=retcgsize;
-        { Return is passed as var parameter }
+        { Return is passed as var parameter,
+          in this case we use the first register R4 for it }
         if ret_in_param(def,p.proccalloption) then
           begin
-            paraloc:=result.add_location;
-            paraloc^.loc:=LOC_REFERENCE;
-            paraloc^.size:=retcgsize;
+            { Reserve first register for ret_in_param }
+            if intparareg=0 then
+              inc(intparareg);
+            if side=calleeside then
+              begin
+                paraloc:=result.add_location;
+                paraloc^.loc:=LOC_REFERENCE;
+                paraloc^.reference.index:=NR_STACK_POINTER_REG;
+                { return is at offset zero }
+                paraloc^.reference.offset:=0;
+                paraloc^.size:=retcgsize;
+              end
+            else
+              begin
+                getIntParaLoc(p.proccalloption,1,result);
+              end;
             exit;
           end;
 
@@ -223,11 +252,8 @@ implementation
           end
       end;
 
-    var
-      param_offset:array[0..20] of ^Aint;
 
-    procedure TMIPSParaManager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee;paras:tparalist;
-                                                           var intparareg,parasize:longint);
+    procedure TMIPSParaManager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee;paras:tparalist);
       var
         paraloc      : pcgparalocation;
         i            : integer;
@@ -242,8 +268,8 @@ implementation
           hparasupregs:=@parainsupregs;
         for i:=0 to paras.count-1 do
           begin
-
-            param_offset[i] := Nil;
+            if i<=MIPS_MAX_OFFSET then
+              param_offset[i] := Nil;
             hp:=tparavarsym(paras[i]);
             { currently only support C-style array of const,
               there should be no location assigned to the vararg array itself }
@@ -283,17 +309,26 @@ implementation
                 { ret in param? }
                 if vo_is_funcret in hp.varoptions then
                   begin
-                    paraloc^.loc:=LOC_REFERENCE;
+                    { This should be the first parameter }
+                    if assigned(current_procinfo) then
+                      begin
+                        TMIPSProcInfo(current_procinfo).register_used[0]:=true;
+                        TMIPSProcInfo(current_procinfo).register_offset[0]:=0;
+                      end;
+                    //if (intparareg<>1) then
+                    //  Comment(V_Warning,'intparareg should be one for funcret in TMipsParaManager.create_paraloc_info_intern');
                     if side=callerside then
                     begin
-                      paraloc^.reference.index := NR_STACK_POINTER_REG;
-                      paraloc^.reference.offset:=parasize;
+                      paraloc^.loc:=LOC_REGISTER;
+                      paraloc^.register:=newreg(R_INTREGISTER,hparasupregs^[0],R_SUBWHOLE);
                     end
                     else
                     begin
+                      paraloc^.loc:=LOC_REFERENCE;
                       paraloc^.reference.index := NR_FRAME_POINTER_REG;
-                      paraloc^.reference.offset:=target_info.first_parm_offset+parasize;
-                      param_offset[i] := @paraloc^.reference.offset;
+                      paraloc^.reference.offset:=0;
+                      if i<=MIPS_MAX_OFFSET then
+                        param_offset[i] := @paraloc^.reference.offset;
                     end;
                     inc(parasize,align(tcgsize2size[paraloc^.size],sizeof(aint)));
                   end
@@ -303,9 +338,27 @@ implementation
                    (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);
+                    if assigned(current_procinfo) then
+                      begin
+                        TMIPSProcInfo(current_procinfo).register_used[intparareg]:=true;
+                        TMIPSProcInfo(current_procinfo).register_offset[intparareg]:=intparareg*4;
+                      end;
+                    if side=callerside then
+                      begin
+                        paraloc^.loc:=LOC_REGISTER;
+                        paraloc^.register:=newreg(R_INTREGISTER,hparasupregs^[intparareg],R_SUBWHOLE);
+                      end
+                    else
+                      begin
+                        paraloc^.loc:=LOC_REFERENCE;
+                        //if assigned(current_procinfo) then
+                        //  paraloc^.reference.index := current_procinfo.framepointer
+                        //else
+                          paraloc^.reference.index := NR_FRAME_POINTER_REG;
+                        paraloc^.reference.offset:=intparareg*sizeof(aint);
+                      end;
                     inc(intparareg);
+                    inc(parasize,align(tcgsize2size[paraloc^.size],sizeof(aint)));
                   end
                 else
                   begin
@@ -317,9 +370,13 @@ implementation
                       end
                     else
                       begin
-                        paraloc^.reference.index := {NR_R18;//}NR_FRAME_POINTER_REG;
-                        paraloc^.reference.offset:=target_info.first_parm_offset+parasize;
-                        param_offset[i] := @paraloc^.reference.offset;
+                        //if assigned(current_procinfo) then
+                        //  paraloc^.reference.index := current_procinfo.framepointer
+                        //else
+                          paraloc^.reference.index := {NR_R18;//}NR_FRAME_POINTER_REG;
+                        paraloc^.reference.offset:=parasize;
+                        if i<=MIPS_MAX_OFFSET then
+                          param_offset[i] := @paraloc^.reference.offset;
                       end;
                     { Parameters are aligned at 4 bytes }
                     inc(parasize,align(tcgsize2size[paraloc^.size],sizeof(aint)));
@@ -338,31 +395,27 @@ implementation
 
 
     function TMIPSParaManager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
-      var
-        intparareg,
-        parasize : longint;
       begin
         intparareg:=0;
         parasize:=0;
+        { Create Function result paraloc }
+        create_funcretloc_info(p,callerside);
         { 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);
         { append the varargs }
-        create_paraloc_info_intern(p,callerside,varargspara,intparareg,parasize);
+        create_paraloc_info_intern(p,callerside,varargspara);
         result:=parasize;
       end;
 
 
 
     function TMIPSParaManager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
-      var
-        intparareg,
-        parasize : longint;
       begin
         intparareg:=0;
         parasize:=0;
-        create_paraloc_info_intern(p,side,p.paras,intparareg,parasize);
         { Create Function result paraloc }
         create_funcretloc_info(p,side);
+        create_paraloc_info_intern(p,side,p.paras);
         { We need to return the size allocated on the stack }
         result:=parasize;
       end;

+ 12 - 1
compiler/mips/cpupi.pas

@@ -28,7 +28,7 @@ interface
   uses
     cutils,
     globtype,
-    procinfo,cpuinfo,
+    procinfo,cpuinfo,cpupara,
     psub;
 
   type
@@ -40,6 +40,8 @@ interface
       floatregstart : aint;
       intregssave,
       floatregssave : byte;
+      register_used : tparasupregsused;
+      register_offset : tparasupregsoffset;
       constructor create(aparent:tprocinfo);override;
       function calc_stackframe_size:longint;override;
       procedure set_first_temp_offset;override;
@@ -53,8 +55,16 @@ implementation
       tgobj,paramgr,symconst;
 
     constructor TMIPSProcInfo.create(aparent: tprocinfo);
+      var
+        i : longint;
       begin
         inherited create(aparent);
+        for i:=low(tparasupregs)  to high(tparasupregs) do
+          begin
+            register_used[i]:=false;
+            register_offset[i]:=-1;
+          end;
+
         floatregssave:=11;
         intregssave:=10;
       end;
@@ -81,6 +91,7 @@ implementation
         floatregstart:=result;
         inc(result,floatregssave*4);
         intregstart:=result;
+        inc(result,intregssave*4);
         result:=Align(tg.lasttemp,max(current_settings.alignment.localalignmin,8));
       end;