Ver código fonte

Merged revisions 6394,6396-6397,6399,6413,6415-6416,6418-6419,6426,6432-6433,6435,6438-6440,6445,6449-6450,6473,6487-6488 via svnmerge from
svn+ssh://[email protected]/FPC/svn/fpc/branches/merged/fpc_2_3

........
r6394 | jonas | 2007-02-10 18:58:47 +0100 (Sat, 10 Feb 2007) | 4 lines

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

........
r6396 | jonas | 2007-02-10 20:16:06 +0100 (Sat, 10 Feb 2007) | 2 lines

+ darwin/ppc64 support for g_indirect_sym_load

........
r6397 | jonas | 2007-02-10 20:22:49 +0100 (Sat, 10 Feb 2007) | 4 lines

+ darwin/ppc64 support to ppc64's fixref
* moved ppc32 a_load_store to cgppc and use it for darwin/ppc64 as
well (its relocatable symbols are only 32 bits large)

........
r6399 | jonas | 2007-02-10 22:02:37 +0100 (Sat, 10 Feb 2007) | 4 lines

+ system_x86_64_darwin identifier
+ set default source system for system_x86_64_darwin and
system_powerpc64_darwin

........
r6413 | jonas | 2007-02-11 12:41:27 +0100 (Sun, 11 Feb 2007) | 2 lines

+ darwin/ppc64 support for signal routines

........
r6415 | jonas | 2007-02-11 13:54:53 +0100 (Sun, 11 Feb 2007) | 2 lines

* set abi of linux/ppc64 to abi_powerpc_sysv

........
r6416 | jonas | 2007-02-11 13:55:51 +0100 (Sun, 11 Feb 2007) | 2 lines

+ darwin/ppc64 source and target information

........
r6418 | jonas | 2007-02-11 14:19:55 +0100 (Sun, 11 Feb 2007) | 2 lines

* darwin/ppc64 compilation fixes

........
r6419 | jonas | 2007-02-11 14:22:22 +0100 (Sun, 11 Feb 2007) | 2 lines

* darwin/ppc64 needs the 32 bit version of a_loadaddr_ref_reg

........
r6426 | jonas | 2007-02-11 16:13:19 +0100 (Sun, 11 Feb 2007) | 2 lines

* fixed refaddr parsing for darwin/ppc64

........
r6432 | jonas | 2007-02-11 19:00:12 +0100 (Sun, 11 Feb 2007) | 2 lines

* changed darwin checks to use systems_darwin constant

........
r6433 | jonas | 2007-02-11 19:05:38 +0100 (Sun, 11 Feb 2007) | 3 lines

* handle non-multiple-of-4 offsets with 64 bit loads/stores for
darwin/ppc64

........
r6435 | jonas | 2007-02-11 19:06:40 +0100 (Sun, 11 Feb 2007) | 2 lines

* fixed 64 bit compilation

........
r6438 | jonas | 2007-02-11 19:22:34 +0100 (Sun, 11 Feb 2007) | 2 lines

+ compiled for darwin/ppc64

........
r6439 | jonas | 2007-02-11 20:24:42 +0100 (Sun, 11 Feb 2007) | 2 lines

* patch from Thomas to fix linux/ppc64

........
r6440 | jonas | 2007-02-11 20:25:15 +0100 (Sun, 11 Feb 2007) | 2 lines

* fixed setting source OS for darwin/ppc64

........
r6445 | jonas | 2007-02-11 22:30:07 +0100 (Sun, 11 Feb 2007) | 6 lines

* hack to work around strange darwin/ppc64 linker bug: it seems to
have problems if you put a global symbol at the end of a section
without any data following (at least in case of the resource strings
section) -> add dummy byte at the end for darwin/ppc64 (otherwise
it messes up the address of the first symbol stub entry)

........
r6449 | jonas | 2007-02-11 23:23:44 +0100 (Sun, 11 Feb 2007) | 4 lines

* cpupowerpc is defined for both ppc32 and ppc64 ->
changed to cpupowerpc32 to avoid defining source
wrongly on ppc64

........
r6450 | jonas | 2007-02-11 23:26:34 +0100 (Sun, 11 Feb 2007) | 3 lines

* disable jump tables for darwin/ppc64 for now, don't work
yet for some reason

........
r6473 | jonas | 2007-02-13 16:45:48 +0100 (Tue, 13 Feb 2007) | 3 lines

* R2 is a volatile and usable register under darwin/ppc64
* R13 is a reserved non-volatile register under darwin/ppc64 (tls)

........
r6487 | jonas | 2007-02-14 15:57:40 +0100 (Wed, 14 Feb 2007) | 2 lines

* fixed for darwin/ppc64

........
r6488 | jonas | 2007-02-14 15:58:56 +0100 (Wed, 14 Feb 2007) | 2 lines

* fixed for darwin/ppc64

........


Merged revisions 7039,7266 via svnmerge from
svn+ssh://[email protected]/FPC/svn/fpc/trunk

........
r7039 | tom_at_work | 2007-03-31 16:50:02 +0200 (Sat, 31 Mar 2007) | 1 line

* do NOT specify R0 as available volatile register. Fixes cycle on ppc64/linux. Most probably the compiler starts using it as temp register which leads to bad code since in some instructions R0 means zero, not the value of R0.
........
r7266 | tom_at_work | 2007-05-04 23:51:04 +0200 (Fri, 04 May 2007) | 1 line

* do not use R13 as available register because it is reserved for tls on ppc64/linux
........



Blocked revisions 6471,6479,6494 via svnmerge

........
r6471 | jonas | 2007-02-13 16:17:16 +0100 (Tue, 13 Feb 2007) | 3 lines

* include stabs support (can work on darwin/ppc64, but doesn't work
yet)

........
r6479 | jonas | 2007-02-13 20:40:50 +0100 (Tue, 13 Feb 2007) | 3 lines

* maxCrecordalign seems to have to be 8 rather 4, in spite of what
the ABI docs say (although they are contradictory to some extent)

........
r6494 | jonas | 2007-02-15 19:36:55 +0100 (Thu, 15 Feb 2007) | 3 lines

* set default debug info for darwin/ppc64 to dwarf2 since
it works better than stabs currently

........

git-svn-id: branches/fixes_2_2@8885 -

Jonas Maebe 18 anos atrás
pai
commit
6a44cc88f8

+ 4 - 0
.gitattributes

@@ -6456,6 +6456,10 @@ tests/test/cg/obj/darwin/powerpc/ctest.o -text
 tests/test/cg/obj/darwin/powerpc/tcext3.o -text
 tests/test/cg/obj/darwin/powerpc/tcext4.o -text
 tests/test/cg/obj/darwin/powerpc/tcext5.o -text
+tests/test/cg/obj/darwin/powerpc64/ctest.o -text
+tests/test/cg/obj/darwin/powerpc64/tcext3.o -text
+tests/test/cg/obj/darwin/powerpc64/tcext4.o -text
+tests/test/cg/obj/darwin/powerpc64/tcext5.o -text
 tests/test/cg/obj/freebsd/i386/ctest.o -text
 tests/test/cg/obj/freebsd/i386/tcext3.o -text
 tests/test/cg/obj/freebsd/i386/tcext4.o -text

