2
0
Эх сурвалжийг харах

* first part of ppc calling conventions fix

florian 23 жил өмнө
parent
commit
b136cecacd

+ 27 - 14
compiler/cgbase.pas

@@ -62,7 +62,7 @@ unit cgbase;
     type
        {# This object gives information on the current routine being
           compiled.
-       }   
+       }
        pprocinfo = ^tprocinfo;
        tprocinfo = object
           {# pointer to parent in nested procedures }
@@ -85,7 +85,7 @@ unit cgbase;
           para_offset : longint;
 
           {# some collected informations about the procedure
-             see pi_xxxx constants above                               
+             see pi_xxxx constants above
           }
           flags : longint;
 
@@ -100,33 +100,40 @@ unit cgbase;
 
           {# true, if we can not use fast exit code }
           no_fast_exit : boolean;
-          
-          {# Holds the environment reference for default exceptions 
-             
+
+          {# Holds the environment reference for default exceptions
+
              The exception reference is created when ansistrings
              or classes are used. It holds buffer for exception
              frames. It is allocted by g_new_exception.
           }
           exception_env_ref : treference;
-          {# Holds the environment reference for default exceptions 
-             
+          {# Holds the environment reference for default exceptions
+
              The exception reference is created when ansistrings
              or classes are used. It holds buffer for setjmp
              It is allocted by g_new_exception.
           }
           exception_jmp_ref :treference;
-          {# Holds the environment reference for default exceptions 
-             
+          {# Holds the environment reference for default exceptions
+
              The exception reference is created when ansistrings
              or classes are used. It holds the location where
              temporary storage of the setjmp result is stored.
-             
+
              This reference can be unused, if the result is instead
              saved on the stack.
           }
           exception_result_ref :treference;
+
+          { overall size of allocated stack space, currently this is used for the PowerPC only }
+          localsize : aword;
+
+          { max. of space need for parameters, currently used by the PowerPC port only }
+          maxpushedparasize : aword;
+
           {# Holds the reference used to store alll saved registers.
-          
+
              This is used on systems which do not have direct stack
              operations (such as the PowerPC), it is unused on other
              systems
@@ -134,7 +141,7 @@ unit cgbase;
           save_regs_ref : treference;
           {# The code for the routine itself, excluding entry and
              exit code. This is a linked list of tai classes.
-          }   
+          }
           aktproccode : taasmoutput;
           {# The code for the routine entry code.
           }
@@ -143,6 +150,7 @@ unit cgbase;
           }
           aktexitcode: taasmoutput;
           aktlocaldata : taasmoutput;
+
           constructor init;
           destructor done;
        end;
@@ -208,7 +216,7 @@ unit cgbase;
     function def_cgsize(def: tdef): tcgsize;
     {# From a constant numeric value, return the abstract code generator
        size.
-    }   
+    }
     function int_cgsize(const l: aword): tcgsize;
 
     {# return the inverse condition of opcmp }
@@ -357,6 +365,8 @@ implementation
         globalsymbol:=false;
         exported:=false;
         no_fast_exit:=false;
+        maxpushedparasize:=0;
+        localsize:=0;
 
         aktentrycode:=Taasmoutput.Create;
         aktexitcode:=Taasmoutput.Create;
@@ -580,7 +590,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.21  2002-08-05 18:27:48  carl
+  Revision 1.22  2002-08-06 20:55:20  florian
+    * first part of ppc calling conventions fix
+
+  Revision 1.21  2002/08/05 18:27:48  carl
     + more more more documentation
     + first version include/exclude (can't test though, not enough scratch for i386 :()...
 

+ 6 - 3
compiler/globtype.pas

@@ -101,7 +101,7 @@ interface
          cs_profile,cs_debuginfo,cs_browser,cs_local_browser,cs_compilesystem,
          cs_lineinfo,
          { linking }
-         cs_create_smart,cs_create_dynamic
+         cs_create_smart,cs_create_dynamic,cs_create_pic
        );
        tmoduleswitches = set of tmoduleswitch;
 
@@ -255,7 +255,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.28  2002-07-04 20:43:00  florian
+  Revision 1.29  2002-08-06 20:55:20  florian
+    * first part of ppc calling conventions fix
+
+  Revision 1.28  2002/07/04 20:43:00  florian
     * first x86-64 patches
 
   Revision 1.27  2002/07/01 18:46:22  peter
@@ -302,4 +305,4 @@ end.
    * implicit result variable generation for assembler routines
    * removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
 
-}
+}

+ 8 - 1
compiler/i386/cpubase.pas

@@ -312,6 +312,10 @@ uses
 *****************************************************************************}
 
     const
+      { declare aliases }
+      LOC_MMREGISTER = LOC_SSEREGISTER;
+      LOC_CMMREGISTER = LOC_CSSEREGISTER;
+
       max_operands = 3;
 
       lvaluelocations = [LOC_REFERENCE,LOC_CFPUREGISTER,
@@ -486,7 +490,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.27  2002-07-25 18:01:29  carl
+  Revision 1.28  2002-08-06 20:55:23  florian
+    * first part of ppc calling conventions fix
+
+  Revision 1.27  2002/07/25 18:01:29  carl
     + FPURESULTREG -> FPU_RESULT_REG
 
   Revision 1.26  2002/07/07 09:52:33  florian

+ 6 - 2
compiler/ncgcal.pas

@@ -1100,7 +1100,8 @@ implementation
                   emit_const_reg(A_ADD,S_L,pushedparasize,R_ESP);
              end;
 {$endif dummy}
-
+         if procinfo^.maxpushedparasize<pushedparasize then
+           procinfo^.maxpushedparasize:=pushedparasize;
 {$ifdef OPTALIGN}
          if pop_esp then
            emit_reg(A_POP,S_L,R_ESP);
@@ -1499,7 +1500,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.3  2002-07-20 11:57:53  florian
+  Revision 1.4  2002-08-06 20:55:20  florian
+    * first part of ppc calling conventions fix
+
+  Revision 1.3  2002/07/20 11:57:53  florian
     * types.pas renamed to defbase.pas because D6 contains a types
       unit so this would conflicts if D6 programms are compiled
     + Willamette/SSE2 instructions to assembler added

+ 10 - 2
compiler/ncgld.pas

@@ -172,7 +172,12 @@ implementation
                               begin
                                  location.reference.base:=procinfo^.framepointer;
                                  if (symtabletype in [inlinelocalsymtable,
-                                                      localsymtable]) then
+                                                      localsymtable])
+{$ifdef powerpc}
+                                   { the ifdef is only for speed reasons }
+                                   and not(target_info.system in [system_powerpc_linux,system_powerpc_macos])
+{$endif powerpc}
+                                   then
                                    location.reference.offset:=
                                      tvarsym(symtableentry).address-symtable.address_fixup
                                  else
