Prechádzať zdrojové kódy

* macos entry/exit: only used registers are saved
- macos entry/exit: stackptr not saved in r31 anymore
* macos entry/exit: misc fixes

olle 23 rokov pred
rodič
commit
b71c1492a9
1 zmenil súbory, kde vykonal 163 pridanie a 50 odobranie
  1. 163 50
      compiler/powerpc/cgcpu.pas

+ 163 - 50
compiler/powerpc/cgcpu.pas

@@ -1110,49 +1110,146 @@ const
           end;
       end;
 
-    const
-      macosLinkageAreaSize = 24;
-      registerSaveAreaMaxSize = 19*4 + 18*8;
+    function save_regs(list : taasmoutput):longint;
+    {Generates code which saves used non-volatile registers in
+     the save area right below the address the stackpointer point to.
+     Returns the actual used save area size.}
 
-    procedure save_fp_regs(list : taasmoutput);
-
-     var regcounter: TRegister;
+     var regcounter,firstregfpu,firstreggpr: TRegister;
+         usesfpr,usesgpr: boolean;
          href : treference;
          offset: integer;
 
     begin
+      usesfpr:=false;
+      for regcounter:=R_F14 to R_F31 do
+        if regcounter in rg.usedbyproc then
+          begin
+             usesfpr:=true;
+             firstregfpu:=regcounter;
+             break;
+          end;
+
+      usesgpr:=false;
+      for regcounter:=R_13 to R_31 do
+        if regcounter in rg.usedbyproc then
+          begin
+             usesgpr:=true;
+             firstreggpr:=regcounter;
+             break;
+          end;
+
       offset:= 0;
-      for regcounter := R_F14 to R_F31 do
-        begin
-          offset:= offset - 8;
-          reference_reset_base(href, STACK_POINTER_REG, offset);
-          list.concat(taicpu.op_reg_ref(A_STFD, regcounter, href));
-        end;
+
+      { save floating-point registers }
+      if usesfpr then
+        for regcounter := firstregfpu to R_F31 do
+          begin
+            offset:= offset - 8;
+            reference_reset_base(href, STACK_POINTER_REG, offset);
+            list.concat(taicpu.op_reg_ref(A_STFD, regcounter, href));
+          end;
+        (* Optimiztion in the future:  a_call_name(list,'_savefXX'); *)
+
+      { save gprs in gpr save area }
+      if usesgpr then
+        if firstreggpr < R_30 then
+          begin
+            offset:= offset - 4 * (ord(R_31) - ord(firstreggpr) + 1);
+            reference_reset_base(href,STACK_POINTER_REG,offset);
+            list.concat(taicpu.op_reg_ref(A_STMW,firstreggpr,href));
+              {STMW stores multiple registers}
+          end
+        else
+          begin
+            for regcounter := firstreggpr to R_31 do
+              begin
+                offset:= offset - 4;
+                reference_reset_base(href, STACK_POINTER_REG, offset);
+                list.concat(taicpu.op_reg_ref(A_STW, regcounter, href));
+              end;
+          end;
+
+      { now comes the AltiVec context save, not yet implemented !!! }
+
+      save_regs:= -offset;
     end;
 
-    procedure restore_fp_regs(list : taasmoutput);
+    procedure restore_regs(list : taasmoutput);
+    {Generates code which restores used non-volatile registers from
+    the save area right below the address the stackpointer point to.}
 
-     var regcounter: TRegister;
+     var regcounter,firstregfpu,firstreggpr: TRegister;
+         usesfpr,usesgpr: boolean;
          href : treference;
          offset: integer;
 
     begin
+      usesfpr:=false;
+      for regcounter:=R_F14 to R_F31 do
+        if regcounter in rg.usedbyproc then
+          begin
+             usesfpr:=true;
+             firstregfpu:=regcounter;
+             break;
+          end;
+
+      usesgpr:=false;
+      for regcounter:=R_13 to R_31 do
+        if regcounter in rg.usedbyproc then
+          begin
+             usesgpr:=true;
+             firstreggpr:=regcounter;
+             break;
+          end;
+
       offset:= 0;