+ 5 - 0
compiler/cresstr.pas

@@ -215,6 +215,11 @@ uses
         new_section(current_asmdata.asmlists[al_resourcestrings],sec_data,make_mangledname('RESSTR',current_module.localsymtable,'3_END'),sizeof(aint));
         current_asmdata.AsmLists[al_resourcestrings].concat(tai_symbol.createname_global(
           make_mangledname('RESSTR',current_module.localsymtable,'END'),AT_DATA,0));
+        { the darwin/ppc64 assembler or linker seems to have trouble       }
+        { if a section ends with a global label without any data after it. }
+        { So for safety, just put a dummy value here.                      }
+        if (target_info.system = system_powerpc64_darwin) then   
+          current_asmdata.asmlists[al_resourcestrings].concat(Tai_const.create_8bit(0));
       end;
 
 

+ 0 - 256
compiler/powerpc/cgcpu.pas

@@ -81,16 +81,12 @@ unit cgcpu;
         procedure g_save_standard_registers(list:TAsmList); override;
         procedure g_restore_standard_registers(list:TAsmList); override;
 
-        procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
-
         procedure g_concatcopy(list : TAsmList;const source,dest : treference;len : aint);override;
 
         { find out whether a is of the form 11..00..11b or 00..11...00. If }
         { 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
@@ -116,10 +112,6 @@ unit cgcpu;
         { instruction                                                      }
         function issimpleref(const ref: treference): boolean;
 
-        { contains the common code of a_load_reg_ref and a_load_ref_reg }
-        procedure a_load_store(list:TAsmList;op: tasmop;reg:tregister;
-                    ref: treference); override;
-
         function save_regs(list : TAsmList):longint;
         procedure restore_regs(list : TAsmList);
      end;
@@ -1497,88 +1489,6 @@ const
       end;
 
 
-     procedure tcgppc.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
-
-       var
-         ref2, tmpref: treference;
-
-       begin
-         ref2 := ref;
-         fixref(list,ref2);
-         if assigned(ref2.symbol) then
-           begin
-             if target_info.system = system_powerpc_macos then
-               begin
-                 if macos_direct_globals then
-                   begin
-                     reference_reset(tmpref);
-                     tmpref.offset := ref2.offset;
-                     tmpref.symbol := ref2.symbol;
-                     tmpref.base := NR_NO;
-                     list.concat(taicpu.op_reg_reg_ref(A_ADDI,r,NR_RTOC,tmpref));
-                   end
-                 else
-                   begin
-                     reference_reset(tmpref);
-                     tmpref.symbol := ref2.symbol;
-                     tmpref.offset := 0;
-                     tmpref.base := NR_RTOC;
-                     list.concat(taicpu.op_reg_ref(A_LWZ,r,tmpref));
-
-                     if ref2.offset <> 0 then
-                       begin
-                         reference_reset(tmpref);
-                         tmpref.offset := ref2.offset;
-                         tmpref.base:= r;
-                         list.concat(taicpu.op_reg_ref(A_LA,r,tmpref));
-                       end;
-                   end;
-
-                 if ref2.base <> NR_NO then
-                   list.concat(taicpu.op_reg_reg_reg(A_ADD,r,r,ref2.base));
-
-                 //list.concat(tai_comment.create(strpnew('*** a_loadaddr_ref_reg')));
-               end
-             else
-               begin
-
-                 { add the symbol's value to the base of the reference, and if the }
-                 { reference doesn't have a base, create one                       }
-                 reference_reset(tmpref);
-                 tmpref.offset := ref2.offset;
-                 tmpref.symbol := ref2.symbol;
-                 tmpref.relsymbol := ref2.relsymbol;
-                 tmpref.refaddr := addr_hi;
-                 if ref2.base<> NR_NO then
-                   begin
-                     list.concat(taicpu.op_reg_reg_ref(A_ADDIS,r,
-                       ref2.base,tmpref));
-                   end
-                 else
-                   list.concat(taicpu.op_reg_ref(A_LIS,r,tmpref));
-                 tmpref.base := NR_NO;
-                 tmpref.refaddr := addr_lo;
-                 { can be folded with one of the next instructions by the }
-                 { optimizer probably                                     }
-                 list.concat(taicpu.op_reg_reg_ref(A_ADDI,r,r,tmpref));
-               end
-           end
-         else if ref2.offset <> 0 Then
-           if ref2.base <> NR_NO then
-             a_op_const_reg_reg(list,OP_ADD,OS_32,ref2.offset,ref2.base,r)
-           { FixRef makes sure that "(ref.index <> R_NO) and (ref.offset <> 0)" never}
-           { occurs, so now only ref.offset has to be loaded                         }
-           else
-             a_load_const_reg(list,OS_32,ref2.offset,r)
-         else if ref2.index <> NR_NO Then
-           list.concat(taicpu.op_reg_reg_reg(A_ADD,r,ref2.base,ref2.index))
-         else if (ref2.base <> NR_NO) and
-                 (r <> ref2.base) then
-           a_load_reg_reg(list,OS_ADDR,OS_ADDR,ref2.base,r)
-         else
-           list.concat(taicpu.op_reg_const(A_LI,r,0));
-       end;
-
 { ************* concatcopy ************ }
 
 {$ifndef ppc603}
@@ -1770,78 +1680,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;
@@ -1976,100 +1814,6 @@ const
       end;
 
 
-    procedure tcgppc.a_load_store(list:TAsmList;op: tasmop;reg:tregister;
-       ref: treference);
-
-      var
-        tmpreg: tregister;
-        tmpref: treference;
-        largeOffset: Boolean;
-
-      begin
-        tmpreg := NR_NO;
-
-        if target_info.system = system_powerpc_macos then
-          begin
-            largeOffset:= (cardinal(ref.offset-low(smallint)) >
-                  high(smallint)-low(smallint));
-
-            if assigned(ref.symbol) then
-              begin {Load symbol's value}
-                tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
-
-                reference_reset(tmpref);
-                tmpref.symbol := ref.symbol;
-                tmpref.base := NR_RTOC;
-
-                if macos_direct_globals then
-                  list.concat(taicpu.op_reg_ref(A_LA,tmpreg,tmpref))
-                else
-                  list.concat(taicpu.op_reg_ref(A_LWZ,tmpreg,tmpref));
-              end;
-
-            if largeOffset then
-              begin {Add hi part of offset}
-                reference_reset(tmpref);
-
-                if Smallint(Lo(ref.offset)) < 0 then
-                  tmpref.offset := Hi(ref.offset) + 1 {Compensate when lo part is negative}
-                else
-                  tmpref.offset := Hi(ref.offset);
-
-                if (tmpreg <> NR_NO) then
-                  list.concat(taicpu.op_reg_reg_ref(A_ADDIS,tmpreg, tmpreg,tmpref))
-                else
-                  begin
-                    tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
-                    list.concat(taicpu.op_reg_ref(A_LIS,tmpreg,tmpref));
-                  end;
-              end;
-
-            if (tmpreg <> NR_NO) then
-              begin
-                {Add content of base register}
-                if ref.base <> NR_NO then
-                  list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,
-                    ref.base,tmpreg));
-
-                {Make ref ready to be used by op}
-                ref.symbol:= nil;
-                ref.base:= tmpreg;
-                if largeOffset then
-                  ref.offset := Smallint(Lo(ref.offset));
-
-                list.concat(taicpu.op_reg_ref(op,reg,ref));
-                //list.concat(tai_comment.create(strpnew('*** a_load_store indirect global')));
-              end
-            else
-              list.concat(taicpu.op_reg_ref(op,reg,ref));
-          end
-        else {if target_info.system <> system_powerpc_macos}
-          begin
-            if assigned(ref.symbol) or
-               (cardinal(ref.offset-low(smallint)) >
-                high(smallint)-low(smallint)) then
-              begin
-                tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
-                reference_reset(tmpref);
-                tmpref.symbol := ref.symbol;
-                tmpref.relsymbol := ref.relsymbol;
-                tmpref.offset := ref.offset;
-                tmpref.refaddr := addr_hi;
-                if ref.base <> NR_NO then
-                  list.concat(taicpu.op_reg_reg_ref(A_ADDIS,tmpreg,
-                    ref.base,tmpref))
-                else
-                  list.concat(taicpu.op_reg_ref(A_LIS,tmpreg,tmpref));
-                ref.base := tmpreg;
-                ref.refaddr := addr_lo;
-                list.concat(taicpu.op_reg_ref(op,reg,ref));
-              end
-            else
-              list.concat(taicpu.op_reg_ref(op,reg,ref));
-          end;
-      end;
-
-
     procedure tcg64fppc.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
       begin
         a_op64_reg_reg_reg(list,op,size,regsrc,regdst,regdst);

+ 91 - 120
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
@@ -177,7 +171,7 @@ end;
 
 function cgsize2string(const size : TCgSize) : string;
 const
-  cgsize_strings : array[TCgSize] of string[7] = (
+  cgsize_strings : array[TCgSize] of string[8] = (
     'OS_NO', 'OS_8', 'OS_16', 'OS_32', 'OS_64', 'OS_128', 'OS_S8', 'OS_S16', 'OS_S32',
     'OS_S64', 'OS_S128', 'OS_F32', 'OS_F64', 'OS_F80', 'OS_C64', 'OS_F128',
     'OS_M8', 'OS_M16', 'OS_M32', 'OS_M64', 'OS_M128', 'OS_MS8', 'OS_MS16', 'OS_MS32',
@@ -400,12 +394,22 @@ end;
 procedure tcgppc.init_register_allocators;
 begin
   inherited init_register_allocators;
-  rg[R_INTREGISTER] := trgcpu.create(R_INTREGISTER, R_SUBWHOLE,
-    [RS_R3, RS_R4, RS_R5, RS_R6, RS_R7, RS_R8,
-      RS_R9, RS_R10, RS_R11, RS_R12, RS_R31, RS_R30, RS_R29,
-      RS_R28, RS_R27, RS_R26, RS_R25, RS_R24, RS_R23, RS_R22,
-      RS_R21, RS_R20, RS_R19, RS_R18, RS_R17, RS_R16, RS_R15,
-      RS_R14], first_int_imreg, []);
+  if (target_info.system <> system_powerpc64_darwin) then
+    // r13 is tls, do not use, r2 is not available
+    rg[R_INTREGISTER] := trgcpu.create(R_INTREGISTER, R_SUBWHOLE,
+      [RS_R3, RS_R4, RS_R5, RS_R6, RS_R7, RS_R8,
+       RS_R9, RS_R10, RS_R11, RS_R12, RS_R31, RS_R30, RS_R29,
+       RS_R28, RS_R27, RS_R26, RS_R25, RS_R24, RS_R23, RS_R22,
+       RS_R21, RS_R20, RS_R19, RS_R18, RS_R17, RS_R16, RS_R15,
+       RS_R14], first_int_imreg, [])
+  else
+    { special for darwin/ppc64: r2 available volatile, r13 = tls }
+    rg[R_INTREGISTER] := trgcpu.create(R_INTREGISTER, R_SUBWHOLE,
+      [RS_R2, RS_R3, RS_R4, RS_R5, RS_R6, RS_R7, RS_R8,
+        RS_R9, RS_R10, RS_R11, RS_R12, RS_R31, RS_R30, RS_R29,
+        RS_R28, RS_R27, RS_R26, RS_R25, RS_R24, RS_R23, RS_R22,
+       RS_R21, RS_R20, RS_R19, RS_R18, RS_R17, RS_R16, RS_R15,
+       RS_R14], first_int_imreg, []);	
   rg[R_FPUREGISTER] := trgcpu.create(R_FPUREGISTER, R_SUBNONE,
     [RS_F0, RS_F1, RS_F2, RS_F3, RS_F4, RS_F5, RS_F6, RS_F7, RS_F8, RS_F9,
     RS_F10, RS_F11, RS_F12, RS_F13, RS_F31, RS_F30, RS_F29, RS_F28, RS_F27,
@@ -669,11 +673,11 @@ procedure tcgppc.a_load_const_reg(list: TAsmList; size: TCGSize; a: aint;
   begin
     if (lo(a) = 0) and (hi(a) <> 0) then begin
       { load only upper 32 bits, and shift }
-      load32bitconstant(list, size, hi(a), reg);
+      load32bitconstant(list, size, longint(hi(a)), reg);
       list.concat(taicpu.op_reg_reg_const(A_SLDI, reg, reg, 32));
     end else begin
       { load lower 32 bits }
-      extendssign := load32bitconstant(list, size, lo(a), reg);
+      extendssign := load32bitconstant(list, size, longint(lo(a)), reg);
       if (extendssign) and (hi(a) = 0) then
         { if upper 32 bits are zero, but loading the lower 32 bit resulted in automatic
           sign extension, clear those bits }
@@ -689,7 +693,7 @@ procedure tcgppc.a_load_const_reg(list: TAsmList; size: TCGSize; a: aint;
           - loading the lower 32 bits resulted in 0 in the upper 32 bits, and the upper
            32 bits should contain 0 }
         a_reg_alloc(list, NR_R0);
-        load32bitconstantR0(list, size, hi(a));
+        load32bitconstantR0(list, size, longint(hi(a)));
         { combine both registers }
         list.concat(taicpu.op_reg_reg_const_const(A_RLDIMI, reg, NR_R0, 32, 0));
         a_reg_dealloc(list, NR_R0);
@@ -964,7 +968,7 @@ var
       end else begin
         getmagic_unsignedN(sizeof(aWord)*8, a, u_magic, u_add, u_shift);
         { load magic in divreg }
-        cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, u_magic, divreg);
+        cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, aint(u_magic), divreg);
         current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_MULHDU, dst, src, divreg));
         if (u_add) then begin
           cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_SUB, OS_INT, dst, src, divreg);
@@ -1209,8 +1213,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);
@@ -1629,6 +1642,12 @@ var
   tempreg : TRegister;
 
 begin
+  if (target_info.system = system_powerpc64_darwin) then
+    begin
+      inherited a_loadaddr_ref_reg(list,ref,r);
+      exit;
+    end;
+
   ref2 := ref;
   fixref(list, ref2);
   { load a symbol }
@@ -1849,83 +1868,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);
@@ -1999,9 +1941,28 @@ begin
   list.concat(tai_comment.create(strpnew('fixref0 ' + ref2string(ref))));
   {$ENDIF EXTDEBUG}
 