@@ -924,7 +929,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.17  2002-07-28 09:25:37  carl
+  Revision 1.18  2002-08-06 20:55:21  florian
+    * first part of ppc calling conventions fix
+
+  Revision 1.17  2002/07/28 09:25:37  carl
     + correct size of parameter (64-bit portability)
 
   Revision 1.16  2002/07/27 19:53:51  jonas

+ 8 - 2
compiler/ncgutil.pas

@@ -1123,6 +1123,8 @@ implementation
               list.concat(Tai_symbol.Createname(hs,0));
            until false;
 
+{$ifdef i386}
+           { at least for the ppc this applies always, so this code isn't usable (FK) }
            { omit stack frame ? }
            if (procinfo^.framepointer=STACK_POINTER_REG) then
             begin
@@ -1136,6 +1138,7 @@ implementation
                 cg.a_op_const_reg(list,OP_SUB,stackframe,procinfo^.framepointer);
             end
            else
+{$endif i386}
             begin
               nostackframe:=false;
               if (aktprocdef.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
@@ -1626,7 +1629,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.29  2002-08-04 19:09:22  carl
+  Revision 1.30  2002-08-06 20:55:21  florian
+    * first part of ppc calling conventions fix
+
+  Revision 1.29  2002/08/04 19:09:22  carl
     + added generic exception support (still does not work!)
     + more documentation
 
@@ -1768,4 +1774,4 @@ end.
   Revision 1.2  2002/03/04 19:10:11  peter
     * removed compiler warnings
 
-}
+}

+ 12 - 4
compiler/paramgr.pas

@@ -81,6 +81,7 @@ unit paramgr;
     uses
        cpuinfo,
        symconst,symbase,symsym,
+       rgobj,
        defbase;
 
     { true if the return value is in accumulator (EAX for i386), D0 for 68k }
@@ -154,10 +155,14 @@ unit paramgr;
          hp:=tparaitem(p.para.first);
          while assigned(hp) do
            begin