-      for regcounter := R_F14 to R_F31 do
-        begin
-          offset:= offset - 8;
-          reference_reset_base(href, STACK_POINTER_REG, offset);
-          list.concat(taicpu.op_reg_ref(A_LFD, regcounter, href));
-        end;
+
+      { restore fp registers }
+      if usesfpr then
+        for regcounter := firstregfpu to R_F31 do
+          begin
+            offset:= offset - 8;
+            reference_reset_base(href, STACK_POINTER_REG, offset);
+            list.concat(taicpu.op_reg_ref(A_LFD, regcounter, href));
+          end;
+        (* Optimiztion in the future: a_call_name(list,'_restfXX'); *)
+
+      { restore gprs }
+      if usesgpr then
+        if firstreggpr < R_30 then
+          begin
+            offset:= offset - 4 * (ord(R_31) - ord(firstreggpr) + 1);
+            reference_reset_base(href,STACK_POINTER_REG,offset); //-220
+            list.concat(taicpu.op_reg_ref(A_LMW,firstreggpr,href));
+              {LMW loads multiple registers}
+          end
+        else
+          begin
+            for regcounter := firstreggpr to R_31 do
+              begin
+                offset:= offset - 4;
+                reference_reset_base(href, STACK_POINTER_REG, offset);
+                list.concat(taicpu.op_reg_ref(A_LWZ, regcounter, href));
+              end;
+          end;
+
+      { now comes the AltiVec context restore, not yet implemented !!! }
     end;
 
+
     procedure tcgppc.g_stackframe_entry_mac(list : taasmoutput;localsize : longint);
  { generated the entry code of a procedure/function. Note: localsize is the }
  { sum of the size necessary for local variables and the maximum possible   }
  { combined size of ALL the parameters of a procedure called by the current }
- { one                                                                      }
+ { one                                                                     }
+
+     const
+         macosLinkageAreaSize = 24;
+
      var regcounter: TRegister;
          href : treference;
+         registerSaveAreaSize : longint;
 
       begin
         if (localsize mod 8) <> 0 then internalerror(58991);