+  if (target_info.system = system_powerpc64_darwin) and
+     assigned(ref.symbol) and
+     (ref.symbol.bind = AB_EXTERNAL) then
+    begin
+      tmpreg := g_indirect_sym_load(list,ref.symbol.name);
+      if (ref.base = NR_NO) then
+        ref.base := tmpreg
+      else if (ref.index = NR_NO) then
+        ref.index := tmpreg
+      else
+        begin
+          list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
+          ref.base := tmpreg;
+        end;
+      ref.symbol := nil;
+    end;
+
+
   { if we have to create PIC, add the symbol to the TOC/GOT }
   {$WARNING Hack for avoiding too long manglednames enabled!!}
-  if (cs_create_pic in current_settings.moduleswitches) and (assigned(ref.symbol) and
+  if (target_info.system <> system_powerpc64_darwin) and
+     (cs_create_pic in current_settings.moduleswitches) and (assigned(ref.symbol) and
     (length(ref.symbol.name) < MAX_GOT_SYMBOL_NAME_LENGTH_HACK)) then begin
     tmpreg := load_got_symbol(list, ref.symbol.name);
     if (ref.base = NR_NO) then
@@ -2039,11 +2000,44 @@ end;
 
 procedure tcgppc.a_load_store(list: TAsmList; op: tasmop; reg: tregister;
   ref: treference);
+
+  procedure maybefixup64bitoffset;
+    var
+      tmpreg: tregister;
+    begin
+      { for some instructions we need to check that the offset is divisible by at
+       least four. If not, add the bytes which are "off" to the base register and
+       adjust the offset accordingly }
+      case op of
+        A_LD, A_LDU, A_STD, A_STDU, A_LWA :
+           if ((ref.offset mod 4) <> 0) then begin
+            tmpreg := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
+    
+            if (ref.base <> NR_NO) then begin
+              a_op_const_reg_reg(list, OP_ADD, OS_ADDR, ref.offset mod 4, ref.base, tmpreg);
+              ref.base := tmpreg;
+            end else begin
+              list.concat(taicpu.op_reg_const(A_LI, tmpreg, ref.offset mod 4));
+              ref.base := tmpreg;
+            end;
+            ref.offset := (ref.offset div 4) * 4;
+          end;
+      end;
+    end;
+
 var
   tmpreg, tmpreg2: tregister;
   tmpref: treference;
   largeOffset: Boolean;
 begin
+  if (target_info.system = system_powerpc64_darwin) then
+    begin
+      { darwin/ppc64 works with 32 bit relocatable symbol addresses }
+      maybefixup64bitoffset;
+      inherited a_load_store(list,op,reg,ref);
+      exit
+    end;
+
   { at this point there must not be a combination of values in the ref treference
     which is not possible to directly map to instructions of the PowerPC architecture }
   if (ref.index <> NR_NO) and ((ref.offset <> 0) or (assigned(ref.symbol))) then
@@ -2061,24 +2055,7 @@ begin
     exit;
   end;
 
-  { for some instructions we need to check that the offset is divisible by at
-   least four. If not, add the bytes which are "off" to the base register and
-   adjust the offset accordingly }
-  case op of
-    A_LD, A_LDU, A_STD, A_STDU, A_LWA :
-       if ((ref.offset mod 4) <> 0) then begin
-        tmpreg := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
-
-        if (ref.base <> NR_NO) then begin
-          a_op_const_reg_reg(list, OP_ADD, OS_ADDR, ref.offset mod 4, ref.base, tmpreg);
-          ref.base := tmpreg;
-        end else begin
-          list.concat(taicpu.op_reg_const(A_LI, tmpreg, ref.offset mod 4));
-          ref.base := tmpreg;
-        end;
-        ref.offset := (ref.offset div 4) * 4;
-      end;
-  end;
+  maybefixup64bitoffset;
   {$IFDEF EXTDEBUG}
   list.concat(tai_comment.create(strpnew('a_load_store1 ' + BoolToStr(ref.refaddr = addr_pic))));
   {$ENDIF EXTDEBUG}
@@ -2183,12 +2160,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;

+ 2 - 0
compiler/powerpc64/cpupara.pas

@@ -69,6 +69,8 @@ function tppcparamanager.get_volatile_registers_int(calloption:
   tproccalloption): tcpuregisterset;
 begin
   result := [RS_R3..RS_R12];
+  if (target_info.system = system_powerpc64_darwin) then
+    include(result,RS_R2);
 end;
 
 function tppcparamanager.get_volatile_registers_fpu(calloption:

+ 4 - 1
compiler/powerpc64/cputarg.pas

@@ -1,7 +1,7 @@
 {
     Copyright (c) 2001-2002 by Peter Vreman
 
-    Includes the powerpc dependent target units
+    Includes the powerpc64 dependent target units
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -38,6 +38,9 @@ implementation
     {$ifndef NOTARGETLINUX}
       ,t_linux
     {$endif}
+    {$ifndef NOTARGETBSD}
+      ,t_bsd
+    {$endif}
 
 {**************************************
              Assemblers

+ 12 - 0
compiler/powerpc64/rappcgas.pas

@@ -116,6 +116,18 @@ begin
         oper.opr.ref.refaddr := addr_highest                
       else
         Message(asmr_e_invalid_reference_syntax);
+
+      { darwin/ppc64's relocation symbols are 32 bits }
+      if (target_info.system = system_powerpc64_darwin) then
+        case oper.opr.ref.refaddr of
+          addr_low:
+            oper.opr.ref.refaddr:=addr_lo;
+          addr_higha:
+            oper.opr.ref.refaddr:=addr_hi;
+          else if (oper.opr.ref.refaddr<>addr_no) then
+            Message(asmr_e_invalid_reference_syntax);
+        end;
+
       Consume(AS_ID);
     end
     else

+ 283 - 1
compiler/ppcgen/cgppc.pas

@@ -45,6 +45,8 @@ unit cgppc;
         procedure a_load_reg_ref(list: TAsmList; fromsize, tosize: TCGSize;
           reg: tregister; const ref: treference); override;
 
+        procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
+
         { fpu move instructions }
         procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
         procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override;
@@ -57,16 +59,24 @@ 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;
         function  fixref(list: TAsmList; var ref: treference): boolean; virtual; abstract;
-        procedure a_load_store(list:TAsmList;op: tasmop;reg:tregister;ref: treference);virtual;abstract;
+        { contains the common code of a_load_reg_ref and a_load_ref_reg }
+        procedure a_load_store(list:TAsmList;op: tasmop;reg:tregister;ref: treference);virtual;
 
         { creates the correct branch instruction for a given combination }
         { 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 +92,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
@@ -173,6 +189,90 @@ unit cgppc;
       end;
 
 
+     procedure tcgppcgen.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
+
+       var
+         ref2, tmpref: treference;
+
+       begin
+         ref2 := ref;
+         fixref(list,ref2);
+         if assigned(ref2.symbol) then
+           begin
+             if target_info.system = system_powerpc_macos then
+               begin
+                 if macos_direct_globals then
+                   begin
+                     reference_reset(tmpref);
+                     tmpref.offset := ref2.offset;
+                     tmpref.symbol := ref2.symbol;
+                     tmpref.base := NR_NO;
+                     list.concat(taicpu.op_reg_reg_ref(A_ADDI,r,NR_RTOC,tmpref));
+                   end
+                 else
+                   begin
+                     reference_reset(tmpref);
+                     tmpref.symbol := ref2.symbol;
+                     tmpref.offset := 0;
+                     tmpref.base := NR_RTOC;
+                     list.concat(taicpu.op_reg_ref(A_LWZ,r,tmpref));
+
+                     if ref2.offset <> 0 then
+                       begin
+                         reference_reset(tmpref);
+                         tmpref.offset := ref2.offset;
+                         tmpref.base:= r;
+                         list.concat(taicpu.op_reg_ref(A_LA,r,tmpref));
+                       end;
+                   end;
+
+                 if ref2.base <> NR_NO then
+                   list.concat(taicpu.op_reg_reg_reg(A_ADD,r,r,ref2.base));
+
+                 //list.concat(tai_comment.create(strpnew('*** a_loadaddr_ref_reg')));
+               end
+             else
+               begin
+
+                 { add the symbol's value to the base of the reference, and if the }
+                 { reference doesn't have a base, create one                       }
+                 reference_reset(tmpref);
+                 tmpref.offset := ref2.offset;
+                 tmpref.symbol := ref2.symbol;
+                 tmpref.relsymbol := ref2.relsymbol;
+                 tmpref.refaddr := addr_hi;
+                 if ref2.base<> NR_NO then
+                   begin
+                     list.concat(taicpu.op_reg_reg_ref(A_ADDIS,r,
+                       ref2.base,tmpref));
+                   end
+                 else
+                   list.concat(taicpu.op_reg_ref(A_LIS,r,tmpref));
+                 tmpref.base := NR_NO;
+                 tmpref.refaddr := addr_lo;
+                 { can be folded with one of the next instructions by the }
+                 { optimizer probably                                     }
+                 list.concat(taicpu.op_reg_reg_ref(A_ADDI,r,r,tmpref));
+               end
+           end
+         else if ref2.offset <> 0 Then
+           if ref2.base <> NR_NO then
+             a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref2.offset,ref2.base,r)
+           { FixRef makes sure that "(ref.index <> R_NO) and (ref.offset <> 0)" never}
+           { occurs, so now only ref.offset has to be loaded                         }
+           else
+             a_load_const_reg(list,OS_ADDR,ref2.offset,r)
+         else if ref2.index <> NR_NO Then
+           list.concat(taicpu.op_reg_reg_reg(A_ADD,r,ref2.base,ref2.index))
+         else if (ref2.base <> NR_NO) and
+                 (r <> ref2.base) then
+           a_load_reg_reg(list,OS_ADDR,OS_ADDR,ref2.base,r)
+         else
+           list.concat(taicpu.op_reg_const(A_LI,r,0));
+       end;
+
+
+
     { calling a procedure by address }
     procedure tcgppcgen.a_call_reg(list : TAsmList;reg: tregister);
       begin
@@ -421,6 +521,188 @@ 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);
+          if (target_info.system = system_powerpc64_linux) then
+            begin
+              reference_reset_base(href, NR_R11, 0);
+              a_load_ref_reg(list, OS_ADDR, OS_ADDR, href, NR_R11);
+            end;
+          list.concat(taicpu.op_reg(A_MTCTR,NR_R11));
+          list.concat(taicpu.op_none(A_BCTR));
+          if (target_info.system = system_powerpc64_linux) then
+            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;
+
+
+    procedure tcgppcgen.a_load_store(list:TAsmList;op: tasmop;reg:tregister;
+       ref: treference);
+
+      var
+        tmpreg: tregister;
+        tmpref: treference;
+        largeOffset: Boolean;
+
+      begin
+        tmpreg := NR_NO;
+        largeOffset:= hasLargeOffset(ref);
+
+        if target_info.system = system_powerpc_macos then
+          begin
+
+            if assigned(ref.symbol) then
+              begin {Load symbol's value}
+                tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+
+                reference_reset(tmpref);
+                tmpref.symbol := ref.symbol;
+                tmpref.base := NR_RTOC;
+
+                if macos_direct_globals then
+                  list.concat(taicpu.op_reg_ref(A_LA,tmpreg,tmpref))
+                else
+                  list.concat(taicpu.op_reg_ref(A_LWZ,tmpreg,tmpref));
+              end;
+
+            if largeOffset then
+              begin {Add hi part of offset}
+                reference_reset(tmpref);
+
+                if Smallint(Lo(ref.offset)) < 0 then
+                  tmpref.offset := Hi(ref.offset) + 1 {Compensate when lo part is negative}
+                else
+                  tmpref.offset := Hi(ref.offset);
+
+                if (tmpreg <> NR_NO) then
+                  list.concat(taicpu.op_reg_reg_ref(A_ADDIS,tmpreg, tmpreg,tmpref))
+                else
+                  begin
+                    tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+                    list.concat(taicpu.op_reg_ref(A_LIS,tmpreg,tmpref));
+                  end;
+              end;
+
+            if (tmpreg <> NR_NO) then
+              begin
+                {Add content of base register}
+                if ref.base <> NR_NO then
+                  list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,
+                    ref.base,tmpreg));
+
+                {Make ref ready to be used by op}
+                ref.symbol:= nil;
+                ref.base:= tmpreg;
+                if largeOffset then
+                  ref.offset := Smallint(Lo(ref.offset));
+
+                list.concat(taicpu.op_reg_ref(op,reg,ref));
+                //list.concat(tai_comment.create(strpnew('*** a_load_store indirect global')));
+              end
+            else
+              list.concat(taicpu.op_reg_ref(op,reg,ref));
+          end
+        else {if target_info.system <> system_powerpc_macos}
+          begin
+            if assigned(ref.symbol) or
+               largeOffset then
+              begin
+                tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+                reference_reset(tmpref);
+                tmpref.symbol := ref.symbol;
+                tmpref.relsymbol := ref.relsymbol;
+                tmpref.offset := ref.offset;
+                tmpref.refaddr := addr_hi;
+                if ref.base <> NR_NO then
+                  list.concat(taicpu.op_reg_reg_ref(A_ADDIS,tmpreg,
+                    ref.base,tmpref))
+                else
+                  list.concat(taicpu.op_reg_ref(A_LIS,tmpreg,tmpref));
+                ref.base := tmpreg;
+                ref.refaddr := addr_lo;
+                list.concat(taicpu.op_reg_ref(op,reg,ref));
+              end
+            else
+              list.concat(taicpu.op_reg_ref(op,reg,ref));
+          end;
+      end;
+
 
 end.
 

+ 1 - 1
compiler/ppcgen/ngppcset.pas

@@ -65,7 +65,7 @@ implementation
 
     function tgppccasenode.has_jumptable : boolean;
       begin
-        has_jumptable:=true;
+        has_jumptable:=(target_info.system <> system_powerpc64_darwin);
       end;
 
 

+ 12 - 0
compiler/systems.pas

@@ -827,6 +827,14 @@ begin
     default_target(system_x86_64_freebsd);
     {$define default_target_set}
    {$endif}
+   {$ifdef darwin}
+    default_target(system_x86_64_darwin);
+    {$define source_system_set}
+   {$endif}
+   { default is linux }
+   {$ifndef source_system_set}
+    default_target(system_x86_64_linux);
+   {$endif source_system_set}
   {$endif cpux86_64}
   { default is linux }
   {$ifndef default_target_set}
@@ -874,8 +882,12 @@ begin
     default_target(source_info.system);
     {$define default_target_set}
   {$else cpupowerpc64}
+  {$ifdef darwin}
+    default_target(system_powerpc64_darwin);
+  {$else darwin}
     default_target(system_powerpc64_linux);
     {$define default_target_set}
+  {$endif darwin}
   {$endif cpupowerpc64}
 {$endif POWERPC64}
 

+ 7 - 2
compiler/systems/i_bsd.pas

@@ -603,12 +603,17 @@ initialization
      set_source_info(system_m68k_NetBSD_info);
   {$endif NetBSD}
 {$endif cpu68}
-{$ifdef cpupowerpc}
+{$ifdef cpupowerpc32}
   {$ifdef Darwin}
      set_source_info(system_powerpc_darwin_info);
   {$endif Darwin}
   {$ifdef NetBSD}
      set_source_info(system_powerpc_netbsd_info);
   {$endif}
-{$endif cpu68}
+{$endif cpupowerpc32}
+{$ifdef cpupowerpc64}
+  {$ifdef Darwin}
+     set_source_info(system_powerpc64_darwin_info);
+  {$endif Darwin}
+{$endif powerpc64}
 end.

+ 1 - 1
compiler/systems/i_linux.pas

@@ -344,7 +344,7 @@ unit i_linux;
               );
             first_parm_offset : 8;
             stacksize    : 10*1024*1024;
-            abi : abi_default
+            abi : abi_powerpc_sysv
           );
 
        system_alpha_linux_info : tsysteminfo =

+ 16 - 9
compiler/systems/t_bsd.pas

@@ -207,7 +207,7 @@ Constructor TLinkerBSD.Create;
 begin
   Inherited Create;
   if not Dontlinkstdlibpath Then
-   if not(target_info.system in [system_powerpc_darwin,system_i386_darwin]) then
+   if not(target_info.system in systems_darwin) then
      LibrarySearchPath.AddPath('/lib;/usr/lib;/usr/X11R6/lib',true)
    else
      { Mac OS X doesn't have a /lib }
@@ -221,12 +221,12 @@ procedure TLinkerBSD.SetDefaultInfo;
 }
 begin
   LibrarySuffix:=' ';
-  LdSupportsNoResponseFile := (target_info.system in [system_m68k_netbsd,system_powerpc_darwin,system_i386_darwin]);
+  LdSupportsNoResponseFile := (target_info.system in ([system_m68k_netbsd]+systems_darwin));
   with Info do
    begin
      if LdSupportsNoResponseFile then
        begin
-         if not(target_info.system in [system_powerpc_darwin,system_i386_darwin]) then
+         if not(target_info.system in systems_darwin) then
            begin
              ExeCmd[1]:='ld $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP -L. -o $EXE `cat $RES`';
              DllCmd[1]:='ld $OPT -shared -L. -o $EXE `cat $RES`'
@@ -245,7 +245,7 @@ begin
          ExeCmd[1]:='ld $OPT $DYNLINK $STATIC  $GCSECTIONS $STRIP -L. -o $EXE $RES';
          DllCmd[1]:='ld $OPT $INIT $FINI $SONAME -shared -L. -o $EXE $RES';
        end;
-     if not(target_info.system in [system_powerpc_darwin,system_i386_darwin]) then
+     if not(target_info.system in systems_darwin) then
        DllCmd[2]:='strip --strip-unneeded $EXE'
      else
        DllCmd[2]:='strip -x $EXE';
@@ -257,7 +257,7 @@ procedure TLinkerBSD.LoadPredefinedLibraryOrder;
 // put your linkorder/linkalias overrides here.
 // Note: assumes only called when reordering/aliasing is used.
 Begin
-  if not(target_info.system in [system_powerpc_darwin,system_i386_darwin]) then
+  if not(target_info.system in systems_darwin) then
     begin
       if (target_info.system =system_i386_freebsd) and
          not (cs_link_no_default_lib_order in  current_settings.globalswitches) Then
@@ -297,7 +297,7 @@ Var
 begin
   WriteResponseFile:=False;
   ReOrder:=False;
-  IsDarwin:=target_info.system in [system_powerpc_darwin,system_i386_darwin];
+  IsDarwin:=target_info.system in systems_darwin;
 { set special options for some targets }
   if not IsDarwin Then
     begin
@@ -585,20 +585,20 @@ begin
 
   if (cs_link_smart in current_settings.globalswitches) and
      (tf_smartlink_sections in target_info.flags) then
-    if not(target_info.system in [system_powerpc_darwin,system_i386_darwin]) then
+    if not(target_info.system in systems_darwin) then
       GCSectionsStr:='--gc-sections'
     else
       // warning: this option only exists for 32 bit under Mac OS X, maybe the default for 64 bit?
       GCSectionsStr:='-dead_strip';
 
-   if(not(target_info.system in [system_powerpc_darwin,system_i386_darwin]) and
+   if(not(target_info.system in systems_darwin) and
       (cs_profile in current_settings.moduleswitches)) or
      ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
    DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
 
   if CShared Then
    begin
-   if not(target_info.system in [system_powerpc_darwin,system_i386_darwin]) then
+   if not(target_info.system in systems_darwin) then
      DynLinKStr:=DynLinkStr+' --shared'
     else
      DynLinKStr:=DynLinkStr+' -dynamic'; // one dash!
@@ -718,9 +718,16 @@ initialization
   RegisterImport(system_powerpc_darwin,timportlibdarwin);
   RegisterExport(system_powerpc_darwin,texportlibbsd);
   RegisterTarget(system_powerpc_darwin_info);
+
   RegisterExternalLinker(system_powerpc_netbsd_info,TLinkerBSD);
   RegisterImport(system_powerpc_netbsd,timportlibbsd);
   RegisterExport(system_powerpc_netbsd,texportlibbsd);
   RegisterTarget(system_powerpc_netbsd_info);
 {$endif powerpc}
+{$ifdef powerpc64}
+  RegisterExternalLinker(system_powerpc64_darwin_info,TLinkerBSD);
+  RegisterImport(system_powerpc64_darwin,timportlibdarwin);
+  RegisterExport(system_powerpc64_darwin,texportlibbsd);
+  RegisterTarget(system_powerpc64_darwin_info);
+{$endif powerpc64}
 end.

+ 5 - 0
rtl/bsd/system.pp

@@ -147,6 +147,11 @@ begin
   { initialize handler                    }
   act.sa_handler :=@SignalToRunError;
   act.sa_flags:=SA_SIGINFO;
+{$if defined(darwin) and defined(cpu64)}
+  act.sa_flags:=SA_SIGINFO or SA_64REGSET;
+{$else}
+  act.sa_flags:=SA_SIGINFO;
+{$endif}
   FpSigAction(SIGFPE,act,oldact);
   FpSigAction(SIGSEGV,act,oldact);
   FpSigAction(SIGBUS,act,oldact);

+ 15 - 15
rtl/darwin/console.pp

@@ -2083,7 +2083,7 @@ Function KDSETMODE(fd:longint;param1 : longint):boolean;
  }
 
 Begin
- KDSETMODE:=FpIoctl(fd,nr_KDSETMODE,pointer(param1))=0;
+ KDSETMODE:=FpIoctl(fd,nr_KDSETMODE,pointer(ptrint(param1)))=0;
 end;
 
 Function KDSBORDER(fd:longint;param1 : longint):boolean;
@@ -2091,7 +2091,7 @@ Function KDSBORDER(fd:longint;param1 : longint):boolean;
  }
 
 Begin
- KDSBORDER:=FpIoctl(fd,nr_KDSBORDER,pointer(param1))=0;
+ KDSBORDER:=FpIoctl(fd,nr_KDSBORDER,pointer(ptrint(param1)))=0;
 end;
 
 Function KDRASTER(fd:longint;var param1 : scr_size_t):boolean;
@@ -2310,7 +2310,7 @@ Function CONS_SETWINORG(fd:longint;param1 : longint):boolean;
  }
 
 Begin
- CONS_SETWINORG:=FpIoctl(fd,nr_CONS_SETWINORG,pointer(param1))=0;
+ CONS_SETWINORG:=FpIoctl(fd,nr_CONS_SETWINORG,pointer(ptrint(param1)))=0;
 end;
 
 Function CONS_SETKBD(fd:longint;param1 : longint):boolean;
@@ -2318,7 +2318,7 @@ Function CONS_SETKBD(fd:longint;param1 : longint):boolean;
  }
 
 Begin