-              if (hp.paraloc.loc in [LOC_REGISTER,LOC_FPUREGISTER]) and
+              if (hp.paraloc.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER]) and
               { if the parameter isn't regable, we've to work with the local copy }
-                (vo_regable in tvarsym(hp.parasym).varoptions) then
-                tvarsym(hp.parasym).reg:=hp.paraloc.register;
+                ((vo_regable in tvarsym(hp.parasym).varoptions) or
+                 (vo_fpuregable in tvarsym(hp.parasym).varoptions)) then
+                begin
+                   tvarsym(hp.parasym).reg:=hp.paraloc.register;
+                   rg.regvar_loaded[hp.paraloc.register]:=true;
+                end;
               hp:=tparaitem(hp.next);
            end;
       end;
@@ -168,7 +173,10 @@ end.
 
 {
    $Log$
-   Revision 1.7  2002-08-05 18:27:48  carl
+   Revision 1.8  2002-08-06 20:55:21  florian
+     * first part of ppc calling conventions fix
+
+   Revision 1.7  2002/08/05 18:27:48  carl
      + more more more documentation
      + first version include/exclude (can't test though, not enough scratch for i386 :()...
 

+ 221 - 78
compiler/powerpc/cgcpu.pas

@@ -214,20 +214,22 @@ const
         tmpreg: tregister;
 
       begin
-  {$ifdef para_sizes_known}
-        if (nr <= max_param_regs_int) then
-          a_loadaddr_ref_reg(list,size,r,param_regs_int[nr])
-        else
-          begin
-            reset_reference(ref);
-            ref.base := STACK_POINTER_REG;
-            ref.offset := LinkageAreaSize+para_size_till_now;
-            tmpreg := get_scratch_reg_address(list);
-            a_loadaddr_ref_reg(list,size,r,tmpreg);
-            a_load_reg_ref(list,size,tmpreg,ref);
-            free_scratch_reg(list,tmpreg);
-          end;
-  {$endif para_sizes_known}
+         case locpara.loc of
+            LOC_REGISTER:
+              a_loadaddr_ref_reg(list,r,locpara.register);
+            LOC_REFERENCE:
+              begin
+                reference_reset(ref);
+                ref.base := locpara.reference.index;
+                ref.offset := locpara.reference.offset;
+                tmpreg := get_scratch_reg_address(list);
+                a_loadaddr_ref_reg(list,r,tmpreg);
+                a_load_reg_ref(list,OS_ADDR,tmpreg,ref);
+                free_scratch_reg(list,tmpreg);
+              end;
+            else
+              internalerror(2002080701);
+         end;
       end;
 
     { calling a code fragment by name }
@@ -243,12 +245,14 @@ const
          list.concat(taicpu.op_sym(A_BL,newasmsymbol(s)));
          reference_reset_base(href,STACK_POINTER_REG,LA_RTOC);
          list.concat(taicpu.op_reg_ref(A_LWZ,R_TOC,href));
+         procinfo^.flags:=procinfo^.flags or pi_do_call;
       end;
 
     { calling a code fragment through a reference }
     procedure tcgppc.a_call_ref(list : taasmoutput;const ref : treference);
       begin
          {$warning FIX ME}
+         procinfo^.flags:=procinfo^.flags or pi_do_call;
       end;
 
 {********************** load instructions ********************}
@@ -789,17 +793,18 @@ const
 
 
     procedure tcgppc.g_stackframe_entry_sysv(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                                                                      }
-     var regcounter: TRegister;
+     { 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,firstregfpu,firstreggpr : TRegister;
          href : treference;
+         usesfpr,usesgpr,gotgot : boolean;
+         parastart : aword;
 
       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         }
+        { 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,STACK_POINTER_REG);
@@ -807,36 +812,114 @@ const
         { allocate registers containing reg parameters }
         for regcounter := R_3 to R_10 do
           a_reg_alloc(list,regcounter);
-        { save return address... }
-        list.concat(taicpu.op_reg_reg(A_MFSPR,R_0,R_LR));
-        { ... in caller's frame }
-        reference_reset_base(href,STACK_POINTER_REG,4);
-        list.concat(taicpu.op_reg_ref(A_STW,R_0,href));
-        a_reg_dealloc(list,R_0);
-        a_reg_alloc(list,R_11);
-        { save end of fpr save area }
-        list.concat(taicpu.op_reg_reg_const(A_ORI,R_11,STACK_POINTER_REG,0));
-        a_reg_alloc(list,R_12);
-        { 0 or 8 based on SP alignment }
-        list.concat(taicpu.op_reg_reg_const_const_const(A_RLWINM,
-          R_12,STACK_POINTER_REG,0,28,28));
-        { add in stack length }
-        list.concat(taicpu.op_reg_reg_const(A_SUBFIC,R_12,R_12,
-          -localsize));
-        { establish new alignment }
-        list.concat(taicpu.op_reg_reg_reg(A_STWUX,STACK_POINTER_REG,STACK_POINTER_REG,R_12));
-        a_reg_dealloc(list,R_12);
-        { save floating-point registers }
-        { !!! has to be optimized: only save registers that are used }
-        list.concat(taicpu.op_sym_ofs(A_BL,newasmsymbol('_savefpr_14'),0));
-        { compute end of gpr save area }
-        list.concat(taicpu.op_reg_reg_const(A_ADDI,R_11,R_11,-144));
+
+        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_14 to R_31 do
+          if regcounter in rg.usedbyproc then
+            begin
+               usesgpr:=true;
+               firstreggpr:=regcounter;
+               break;
+            end;
+
+        { save link register? }
+        if (procinfo^.flags and pi_do_call)<>0 then
+          begin
+             { save return address... }
+             list.concat(taicpu.op_reg_reg(A_MFSPR,R_0,R_LR));
+             { ... in caller's rframe }
+             reference_reset_base(href,STACK_POINTER_REG,4);
+             list.concat(taicpu.op_reg_ref(A_STW,R_0,href));
+             a_reg_dealloc(list,R_0);
+          end;
+
+        if usesfpr or usesgpr then
+          begin
+             a_reg_alloc(list,R_11);
+             { save end of fpr save area }
+             list.concat(taicpu.op_reg_reg_const(A_ORI,R_11,STACK_POINTER_REG,0));
+          end;
+
+        { calculate the size of the locals }
+        if usesgpr then
+          inc(localsize,(ord(R_31)-ord(firstreggpr)+1)*4);
+        if usesfpr then
+          inc(localsize,(ord(R_F31)-ord(firstregfpu)+1)*8);
+
+        { align to 16 bytes }
+        if (localsize mod 16)<>0 then
+          localsize:=(localsize and $fffffff0)+16;
+
+        parastart:=localsize;
+        inc(localsize,procinfo^.maxpushedparasize);
+
+        { align to 16 bytes }
+        if (localsize mod 16)<>0 then
+          localsize:=(localsize and $fffffff0)+16;
+
+        procinfo^.procdef.localst.address_fixup:=localsize-parastart;
+
+        procinfo^.localsize:=localsize;
+
+        reference_reset_base(href,R_1,-localsize);
+        list.concat(taicpu.op_reg_ref(A_STWU,R_1,href));
+
+        { no GOT pointer loaded yet }
+        gotgot:=false;
+        if usesfpr then
+          begin
+             { save floating-point registers }
+             if (cs_create_pic in aktmoduleswitches) and not(usesgpr) then
+               begin
+                  list.concat(taicpu.op_sym_ofs(A_BL,newasmsymbol('_savefpr_'+tostr(ord(firstregfpu)-ord(R_F14)+14)+'_g'),0));
+                  gotgot:=true;
+               end
+             else
+               list.concat(taicpu.op_sym_ofs(A_BL,newasmsymbol('_savefpr_'+tostr(ord(firstregfpu)-ord(R_F14)+14)),0));
+             { compute end of gpr save area }
+             list.concat(taicpu.op_reg_reg_const(A_ADDI,R_11,R_11,-(ord(R_F31)-ord(firstregfpu)+1)*8));
+          end;
+
         { save gprs and fetch GOT pointer }
-        { !!! has to be optimized: only save registers that are used }
-        list.concat(taicpu.op_sym_ofs(A_BL,newasmsymbol('_savegpr_14_go'),0));
-        a_reg_alloc(list,R_31);
-        { place GOT ptr in r31 }
-        list.concat(taicpu.op_reg_reg(A_MFSPR,R_31,R_LR));
+        if usesgpr then
+          begin
+             {
+             if cs_create_pic in aktmoduleswitches then
+               begin
+                  list.concat(taicpu.op_sym_ofs(A_BL,newasmsymbol('_savegpr_'+tostr(ord(firstreggpr)-ord(R_14)+14)+'_g'),0));
+                  gotgot:=true;
+               end
+             else
+               list.concat(taicpu.op_sym_ofs(A_BL,newasmsymbol('_savegpr_'+tostr(ord(firstreggpr)-ord(R_14)+14)),0))
+             }
+             reference_reset_base(href,R_11,-(ord(R_31)-ord(firstreggpr)+1)*4);
+             list.concat(taicpu.op_reg_ref(A_STMW,firstreggpr,href));
+          end;
+
+        if usesfpr or usesgpr then
+          a_reg_dealloc(list,R_11);
+
+        { PIC code support, }
+        if cs_create_pic in aktmoduleswitches then
+          begin
+             { if we didn't get the GOT pointer till now, we've to calculate it now }
+             if not(gotgot) then
+               begin
+                  {!!!!!!!!!!!!!}
+               end;
+             a_reg_alloc(list,R_31);
+             { place GOT ptr in r31 }
+             list.concat(taicpu.op_reg_reg(A_MFSPR,R_31,R_LR));
+          end;
         { 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);
@@ -844,11 +927,89 @@ const
         list.concat(taicpu.op_reg_ref(A_STW,scratch_register,
           new_reference(STACK_POINTER_REG,LA_CR)));
         a_reg_dealloc(list,R_0); }
-        { save pointer to incoming arguments }
-        list.concat(taicpu.op_reg_reg_const(A_ADDI,R_30,R_11,144));
         { now comes the AltiVec context save, not yet implemented !!! }
       end;
 
+    procedure tcgppc.g_return_from_proc_sysv(list : taasmoutput;parasize : aword);
+
+      var
+         regcounter,firstregfpu,firstreggpr : TRegister;
+         href : treference;
+         usesfpr,usesgpr,genret : boolean;
+
+      begin
+        { release parameter registers }
+        for regcounter := R_3 to R_10 do
+          a_reg_dealloc(list,regcounter);
+        { AltiVec context restore, not yet implemented !!! }
+
+        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_14 to R_30 do
+          if regcounter in rg.usedbyproc then
+            begin
+               usesgpr:=true;
+               firstreggpr:=regcounter;
+               break;
+            end;
+
+        { no return (blr) generated yet }
+        genret:=true;
+        if usesgpr then
+          begin
+             { address of gpr save area to r11 }
+             if usesfpr then
+               list.concat(taicpu.op_reg_reg_const(A_ADDI,R_11,R_1,procinfo^.localsize-(ord(R_F31)-ord(firstregfpu)+1)*8))
+             else
+               list.concat(taicpu.op_reg_reg_const(A_ADDI,R_11,R_1,procinfo^.localsize));
+
+             { restore gprs }
+             { at least for now we use LMW }
+             {
+             list.concat(taicpu.op_sym_ofs(A_BL,newasmsymbol('_restgpr_14'),0));
+             }
+             reference_reset_base(href,R_11,-(ord(R_31)-ord(firstreggpr)+1)*4);
+             list.concat(taicpu.op_reg_ref(A_LMW,firstreggpr,href));
+          end;
+
+        { restore fprs and return }
+        if usesfpr then
+          begin
+             { address of fpr save area to r11 }
+             list.concat(taicpu.op_reg_reg_const(A_ADDI,R_11,R_11,(ord(R_F31)-ord(firstregfpu)+1)*8));
+             if (procinfo^.flags and pi_do_call)<>0 then
+               list.concat(taicpu.op_sym_ofs(A_BL,newasmsymbol('_restfpr_'+tostr(ord(firstregfpu)-ord(R_F14)+14)+
+                 '_x'),0))
+             else
+               { leaf node => lr haven't to be restored }
+               list.concat(taicpu.op_sym_ofs(A_BL,newasmsymbol('_restfpr_'+tostr(ord(firstregfpu)-ord(R_F14)+14)+
+                 '_l'),0));
+             genret:=false;
+          end;
+        { if we didn't generate the return code, we've to do it now }
+        if genret then
+          begin
+             { adjust r1 }
+             reference_reset_base(href,R_1,procinfo^.localsize);
+             list.concat(taicpu.op_reg_ref(A_STWU,R_1,href));
+             { load link register? }
+             if (procinfo^.flags and pi_do_call)<>0 then
+               begin
+                  reference_reset_base(href,STACK_POINTER_REG,4);
+                  list.concat(taicpu.op_reg_ref(A_LWZ,R_0,href));
+                  list.concat(taicpu.op_reg_reg(A_MTSPR,R_LR,R_0));
+               end;
+             list.concat(taicpu.op_none(A_BLR));
+          end;
+      end;
 
     procedure tcgppc.g_stackframe_entry_mac(list : taasmoutput;localsize : longint);
  { generated the entry code of a procedure/function. Note: localsize is the }
@@ -860,8 +1021,8 @@ const
 
       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         }
+        { 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,STACK_POINTER_REG);
@@ -907,7 +1068,7 @@ const
     procedure tcgppc.g_restore_frame_pointer(list : taasmoutput);
 
       begin
- { no frame pointer on the PowerPC (maybe there is one in the SystemV ABI?)}
+         { no frame pointer on the PowerPC (maybe there is one in the SystemV ABI?)}
       end;
 
 
@@ -1154,27 +1315,6 @@ const
 
 {***************** This is private property, keep out! :) *****************}
 
-    procedure tcgppc.g_return_from_proc_sysv(list : taasmoutput;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 of gpr save area to r11 }
-        list.concat(taicpu.op_reg_reg_const(A_ADDI,R_11,R_31,-144));
-        { restore gprs }
-        list.concat(taicpu.op_sym_ofs(A_BL,newasmsymbol('_restgpr_14'),0));
-        { address of fpr save area to r11 }
-        list.concat(taicpu.op_reg_reg_const(A_ADDI,R_11,R_11,144));
-        { restore fprs and return }
-        list.concat(taicpu.op_sym_ofs(A_BL,newasmsymbol('_restfpr_14_x'),0));
-      end;
-
 
     procedure tcgppc.g_return_from_proc_mac(list : taasmoutput;parasize : aword);
 
@@ -1446,7 +1586,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.35  2002-08-06 07:12:05  jonas
+  Revision 1.36  2002-08-06 20:55:23  florian
+    * first part of ppc calling conventions fix
+
+  Revision 1.35  2002/08/06 07:12:05  jonas
     * fixed bug in g_flags2reg()
     * and yet more constant operation fixes :)
 

+ 4 - 2
compiler/powerpc/cpubase.pas

@@ -646,7 +646,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.23  2002-08-04 12:57:56  jonas
+  Revision 1.24  2002-08-06 20:55:24  florian
+    * first part of ppc calling conventions fix
+
+  Revision 1.23  2002/08/04 12:57:56  jonas
     * more misc. fixes, mostly constant-related
 
   Revision 1.22  2002/07/27 19:57:18  jonas
@@ -700,5 +703,4 @@ end.
 
   Revision 1.7  2002/04/06 18:13:02  jonas
     * several powerpc-related additions and fixes
-
 }

