Browse Source

* adapted a_jmp_name for darwin/ppc64
* merged g_intf_wrapper for ppc32 and ppc64, and added darwin/ppc64
support to it

git-svn-id: branches/fpc_2_3@6394 -

Jonas Maebe 18 years ago
parent
commit
42d6fd663e
3 changed files with 109 additions and 164 deletions
  1. 0 74
      compiler/powerpc/cgcpu.pas
  2. 10 90
      compiler/powerpc64/cgcpu.pas
  3. 99 0
      compiler/ppcgen/cgppc.pas

+ 0 - 74
compiler/powerpc/cgcpu.pas

@@ -89,8 +89,6 @@ unit cgcpu;
         { that's the case, we can use rlwinm to do an AND operation        }
         function get_rlwi_const(a: aint; var l1, l2: longint): boolean;
 
-        procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
-
       protected
        procedure a_load_regconst_subsetreg_intern(list : TAsmList; fromsize, subsetsize: tcgsize; fromreg: tregister; const sreg: tsubsetregister; slopt: tsubsetloadopt); override;
       private
@@ -1776,78 +1774,6 @@ const
       end;
 
 
-    procedure tcgppc.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
-
-        procedure loadvmttor11;
-        var
-          href : treference;
-        begin
-          reference_reset_base(href,NR_R3,0);
-          cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R11);
-        end;
-
-        procedure op_onr11methodaddr;
-        var
-          href : treference;
-        begin
-          if (procdef.extnumber=$ffff) then
-            Internalerror(200006139);
-          { call/jmp  vmtoffs(%eax) ; method offs }
-          reference_reset_base(href,NR_R11,procdef._class.vmtmethodoffset(procdef.extnumber));
-          if not((longint(href.offset) >= low(smallint)) and
-                 (longint(href.offset) <= high(smallint))) then
-            begin
-              list.concat(taicpu.op_reg_reg_const(A_ADDIS,NR_R11,NR_R11,
-                smallint((href.offset shr 16)+ord(smallint(href.offset and $ffff) < 0))));
-              href.offset := smallint(href.offset and $ffff);
-            end;
-          list.concat(taicpu.op_reg_ref(A_LWZ,NR_R11,href));
-          list.concat(taicpu.op_reg(A_MTCTR,NR_R11));
-          list.concat(taicpu.op_none(A_BCTR));
-        end;
-
-      var
-        make_global : boolean;
-      begin
-        if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
-          Internalerror(200006137);
-        if not assigned(procdef._class) or
-           (procdef.procoptions*[po_classmethod, po_staticmethod,
-             po_methodpointer, po_interrupt, po_iocheck]<>[]) then
-          Internalerror(200006138);
-        if procdef.owner.symtabletype<>ObjectSymtable then
-          Internalerror(200109191);
-
-        make_global:=false;
-        if (not current_module.is_unit) or
-           (cs_create_smart in current_settings.moduleswitches) or
-           (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
-          make_global:=true;
-
-        if make_global then
-          List.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0))
-        else
-          List.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
-
-        { set param1 interface to self  }
-        g_adjust_self_value(list,procdef,ioffset);
-
-        { case 4 }
-        if po_virtualmethod in procdef.procoptions then
-          begin
-            loadvmttor11;
-            op_onr11methodaddr;
-          end
-        { case 0 }
-        else
-          if not(target_info.system = system_powerpc_darwin) then
-            list.concat(taicpu.op_sym(A_B,current_asmdata.RefAsmSymbol(procdef.mangledname)))
-          else
-            list.concat(taicpu.op_sym(A_B,get_darwin_call_stub(procdef.mangledname)));
-        List.concat(Tai_symbol_end.Createname(labelname));
-      end;
-
-
 {***************** This is private property, keep out! :) *****************}
 
     function tcgppc.issimpleref(const ref: treference): boolean;

+ 10 - 90
compiler/powerpc64/cgcpu.pas

@@ -99,8 +99,6 @@ type
     procedure g_concatcopy(list: TAsmList; const source, dest: treference;
       len: aint); override;
 
-    procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const
-      labelname: string; ioffset: longint); override;
   private
 
     procedure a_load_regconst_subsetreg_intern(list : TAsmList; fromsize, subsetsize: tcgsize; fromreg: tregister; const sreg: tsubsetregister; slopt: tsubsetloadopt); override;
@@ -132,10 +130,6 @@ type
       for the current procedure }
     procedure calcFirstUsedGPR(out firstgpr : TSuperRegister; out gprcount : aint);
 