- CONS_SETKBD:=FpIoctl(fd,nr_CONS_SETKBD,pointer(param1))=0;
+ CONS_SETKBD:=FpIoctl(fd,nr_CONS_SETKBD,pointer(ptrint(param1)))=0;
 end;
 
 Function CONS_RELKBD(fd:longint):boolean;
@@ -2377,7 +2377,7 @@ Function VT_RELDISP(fd:longint;param1 : longint):boolean;
  }
 
 Begin
- VT_RELDISP:=FpIoctl(fd,nr_VT_RELDISP,pointer(param1))=0;
+ VT_RELDISP:=FpIoctl(fd,nr_VT_RELDISP,pointer(ptrint(param1)))=0;
 end;
 
 Function VT_ACTIVATE(fd:longint;param1 : longint):boolean;
@@ -2385,7 +2385,7 @@ Function VT_ACTIVATE(fd:longint;param1 : longint):boolean;
  }
 
 Begin
- VT_ACTIVATE:=FpIoctl(fd,nr_VT_ACTIVATE,pointer(param1))=0;
+ VT_ACTIVATE:=FpIoctl(fd,nr_VT_ACTIVATE,pointer(ptrint(param1)))=0;
 end;
 
 Function VT_WAITACTIVE(fd:longint;param1 : longint):boolean;