+ 5 - 4
compiler/powerpc/nppcadd.pas

@@ -1302,7 +1302,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.5  2002-08-05 08:58:54  jonas
+  Revision 1.6  2002-08-06 20:55:24  florian
+    * first part of ppc calling conventions fix
+
+  Revision 1.5  2002/08/05 08:58:54  jonas
     * fixed compilation problems
 
   Revision 1.4  2002/08/04 12:57:56  jonas
@@ -1319,6 +1322,4 @@ end.
   Revision 1.1  2002/07/26 12:31:57  jonas
     + intial implementation of add nodes, only integer/enumeration/pointer/...
       handling is finished
-
-
-}
+}

+ 10 - 2
compiler/pstatmnt.pas

@@ -889,6 +889,7 @@ implementation
                     if pattern=upper(std_reg2str[r]) then
                       begin
                          include(rg.usedinproc,r);
+                         include(rg.usedbyproc,r);
                          found:=true;
                          break;
                       end;
@@ -906,7 +907,11 @@ implementation
                 until false;
               consume(_RECKKLAMMER);
            end
-         else rg.usedinproc := ALL_REGISTERS;
+         else
+           begin
+              rg.usedbyproc := ALL_REGISTERS;
+              rg.usedinproc := ALL_REGISTERS;
+           end;
 
          { mark the start and the end of the assembler block
            this is needed for the optimizer }