@@ -1162,35 +1259,33 @@ const
         { Interface Manual", bar the saving of AltiVec registers           }
         a_reg_alloc(list,STACK_POINTER_REG);
         a_reg_alloc(list,R_0);
+
         { allocate registers containing reg parameters }
         for regcounter := R_3 to R_10 do
           a_reg_alloc(list,regcounter);
+        {TODO: Allocate fp and altivec parameter registers also}
 
-        { save return address... }
+        { save return address in callers frame}
         list.concat(taicpu.op_reg_reg(A_MFSPR,R_0,R_LR));
         { ... in caller's frame }
         reference_reset_base(href,STACK_POINTER_REG,8);
         list.concat(taicpu.op_reg_ref(A_STW,R_0,href));
         a_reg_dealloc(list,R_0);
 
-        { save floating-point registers }
-        { !!! has to be optimized: only save registers that are used }
-        save_fp_regs(list);
-        (* a_call_name(list,'_savef14'); *)
-        { save gprs in gpr save area }
-        { !!! has to be optimized: only save registers that are used }
-        reference_reset_base(href,STACK_POINTER_REG,-220);
-        list.concat(taicpu.op_reg_ref(A_STMW,R_13,href));
+        { save non-volatile registers in callers frame}
+        registerSaveAreaSize:= save_regs(list);
 
-        { save the CR if necessary ( !!! always done currently ) }
+        { save the CR if necessary in callers frame ( !!! always done currently ) }
         a_reg_alloc(list,R_0);
         list.concat(taicpu.op_reg_reg(A_MFSPR,R_0,R_CR));
         reference_reset_base(href,stack_pointer_reg,LA_CR);
         list.concat(taicpu.op_reg_ref(A_STW,R_0,href));
         a_reg_dealloc(list,R_0);
 
+        (*
         { save pointer to incoming arguments }
         list.concat(taicpu.op_reg_reg_const(A_ORI,R_31,STACK_POINTER_REG,0));
+        *)
 
         (*
         a_reg_alloc(list,R_12);
@@ -1208,12 +1303,14 @@ const
         *)
 
         { allocate stack frame }
-        localsize:= align(localsize + macosLinkageAreaSize + registerSaveAreaMaxSize, 16);
+        localsize:= align(localsize + macosLinkageAreaSize + registerSaveAreaSize, 16);
+        inc(localsize,tg.lasttemp);
+        localsize:=align(localsize,16);
+        tppcprocinfo(procinfo).localsize:=localsize;
+
         reference_reset_base(href,R_1,-localsize);
         a_load_store(list,A_STWU,R_1,href);
-
-
-        { now comes the AltiVec context save, not yet implemented !!! }
+          { this also stores the old stack pointer in the new stack frame }
       end;
 
     procedure tcgppc.g_return_from_proc_mac(list : taasmoutput;parasize : aword);
@@ -1225,31 +1322,42 @@ const
         { release parameter registers }
         for regcounter := R_3 to R_10 do
           a_reg_dealloc(list,regcounter);
-        { AltiVec context restore, not yet implemented !!! }
+        {TODO: Release fp and altivec parameter registers also}
+
+        a_reg_alloc(list,R_0);
 
-        { restore SP }
+        { restore stack pointer }
+        reference_reset_base(href,stack_pointer_reg,LA_SP);
+        list.concat(taicpu.op_reg_ref(A_LWZ,STACK_POINTER_REG,href));
+        (*
         list.concat(taicpu.op_reg_reg_const(A_ORI,STACK_POINTER_REG,R_31,0));
+        *)
 
-        { restore the CR if necessary ( !!! always done currently ) }
-        a_reg_alloc(list,R_0);
-        list.concat(taicpu.op_reg_reg(A_MTSPR,R_0,R_CR));
-        reference_reset_base(href,stack_pointer_reg,LA_CR);
+        { restore the CR if necessary from callers frame
+            ( !!! always done currently ) }
+        reference_reset_base(href,STACK_POINTER_REG,LA_CR);
         list.concat(taicpu.op_reg_ref(A_LWZ,R_0,href));
+        list.concat(taicpu.op_reg_reg(A_MTSPR,R_0,R_CR));
         a_reg_dealloc(list,R_0);
-        { restore gprs }
-        reference_reset_base(href,STACK_POINTER_REG,-220);
-        list.concat(taicpu.op_reg_ref(A_LMW,R_13,href));
-        { restore return address ... }
+
+        (*
+        { restore return address from callers frame }
         reference_reset_base(href,STACK_POINTER_REG,8);
         list.concat(taicpu.op_reg_ref(A_LWZ,R_0,href));
+        *)
+
+        { restore non-volatile registers from callers frame }
+        restore_regs(list);
 
         (*
-        { ... and return from _restf14 }
-        list.concat(taicpu.op_sym_ofs(A_B,objectlibrary.newasmsymbol('_restf14'),0));
+        { return to caller }
+        list.concat(taicpu.op_reg_reg(A_MTSPR,R_0,R_LR));
+        list.concat(taicpu.op_none(A_BLR));
         *)
 
-        { restore fp registers }
-        restore_fp_regs(list);
+        { restore return address from callers frame }
+        reference_reset_base(href,STACK_POINTER_REG,8);
+        list.concat(taicpu.op_reg_ref(A_LWZ,R_0,href));
 
         { return to caller }
         list.concat(taicpu.op_reg_reg(A_MTSPR,R_0,R_LR));
@@ -1770,7 +1878,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.62  2002-10-19 23:51:48  olle
+  Revision 1.63  2002-10-28 22:24:28  olle
+    * macos entry/exit: only used registers are saved
+    - macos entry/exit: stackptr not saved in r31 anymore
+    * macos entry/exit: misc fixes
+
+  Revision 1.62  2002/10/19 23:51:48  olle
     * macos stack frame size computing updated
     + macos epilogue: control register now restored
     * macos prologue and epilogue: fp reg now saved and restored