@@ -2393,7 +2393,7 @@ Function VT_WAITACTIVE(fd:longint;param1 : longint):boolean;
  }
 
 Begin
- VT_WAITACTIVE:=FpIoctl(fd,nr_VT_WAITACTIVE,pointer(param1))=0;
+ VT_WAITACTIVE:=FpIoctl(fd,nr_VT_WAITACTIVE,pointer(ptrint(param1)))=0;
 end;
 
 Function VT_GETACTIVE(fd:longint;var param1 : longint):boolean;
@@ -3152,7 +3152,7 @@ Function KDSKBMODE(fd:longint;param1 : longint):boolean;
  }
 
 Begin
- KDSKBMODE:=FpIoctl(fd,nr_KDSKBMODE,pointer(param1))=0;
+ KDSKBMODE:=FpIoctl(fd,nr_KDSKBMODE,pointer(ptrint(param1)))=0;
 end;
 
 Function KDMKTONE(fd:longint;param1 : longint):boolean;
@@ -3160,7 +3160,7 @@ Function KDMKTONE(fd:longint;param1 : longint):boolean;
  }
 
 Begin
- KDMKTONE:=FpIoctl(fd,nr_KDMKTONE,pointer(param1))=0;
+ KDMKTONE:=FpIoctl(fd,nr_KDMKTONE,pointer(ptrint(param1)))=0;
 end;
 
 {$ifndef definconsole}