@@ -1266,7 +1271,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.65  2002-07-28 20:45:22  florian
+  Revision 1.66  2002-08-06 20:55:22  florian
+    * first part of ppc calling conventions fix
+
+  Revision 1.65  2002/07/28 20:45:22  florian
     + added direct assembler reader for PowerPC
 
   Revision 1.64  2002/07/20 11:57:56  florian

+ 5 - 1
compiler/psub.pas

@@ -285,6 +285,7 @@ implementation
          { reset the temporary memory }
          rg.cleartempgen;
          rg.usedinproc:=[];
+         rg.usedbyproc:=[];
 
          { save entry info }
          entrypos:=aktfilepos;
@@ -831,7 +832,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.62  2002-07-26 21:15:41  florian
+  Revision 1.63  2002-08-06 20:55:22  florian
+    * first part of ppc calling conventions fix
+
+  Revision 1.62  2002/07/26 21:15:41  florian
     * rewrote the system handling
 
   Revision 1.61  2002/07/20 11:57:56  florian

+ 9 - 1
compiler/regvars.pas

@@ -213,6 +213,11 @@ implementation
                 parasym:=false;
                 symtablestack.foreach_static({$ifdef FPCPROCVAR}@{$endif}searchfpuregvars,@parasym);
 {$ifdef dummy}