-    { returns true if the offset of the given reference can not be represented by a 16 bit
-    immediate as required by some PowerPC instructions }
-    function hasLargeOffset(const ref : TReference) : Boolean; inline;
-
     { generates code to call a method with the given string name. The boolean options
      control code generation. If prependDot is true, a single dot character is prepended to
      the string, if addNOP is true a single NOP instruction is added after the call, and
@@ -1205,8 +1199,17 @@ begin
 end;
 
 procedure tcgppc.a_jmp_name(list: TAsmList; const s: string);
+var
+  p: taicpu;
 begin
-  a_jmp_name_direct(list, s, true);
+  if (target_info.system = system_powerpc64_darwin) then
+    begin
+      p := taicpu.op_sym(A_B,get_darwin_call_stub(s));
+      p.is_jmp := true;
+      list.concat(p)
+    end
+  else
+    a_jmp_name_direct(list, s, true);
 end;
 
 procedure tcgppc.a_jmp_always(list: TAsmList; l: tasmlabel);
@@ -1841,83 +1844,6 @@ begin
 
 end;
 
-procedure tcgppc.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const
-  labelname: string; ioffset: longint);
-
-  procedure loadvmttor11;
-  var
-    href: treference;
-  begin
-    reference_reset_base(href, NR_R3, 0);
-    cg.a_load_ref_reg(list, OS_ADDR, OS_ADDR, href, NR_R11);
-  end;
-
-  procedure op_onr11methodaddr;
-  var
-    href: treference;
-  begin
-    if (procdef.extnumber = $FFFF) then
-      Internalerror(200006139);
-    { call/jmp  vmtoffs(%eax) ; method offs }
-    reference_reset_base(href, NR_R11,
-      procdef._class.vmtmethodoffset(procdef.extnumber));
-    if not (hasLargeOffset(href)) then begin
-      list.concat(taicpu.op_reg_reg_const(A_ADDIS, NR_R11, NR_R11,
-        smallint((href.offset shr 16) + ord(smallint(href.offset and $FFFF) <
-        0))));
-      href.offset := smallint(href.offset and $FFFF);
-    end else
-      { add support for offsets > 16 bit }
-      internalerror(200510201);
-    list.concat(taicpu.op_reg_ref(A_LD, NR_R11, href));
-    { the loaded reference is a function descriptor reference, so deref again
-     (at ofs 0 there's the real pointer) }
-    {$warning ts:TODO: update GOT reference}
-    reference_reset_base(href, NR_R11, 0);
-    list.concat(taicpu.op_reg_ref(A_LD, NR_R11, href));
-
-    list.concat(taicpu.op_reg(A_MTCTR, NR_R11));
-    list.concat(taicpu.op_none(A_BCTR));
-    { NOP needed for the linker...? }
-    list.concat(taicpu.op_none(A_NOP));
-  end;
-
-var
-  make_global: boolean;
-begin
-  if (not (procdef.proctypeoption in [potype_function, potype_procedure])) then
-    Internalerror(200006137);
-  if not assigned(procdef._class) or
-    (procdef.procoptions * [po_classmethod, po_staticmethod,
-    po_methodpointer, po_interrupt, po_iocheck] <> []) then
-    Internalerror(200006138);
-  if procdef.owner.symtabletype <> ObjectSymtable then
-    Internalerror(200109191);
-
-  make_global := false;
-  if (not current_module.is_unit) or
-    (cs_create_smart in current_settings.moduleswitches) or
-    (procdef.owner.defowner.owner.symtabletype = globalsymtable) then
-    make_global := true;
-
-  if make_global then
-    List.concat(Tai_symbol.Createname_global(labelname, AT_FUNCTION, 0))
-  else
-    List.concat(Tai_symbol.Createname(labelname, AT_FUNCTION, 0));
-
-  { set param1 interface to self  }
-  g_adjust_self_value(list, procdef, ioffset);
-
-  if po_virtualmethod in procdef.procoptions then begin
-    loadvmttor11;
-    op_onr11methodaddr;
-  end else
-    {$note ts:todo add GOT change?? - think not needed :) }
-    list.concat(taicpu.op_sym(A_B,current_asmdata.RefAsmSymbol('.' + procdef.mangledname)));
-
-  List.concat(Tai_symbol_end.Createname(labelname));
-end;
-
 {***************** This is private property, keep out! :) *****************}
 
 procedure tcgppc.maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
@@ -2175,12 +2101,6 @@ begin
   end;
 end;
 
-function tcgppc.hasLargeOffset(const ref : TReference) : Boolean; {$ifdef ver2_0}inline;{$endif}
-begin
-  { this rather strange calculation is required because offsets of TReferences are unsigned }
-  result := aword(ref.offset-low(smallint)) > high(smallint)-low(smallint);
-end;
-
 procedure tcgppc.loadConstantPIC(list : TAsmList; size : TCGSize; a : aint; reg : TRegister);
 var
   l: tasmsymbol;