@@ -3176,7 +3176,7 @@ Function KDSETMODE(fd:longint;param1 : longint):boolean;
  }
 
 Begin
- KDSETMODE:=FpIoctl(fd,nr_KDSETMODE,pointer(param1))=0;
+ KDSETMODE:=FpIoctl(fd,nr_KDSETMODE,pointer(ptrint(param1)))=0;
 end;
 
 Function KDSBORDER(fd:longint;param1 : longint):boolean;
@@ -3184,7 +3184,7 @@ Function KDSBORDER(fd:longint;param1 : longint):boolean;
  }
 
 Begin
- KDSBORDER:=FpIoctl(fd,nr_KDSBORDER,pointer(param1))=0;
+ KDSBORDER:=FpIoctl(fd,nr_KDSBORDER,pointer(ptrint(param1)))=0;
 end;
 {$endif}
 Function KDGKBSTATE(fd:longint;var param1 : longint):boolean;
@@ -3199,7 +3199,7 @@ Function KDSKBSTATE(fd:longint;param1 : longint):boolean;
  }
 
 Begin
- KDSKBSTATE:=FpIoctl(fd,nr_KDSKBSTATE,pointer(param1))=0;
+ KDSKBSTATE:=FpIoctl(fd,nr_KDSKBSTATE,pointer(ptrint(param1)))=0;
 end;
 
 Function KDENABIO(fd:longint):boolean;
