Browse Source

+ entry/exitcode for SystemV (Linux) and AIX/Mac from the Altivec
PIM (no AltiVec support yet though)
* small fix to the a_cmp_* methods

Jonas Maebe 26 years ago
parent
commit
9feb0d4b0e
1 changed files with 173 additions and 73 deletions
  1. 173 73
      compiler/new/powerpc/cgcpu.pas

+ 173 - 73
compiler/new/powerpc/cgcpu.pas

@@ -59,9 +59,13 @@ unit cgcpu;
           procedure a_cmp_reg_reg_label(list : paasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : pasmlabel);
 
 
-          procedure g_stackframe_entry(list : paasmoutput;localsize : longint);virtual;
+          procedure g_stackframe_entry_sysv(list : paasmoutput;localsize : longint);
+          procedure g_stackframe_entry_mac(list : paasmoutput;localsize : longint);
+{          procedure g_stackframe_entry(list : paasmoutput;localsize : longint);virtual;}
           procedure g_restore_frame_pointer(list : paasmoutput);virtual;
-          procedure g_return_from_proc(list : paasmoutput;parasize : aword); virtual;
+{          procedure g_return_from_proc(list : paasmoutput;parasize : aword); virtual;}
+          procedure g_return_from_proc_sysv(list : paasmoutput;parasize : aword); virtual;
+          procedure g_return_from_proc_mac(list : paasmoutput;parasize : aword); virtual;
 
           procedure a_loadaddress_ref_reg(list : paasmoutput;const ref2 : treference;r : tregister);virtual;
 
@@ -342,73 +346,173 @@ const
         reg1,reg2 : tregister;l : pasmlabel);
 
       var p: paicpu;
-          AsmCond: TAsmCondFlags;
+          op: tasmop;
 
       begin
-        list^.concat(new(paicpu,op_const_reg_reg(A_CMPL,0,reg1,reg2)));
+        if cmp_op in [OC_GT,OC_LT,OC_GTE,OC_LTE] then
+          op := A_CMP
+        else op := A_CMPL;
+        list^.concat(new(paicpu,op_const_reg_reg(op,0,reg1,reg2)));
         a_jmp(list,A_BC,TOpCmp2AsmCond[cmp_op],l);
       end;
 
 
 { *********** entry/exit code and address loading ************ }
 