+                { this code should be never enabled because     }
+                { 1. the caller loads parameters into registers }
+                { 2. (later) the CSE loads a parameter into a   }
+                {    register, if necessary                     }
+                {                                        (FK)   }
                 { copy parameter into a register ? }
                 parasym:=true;
                 symtablestack.next.foreach_static({$ifdef FPCPROCVAR}@{$endif}searchregvars);
@@ -464,7 +469,10 @@ end.
 
 {
   $Log$
-  Revision 1.37  2002-07-20 11:57:57  florian
+  Revision 1.38  2002-08-06 20:55:22  florian
+    * first part of ppc calling conventions fix
+
+  Revision 1.37  2002/07/20 11:57:57  florian
     * types.pas renamed to defbase.pas because D6 contains a types
       unit so this would conflicts if D6 programms are compiled
     + Willamette/SSE2 instructions to assembler added

+ 37 - 23
compiler/rgobj.pas

@@ -51,12 +51,12 @@ unit rgobj;
 
        tpushedsaved = array[firstreg..lastreg] of tpushedsavedloc;
 
-       {# 
+       {#
           This class implements the abstract register allocator
           It is used by the code generator to allocate and free
           registers which might be valid across nodes. It also
           contains utility routines related to registers.
-          
+
           Some of the methods in this class should be overriden
           by cpu-specific implementations.
        }
@@ -77,6 +77,10 @@ unit rgobj;
           countusableregsfpu,
           countusableregsmm : byte;
 
+          { Contains the registers which are really used by the proc itself.
+            It doesn't take care of registers used by called procedures
+          }
+          usedbyproc,
           usedinproc : tregisterset;
 
           reg_pushes : regvar_longintarray;
@@ -89,27 +93,27 @@ unit rgobj;
 
           constructor create;
 
-          {# Allocate a general purpose register 
-             
+          {# Allocate a general purpose register
+
              An internalerror will be generated if there
              is no more free registers which can be allocated
           }
           function getregisterint(list: taasmoutput) : tregister; virtual;
           {# Free a general purpose register
-          
+
              @param(r register to free)
 
           }
           procedure ungetregisterint(list: taasmoutput; r : tregister); virtual;
 
-          {# Allocate a floating point register 
+          {# Allocate a floating point register
 
              An internalerror will be generated if there
              is no more free registers which can be allocated
           }
           function getregisterfpu(list: taasmoutput) : tregister; virtual;
-          {# Free a floating point register 
-          
+          {# Free a floating point register
+
              @param(r register to free)
 
           }
@@ -118,8 +122,8 @@ unit rgobj;
           function getregistermm(list: taasmoutput) : tregister; virtual;
           procedure ungetregistermm(list: taasmoutput; r : tregister); virtual;
 
-          {# Allocate an address register. 
-          
+          {# Allocate an address register.
+
              Address registers are the only registers which can
              be used as a base register in references (treference).
              On most cpu's this is the same as a general purpose
@@ -133,18 +137,18 @@ unit rgobj;
           {# Verify if the specified register is an address or
              general purpose register. Returns TRUE if @var(reg)
              is an adress register.
-             
-             This routine should only be used to check on 
+
+             This routine should only be used to check on
              general purpose or address register. It will
              not work on multimedia or floating point
              registers
-             
+
              @param(reg register to verify)
-          }   
+          }
           function isaddressregister(reg: tregister): boolean; virtual;
 
-          {# Tries to allocate the passed register, if possible 
-          
+          {# Tries to allocate the passed register, if possible
+
              @param(r specific register to allocate)
           }
           function getexplicitregisterint(list: taasmoutput; r : tregister) : tregister;virtual;
@@ -156,7 +160,7 @@ unit rgobj;
              in the specified reference. On most systems,
              this will free the base and index registers
              of the specified reference.
-             
+
              @param(ref reference which must have its registers freed)
           }
           procedure ungetreference(list: taasmoutput; const ref : treference); virtual;
@@ -174,10 +178,10 @@ unit rgobj;
           {# Saves in temporary references (allocated via the temp. allocator)
              the registers defined in @var(s). The registers are only saved
              if they are currently in use, otherwise they are left as is.
-             
+
              On processors which have instructions which manipulate the stack,
              this routine should be overriden for performance reasons.
-             
+
              @param(list)   List to add the instruction to
              @param(saved)  Array of saved register information
              @param(s)      Registers which might require saving
@@ -186,7 +190,7 @@ unit rgobj;
             var saved : tpushedsaved;const s: tregisterset);virtual;
           {# Restores the registers which were saved with a call
              to @var(saveusedregisters).
-             
+
              On processors which have instructions which manipulate the stack,
              this routine should be overriden for performance reasons.
           }
@@ -223,7 +227,7 @@ unit rgobj;
        end;
 
      const
-       {# This value is used in tsaved. If the array value is equal 
+       {# This value is used in tsaved. If the array value is equal
           to this, then this means that this register is not used.
        }
        reg_not_saved = $7fffffff;
@@ -233,7 +237,7 @@ unit rgobj;
        rg: trgobj;
 
      { trerefence handling }
-     
+
      {# Clear to zero a treference }
      procedure reference_reset(var ref : treference);
      {# Clear to zero a treference, and set is base address
@@ -270,6 +274,8 @@ unit rgobj;
         countusableregsint,
         countusableregsfpu,
         countusableregsmm : byte;
+        { contains the registers which are really used by the proc itself }
+        usedbyproc,
         usedinproc : tregisterset;
         reg_pushes : regvar_longintarray;
         is_reg_var : regvar_booleanarray;
@@ -296,6 +302,7 @@ unit rgobj;
 
      begin
        usedinproc := [];
+       usedbyproc:=[];
        t_times := 0;
        resetusableregisters;
 {$ifdef TEMPREGDEBUG}
@@ -316,6 +323,7 @@ unit rgobj;
                 begin
                    exclude(unusedregs,i);
                    include(usedinproc,i);
+                   include(usedbyproc,i);
                    dec(countunusedregs);
                    list.concat(tai_regalloc.alloc(i));
                    result := i;
@@ -399,6 +407,7 @@ unit rgobj;
 {$endif TEMPREGDEBUG}
               exclude(unusedregsint,r);
               include(usedinproc,r);
+              include(usedbyproc,r);
               list.concat(tai_regalloc.alloc(r));
               getexplicitregisterint:=r;
 {$ifdef TEMPREGDEBUG}
@@ -783,6 +792,7 @@ unit rgobj;
         psavedstate(state)^.countusableregsfpu := countusableregsfpu;
         psavedstate(state)^.countusableregsmm := countusableregsmm;
         psavedstate(state)^.usedinproc := usedinproc;
+        psavedstate(state)^.usedbyproc := usedbyproc;
         psavedstate(state)^.reg_pushes := reg_pushes;
         psavedstate(state)^.is_reg_var := is_reg_var;
         psavedstate(state)^.regvar_loaded := regvar_loaded;
@@ -808,6 +818,7 @@ unit rgobj;
         countusableregsfpu := psavedstate(state)^.countusableregsfpu;
         countusableregsmm := psavedstate(state)^.countusableregsmm;
         usedinproc := psavedstate(state)^.usedinproc;
+        usedbyproc := psavedstate(state)^.usedbyproc;
         reg_pushes := psavedstate(state)^.reg_pushes;
         is_reg_var := psavedstate(state)^.is_reg_var;
         regvar_loaded := psavedstate(state)^.regvar_loaded;
@@ -942,7 +953,10 @@ end.
 
 {
   $Log$
-  Revision 1.15  2002-08-05 18:27:48  carl
+  Revision 1.16  2002-08-06 20:55:23  florian
+    * first part of ppc calling conventions fix
+
+  Revision 1.15  2002/08/05 18:27:48  carl
     + more more more documentation
     + first version include/exclude (can't test though, not enough scratch for i386 :()...