@@ -3223,7 +3223,7 @@ Function KIOCSOUND(fd:longint;param1 : longint):boolean;
  }
 
 Begin
- KIOCSOUND:=FpIoctl(fd,nr_KIOCSOUND,pointer(param1))=0;
+ KIOCSOUND:=FpIoctl(fd,nr_KIOCSOUND,pointer(ptrint(param1)))=0;
 end;
 
 Function KDGKBTYPE(fd:longint;var param1 : longint):boolean;
@@ -3245,7 +3245,7 @@ Function KDSETLED(fd:longint;param1 : longint):boolean;
  }
 
 Begin
- KDSETLED:=FpIoctl(fd,nr_KDSETLED,pointer(param1))=0;
+ KDSETLED:=FpIoctl(fd,nr_KDSETLED,pointer(ptrint(param1)))=0;
 end;
 
 Function KDSETRAD(fd:longint;param1 : longint):boolean;
@@ -3253,7 +3253,7 @@ Function KDSETRAD(fd:longint;param1 : longint):boolean;
  }
 
 Begin
- KDSETRAD:=FpIoctl(fd,nr_KDSETRAD,pointer(param1))=0;
+ KDSETRAD:=FpIoctl(fd,nr_KDSETRAD,pointer(ptrint(param1)))=0;
 end;
 {$ifndef definconsole}
 