+ 99 - 0
compiler/ppcgen/cgppc.pas

@@ -57,6 +57,8 @@ unit cgppc;
         procedure g_profilecode(list: TAsmList); override;
 
         procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
+
+        procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
        protected
         function  get_darwin_call_stub(const s: string): tasmsymbol;
         procedure a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tcgsize; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister); override;
@@ -67,6 +69,11 @@ unit cgppc;
         { of asmcondflags and destination addressing mode                }
         procedure a_jmp(list: TAsmList; op: tasmop;
                         c: tasmcondflag; crval: longint; l: tasmlabel);
+
+        { returns true if the offset of the given reference can not be  }
+        { represented by a 16 bit immediate as required by some PowerPC }
+        { instructions                                                  }
+        function hasLargeOffset(const ref : TReference) : Boolean; inline;
      end;
 
   const
@@ -82,6 +89,12 @@ unit cgppc;
        rgobj,tgobj,cpupi,procinfo,paramgr;
 
 
+    function tcgppcgen.hasLargeOffset(const ref : TReference) : Boolean;
+      begin
+        result := aword(ref.offset-low(smallint)) > high(smallint)-low(smallint);
+      end;
+
+
     procedure tcgppcgen.a_param_const(list: TAsmList; size: tcgsize; a: aint; const
       paraloc: tcgpara);
     var
@@ -417,6 +430,92 @@ unit cgppc;
 
 
 
+    procedure tcgppcgen.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
+
+        procedure loadvmttor11;
+        var
+          href : treference;
+        begin
+          reference_reset_base(href,NR_R3,0);
+          cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R11);
+        end;
+
+
+        procedure op_onr11methodaddr;
+        var
+          href : treference;
+        begin
+          if (procdef.extnumber=$ffff) then
+            Internalerror(200006139);
+          { call/jmp  vmtoffs(%eax) ; method offs }
+          reference_reset_base(href,NR_R11,procdef._class.vmtmethodoffset(procdef.extnumber));
+          if hasLargeOffset(href) then
+            begin
+{$ifdef cpu64}
+              if (longint(href.offset) <> href.offset) then
+                { add support for offsets > 32 bit }
+                internalerror(200510201);
+{$endif cpu64}
+              list.concat(taicpu.op_reg_reg_const(A_ADDIS,NR_R11,NR_R11,
+                smallint((href.offset shr 16)+ord(smallint(href.offset and $ffff) < 0))));
+              href.offset := smallint(href.offset and $ffff);
+            end;
+          a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R11);
+          list.concat(taicpu.op_reg(A_MTCTR,NR_R11));
+          list.concat(taicpu.op_none(A_BCTR));
+          if (target_info.system = system_powerpc64_linux) then
+            { NOP needed for the linker...? }
+            list.concat(taicpu.op_none(A_NOP));
+        end;
+
+
+      var
+        make_global : boolean;
+      begin
+        if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
+          Internalerror(200006137);
+        if not assigned(procdef._class) or
+           (procdef.procoptions*[po_classmethod, po_staticmethod,
+             po_methodpointer, po_interrupt, po_iocheck]<>[]) then
+          Internalerror(200006138);
+        if procdef.owner.symtabletype<>ObjectSymtable then
+          Internalerror(200109191);
+
+        make_global:=false;
+        if (not current_module.is_unit) or
+           (cs_create_smart in current_settings.moduleswitches) or
+           (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
+          make_global:=true;
+
+        if make_global then
+          List.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0))
+        else
+          List.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
+
+        { set param1 interface to self  }
+        g_adjust_self_value(list,procdef,ioffset);
+
+        { case 4 }
+        if po_virtualmethod in procdef.procoptions then
+          begin
+            loadvmttor11;
+            op_onr11methodaddr;
+          end
+        { case 0 }
+        else
+          case target_info.system of
+            system_powerpc_darwin,
+            system_powerpc64_darwin:
+              list.concat(taicpu.op_sym(A_B,get_darwin_call_stub(procdef.mangledname)));
+            system_powerpc64_linux:
+              {$note ts:todo add GOT change?? - think not needed :) }
+              list.concat(taicpu.op_sym(A_B,current_asmdata.RefAsmSymbol('.' + procdef.mangledname)));
+            else
+              list.concat(taicpu.op_sym(A_B,current_asmdata.RefAsmSymbol(procdef.mangledname)))
+          end;
+        List.concat(Tai_symbol_end.Createname(labelname));
+      end;
+
 
 end.