-    procedure tcgppc.g_stackframe_entry(list : paasmoutput;localsize : longint);
+    procedure tcgppc.g_stackframe_entry_sysv(list : paasmoutput;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                                                                      }
-     var scratch_register: TRegister;
+     var regcounter: TRegister;
 
       begin
         if (localsize mod 8) <> 0 then internalerror(58991);
  { CR and LR only have to be saved in case they are modified by the current }
  { procedure, but currently this isn't checked, so save them always         }
-        scratch_register := get_scratch_reg(list);
-        list^.concat(new(paicpu,op_reg(A_MFCR,scratch_register)));
+        { following is the entry code as described in "Altivec Programming }
+        { Interface Manual", bar the saving of AltiVec registers           }
+        a_reg_alloc(list,R_SP);
+        a_reg_alloc(list,R_0);
+        { allocate registers containing reg parameters }
+        for regcounter := R_3 to R_10 do
+          a_reg_alloc(list,regcounter);
+        { save return address... }
+        list^.concat(new(paicpu,op_reg(A_MFLR,R_0)));
+        { ... in caller's frame }
+        list^.concat(new(paicpu,op_reg_ref(A_STW,R_0,new_reference(R_SP,4))));
+        a_reg_dealloc(list,R_0);
+        a_reg_alloc(list,R_11);
+        { save end of fpr save area }
+        list^.concat(new(paicpu,op_reg_reg_const(A_ORI,R_11,R_SP,0)));
+        a_reg_alloc(list,R_12);
+        { 0 or 8 based on SP alignment }
+        list^.concat(new(paicpu,op_reg_reg_const_const_const(A_RLWINM,
+          R_12,R_SP,0,28,28)));
+        { add in stack length }
+        list^.concat(new(paicpu,op_reg_reg_const(A_SUBFIC,R_12,R_12,
+          -localsize)));
+        { establish new alignment }
+        list^.concat(new(paicpu,op_reg_reg_reg(A_STWUX,R_SP,R_SP,R_12)));
+        a_reg_dealloc(list,R_12);
+        { save floating-point registers }
+        { !!! has to be optimized: only save registers that are used }
+        list^.concat(new(op_sym_ofs(A_BL,newasmsymbol('_savefpr_14'),0)));
+        { compute end of gpr save area }
+        list^.concat(new(paicpu,op_reg_reg_const(A_ADDI,R_11,R_11,-144)));
+        { save gprs and fetch GOT pointer }
+        { !!! has to be optimized: only save registers that are used }
+        list^.concat(new(op_sym_ofs(A_BL,newasmsymbol('_savegpr_14_go'),0)));
+        a_reg_alloc(list,R_31);
+        { place GOT ptr in r31 }
+        list^.concat(new(paicpu,op_reg(A_MFLR,R_31));
+        { save the CR if necessary ( !!! always done currently ) }
+        { still need to find out where this has to be done for SystemV
+        a_reg_alloc(list,R_0);
+        list^.concat(new(paicpu,op_reg(A_MFCR,R_0);
         list^.concat(new(paicpu,op_reg_ref(A_STW,scratch_register,
           new_reference(stack_pointer,LA_CR))));
-        free_scratch_reg(list,scratch_register);
-        scratch_register := get_scratch_reg(list);
-        list^.concat(new(paicpu,op_reg_reg(A_MFSPR,scratch_register,
-          R_LR)));
+        a_reg_dealloc(list,R_0); }
+        { save pointer to incoming arguments }
+        list^.concat(new(paicpu,op_reg_reg_const(A_ADDI,R_30,R_11,144)));
+        { now comes the AltiVec context save, not yet implemented !!! }
+       end;
+
+    procedure tcgppc.g_stackframe_entry_mac(list : paasmoutput;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                                                                      }
+     var regcounter: TRegister;
+
+      begin
+        if (localsize mod 8) <> 0 then internalerror(58991);
+ { CR and LR only have to be saved in case they are modified by the current }
+ { procedure, but currently this isn't checked, so save them always         }
+        { following is the entry code as described in "Altivec Programming }
+        { Interface Manual", bar the saving of AltiVec registers           }
+        a_reg_alloc(list,R_SP);
+        a_reg_alloc(list,R_0);
+        { allocate registers containing reg parameters }
+        for regcounter := R_3 to R_10 do
+          a_reg_alloc(list,regcounter);
+        { save return address... }
+        list^.concat(new(paicpu,op_reg(A_MFLR,R_0)));
+        { ... in caller's frame }
+        list^.concat(new(paicpu,op_reg_ref(A_STW,R_0,new_reference(R_SP,8))));
+        a_reg_dealloc(list,R_0);
+        { save floating-point registers }
+        { !!! has to be optimized: only save registers that are used }
+        list^.concat(new(op_sym_ofs(A_BL,'_savef14',0)));
+        { save gprs in gpr save area }
+        { !!! has to be optimized: only save registers that are used }
+        list^.concat(new(op_reg_ref(A_STMW,R_13,new_reference(R_SP,-220))));
+        { save the CR if necessary ( !!! always done currently ) }
+        a_reg_alloc(list,R_0);
+        list^.concat(new(paicpu,op_reg(A_MFCR,R_0);
         list^.concat(new(paicpu,op_reg_ref(A_STW,scratch_register,
-          new_reference(stack_pointer,LA_LR))));
-        free_scratch_reg(list,scratch_register);
-{ if the current procedure is a leaf procedure, we can use the Red Zone,    }
-{ but this is not yet implemented                                           }
-{        if ((procinfo.flags and pi_do_call) <> 0) And                      }
-{           (localsize <= (256 - LinkageAreaSize)) Then                     }
-           Begin
-             if localsize<>0 then
-               begin
- { allocate space for the local variable, parameter and linkage area and   }
- { save the stack pointer at the end of the linkage area                   }
-                 if localsize <= $ffff Then
-                   list^.concat(new(paicpu,op_reg_ref
-                     (A_STWU,stack_pointer, new_reference(stack_pointer,localsize+
-                      LinkageAreaSize))))
-                 else
-                   Begin
-                     scratch_register := get_scratch_reg(list);
-                     a_load_const_reg(list,OS_32,localsize,scratch_register);
-                     list^.concat(new(paicpu,op_reg_reg_reg(A_STWUX,stack_pointer,
-                       stack_pointer,scratch_register)));
-                     free_scratch_reg(list,scratch_register);
-                  End;
-               End
-           End;
+          new_reference(stack_pointer,LA_CR))));
+        a_reg_dealloc(list,R_0);
+        { save pointer to incoming arguments }
+        list^.concat(new(paicpu,op_reg_reg_const(A_ORI,R_31,R_SP,0)));
+        a_reg_alloc(list,R_12);
+        { 0 or 8 based on SP alignment }
+        list^.concat(new(paicpu,op_reg_reg_const_const_const(A_RLWINM,
+          R_12,R_SP,0,28,28)));
+        { add in stack length }
+        list^.concat(new(paicpu,op_reg_reg_const(A_SUBFIC,R_12,R_12,
+          -localsize)));
+        { establish new alignment }
+        list^.concat(new(paicpu,op_reg_reg_reg(A_STWUX,R_SP,R_SP,R_12)));
+        a_reg_dealloc(list,R_12);
+        { now comes the AltiVec context save, not yet implemented !!! }
        end;
 
+
     procedure tcgppc.g_restore_frame_pointer(list : paasmoutput);
 
       begin
- { no frame pointer on the PowerPC                                          }
+ { no frame pointer on the PowerPC (maybe there is one in the SystemV ABI?)}
       end;
 
-     procedure tcgppc.g_return_from_proc(list : paasmoutput;parasize : aword);
+     procedure tcgppc.g_return_from_proc_sysv(list : paasmoutput;parasize : aword);
+
+     var regcounter: TRegister;
+
+     begin
+       { release parameter registers }
+       for regcounter := R_3 to R_10 do
+         a_reg_dealloc(list,regcounter);
+       { AltiVec context restore, not yet implemented !!! }
+
+       { address if gpr save area to r11 }
+       list^.concat(new(paicpu,op_reg_reg_const(A_ADDI,R_11,R_31,-144)));
+       { restore gprs }
+       list^.concat(new(paicpu,op_sym_ofs(A_BL,newasmsymbol('_restgpr_14'),0)));
+       { address of fpr save area to r11 }
+       list^.concat(new(paicpu,op_reg_reg_const(A_ADDI,R_11,R_11,144)));
+       { restore fprs and return }
+       list^.concat(new(paicpu,op_sym_ofs(A_BL,newasmsymbol('_restfpr_14_x'),0)));
+     end;
+
+     procedure tcgppc.g_return_from_proc_sysv(list : paasmoutput;parasize : aword);
+
+     var regcounter: TRegister;
 
      begin
-       abstract;
+       { release parameter registers }
+       for regcounter := R_3 to R_10 do
+         a_reg_dealloc(list,regcounter);
+       { AltiVec context restore, not yet implemented !!! }
+
+       { restore SP }
+       list^.concat(new(paicpu,op_reg_reg_const(A_ORI,R_SP,R_31,0)));
+       { restore gprs }
+       list^.concat(new(paicpu,op_reg_ref(A_LMW,R_13,new_reference(R_SP,-220))));
+       { restore return address ... }
+       list^.concat(new(paicpu,op_reg_ref(A_LWZ,R_0,new_reference(R_SP,8))));
+       { ... and return from _restf14 }
+       list^.concat(new(paicpu,op_sym_ofs(A_B,newasmsymbol('_restf14'),0)));
      end;
 
      procedure tcgppc.a_loadaddress_ref_reg(list : paasmoutput;const ref2 : treference;r : tregister);
@@ -422,27 +526,27 @@ const
          if assigned(ref.symbol) then
            { add the symbol's value to the base of the reference, and if the }
            { reference doesn't have a base, create one                       }
-	 	       begin
-	           tmpreg := get_scratch_reg(list);
-	           reset_reference(tmpref);
-	           tmpref.symbol := ref.symbol;
-	           tmpref.symaddr := refs_ha;
-	           tmpref.is_immediate := true;
-	           if ref.base <> R_NO then
-	             list^.concat(new(paicpu,op_reg_reg_ref(A_ADDIS,tmpreg,
-	               ref.base,newreference(tmpref))))
-	           else
-	             list^.concat(new(paicpu,op_reg_ref(A_LIS,tmpreg,
-	                newreference(tmpref))));
-	           ref.base := tmpreg
-	           ref.symaddr := refs_l;
-	           { can be folded with one of the next instructions by the }
-	           { optimizer probably                                     }
-	           list^.concat(new(paicpu,op_reg_ref(A_ADDI,tmpreg,tmpreg
-	              newreference(tmpref))));
-	 	       end;
-         If ref.offset <> 0 Then
-           If ref.base <> R_NO then
+           begin
+             tmpreg := get_scratch_reg(list);
+             reset_reference(tmpref);
+             tmpref.symbol := ref.symbol;
+             tmpref.symaddr := refs_ha;
+             tmpref.is_immediate := true;
+             if ref.base <> R_NO then
+               list^.concat(new(paicpu,op_reg_reg_ref(A_ADDIS,tmpreg,
+                 ref.base,newreference(tmpref))))
+             else
+               list^.concat(new(paicpu,op_reg_ref(A_LIS,tmpreg,
+                  newreference(tmpref))));
+             ref.base := tmpreg
+             ref.symaddr := refs_l;
+             { can be folded with one of the next instructions by the }
+             { optimizer probably                                     }
+             list^.concat(new(paicpu,op_reg_ref(A_ADDI,tmpreg,tmpreg
+                newreference(tmpref))));
+           end;
+         if ref.offset <> 0 Then
+           if ref.base <> R_NO then
              a_op_reg_reg_const32(list,A_ADDI,A_ADDIS,r,r,ref.offset)
   { FixRef makes sure that "(ref.index <> R_NO) and (ref.offset <> 0)" never}
   { occurs, so now only ref.offset has to be loaded                         }
@@ -451,20 +555,11 @@ const
            if ref.index <> R_NO Then
              list^.concat(new(paicpu,op_reg_reg_reg(A_ADD,r,ref.base,ref.index)))
            else list^.concat(new(paicpu,op_reg_reg(A_MR,r,ref.base)));
-         If assigned(ref.symbol) then
+         if assigned(ref.symbol) then
            free_scratch_reg(list,tmpreg);
        end;
 
 
-	     begin
-	         begin
-	         end;
-	       list^.concat(new(paicpu,op_reg_ref(op,reg,newreference(ref))));
-	       if assigned(ref.symbol) then
-	         free_scratch_reg(list,tmpreg);
-	     end;
-
-
 { ************* concatcopy ************ }
 
     procedure tcgppc.g_concatcopy(list : paasmoutput;const source,dest : treference;len : aword;loadref : boolean);
@@ -506,7 +601,7 @@ const
             countreg := get_scratch_reg(list);
             a_load_const_reg(list,OS_32,count-1,countreg);
             { explicitely allocate R_0 since it can be used safely here }
-            { (for holding date that's being copyied)                   }
+            { (for holding date that's being copied)                    }
             tempreg := R_0;
             a_reg_alloc(list,R_0);
             getlabel(lab);
@@ -617,7 +712,12 @@ const
 end.
 {
   $Log$
-  Revision 1.7  1999-10-20 12:23:24  jonas
+  Revision 1.8  1999-10-24 09:22:18  jonas
+    + entry/exitcode for SystemV (Linux) and AIX/Mac from the Altivec
+      PIM (no AltiVec support yet though)
+    * small fix to the a_cmp_* methods
+
+  Revision 1.7  1999/10/20 12:23:24  jonas
     * fixed a_loadaddress_ref_reg (mentioned as ToDo in rev. 1.5)
     * small bugfix in a_load_store