+ 6 - 1
rtl/darwin/powerpc/sig_cpu.inc

@@ -79,7 +79,7 @@
   { Structure used in sigstack call. }
     tdarwin_stack_t = record
         ss_sp    : pchar;        { signal stack base }
-        ss_size  : cint;         { signal stack length }
+        ss_size  : clong;         { signal stack length }
         ss_flags : cint;         { SA_DISABLE and/or SA_ONSTACK }
     end;
 
@@ -249,8 +249,13 @@
 {$packrecords C}
 
      mcontext_t = record
+{$ifdef cpu64}
+        es: ppc_exception_state64_t;
+        ss: ppc_thread_state64_t;
+{$else cpu64}
         es: ppc_exception_state_t;
         ss: ppc_thread_state_t;
+{$endif cpu64}
         fs: ppc_float_state_t;
         vs: ppc_vector_state_t;
      end;

+ 11 - 12
rtl/darwin/signal.inc

@@ -66,11 +66,13 @@
     SA_NOCLDSTOP = 8;
     SA_ONSTACK   = $001; { take signal on signal stack }
     SA_RESTART   = $002; { restart system call on signal return }
+    SA_DISABLE   = $004; { disable taking signals on alternate stack }
     SA_RESETHAND = $004; { reset to SIG_DFL when taking signal }
     SA_NODEFER   = $010; { don't mask the signal we're delivering }
     SA_NOCLDWAIT = $020; { don't keep zombies around }
     SA_SIGINFO   = $040; { signal handler with SA_SIGINFO args }
     SA_USERTRAMP = $100; { SUNOS compat: Do not bounce off kernel's sigtramp }
+    SA_64REGSET  = $200; { SUNOS compat: Do not bounce off kernel's sigtramp }
 
   { hangup  }
      SIGHUP = 1;
@@ -173,15 +175,15 @@
     Sigset=sigset_t;
     PSigSet = ^TSigSet;
 
-{$ifdef cpupowerpc}
+{$if defined(cpupowerpc) or defined(cpupowerpc64)}
     {$include powerpc/sig_cpu.inc}    { SigContextRec }
-{$else cpupowerpc}
+{$else cpupowerpc or cpupowerpc64}
 {$ifdef cpui386}
     {$include i386/sig_cpu.inc}       { SigContextRec }
 {$else cpui386}
     {$error Unsupported cpu type!}
 {$endif cpui386}
-{$endif cpupowerpc}
+{$endif cpupowerpc or cpupowerpc64}
 
 
 
@@ -223,11 +225,11 @@ const
   type
      sigaltstack = record
   { signal stack base  }
-          ss_sp : ^char;
+          ss_sp : pchar;
   { signal stack length  }
-          ss_size : longint;
+          ss_size : clong;
   { SA_DISABLE and/or SA_ONSTACK  }
-          ss_flags : longint;
+          ss_flags : cint;
        end;
 
   { minimum allowable stack  }
@@ -245,11 +247,11 @@ const
   type
      sigvec = record
   { signal handler  }
-          sv_handler : procedure ;
+          sv_handler : procedure(para: cint);
   { signal mask to apply  }
-          sv_mask : longint;
+          sv_mask : cint;
   { see signal options below  }
-          sv_flags : longint;
+          sv_flags : cint;
        end;
 
 
@@ -268,6 +270,3 @@ const
      FPE_FLTSUB    =  6;  { subscript out of range -NOTIMP on Mac OS X 10.4.7 }
      FPE_INTDIV    =  7;  { integer divide by zero -NOTIMP on Mac OS X 10.4.7 }
      FPE_INTOVF    =  8;  { integer overflow -NOTIMP on Mac OS X 10.4.7 }
-
-
-

+ 2 - 2
rtl/darwin/termiosproc.inc

@@ -85,7 +85,7 @@ end;
 
 Function TCSetPGrp(fd,id:cint):cint;{$ifdef VER2_0}inline;{$endif}
 begin
-  TCSetPGrp:=fpIOCtl(fd,TIOCSPGRP,pointer(id));
+  TCSetPGrp:=fpIOCtl(fd,TIOCSPGRP,pointer(ptrint(id)));
 end;
 
 
@@ -111,7 +111,7 @@ end;
 
 Function TCFlush(fd,qsel:cint):cint;  {$ifdef VER2_0}inline;{$endif}
 begin
-  TCFlush:=fpIOCtl(fd,TIOCFLUSH,pointer(qsel));
+  TCFlush:=fpIOCtl(fd,TIOCFLUSH,pointer(ptrint(qsel)));
 end;
 
 Function IsATTY (Handle:cint):cint;

+ 7 - 0
rtl/powerpc64/math.inc

@@ -52,6 +52,8 @@ asm
   ld r3, -8(r1)
 end;
 
+{$ifndef FPC_SYSTEM_HAS_ROUND}
+
 {$define FPC_SYSTEM_HAS_ROUND}
 function fpc_round_real(d : valreal) : int64; compilerproc;assembler; nostackframe;
 { exactly the same as trunc, except that one fctiwz has become fctiw }
@@ -62,6 +64,7 @@ asm
   stfd  f1, -8(r1)
   ld r3, -8(r1)
 end;
+{$endif not FPC_SYSTEM_HAS_ROUND}
 
 {****************************************************************************
                          Int to real helpers
@@ -90,11 +93,15 @@ const
 var
   temp1, temp2: qword;
 asm
+{$ifndef darwin}
   // load 2^32 into f4
   lis   r4, longint_to_real_helper@highesta
   ori   r4, r4, longint_to_real_helper@highera
   sldi  r4, r4, 32
   oris  r4, r4, longint_to_real_helper@ha
+{$else darwin}
+  lis   r4, longint_to_real_helper@ha
+{$endif darwin}
   lfd   f4, longint_to_real_helper@l(r4)
 
   rldicl r4,r3,32,32  // isolate high half

BIN
tests/test/cg/obj/darwin/powerpc64/ctest.o


BIN
tests/test/cg/obj/darwin/powerpc64/tcext3.o


BIN
tests/test/cg/obj/darwin/powerpc64/tcext4.o


BIN
tests/test/cg/obj/darwin/powerpc64/tcext5.o


+ 4 - 0
tests/webtbs/tw7851a.pp

@@ -38,7 +38,11 @@ asm
   lwz r0, retaddr
 {$else}
   std r0, retaddr
+{$ifdef linux}
   bl .TMyObject.Test2
+{$else linux}
+  bl TMyObject.Test2
+{$endif linux}
   ld r0, retaddr
 {$endif}
   mtlr r0

+ 4 - 0
tests/webtbs/tw8153a.pp

@@ -16,8 +16,12 @@ asm
 // for simplicity sake do not bother about setting the GOT and
 // environment pointer correctly
   ld r4,0(r3)
+{$ifdef linux}
   ld r4,+vmtoffset tc.v(r4)
   ld r4,0(r4)
+{$else linux}
+  ld r4,+vmtoffset tc.v(r4)
+{$endif linux}
 {$else}
   lwz r4,0(r3)
   lwz r4,+vmtoffset tc.v(r4)