mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 08:19:36 +01:00 
			
		
		
		
	+ darwin/ppc64 support
    + val/str/read(ln)/write(ln) support for enums
    + simple cse at the node tree level
    + if-node simplify support
    + simple ssa support for memory locations
    + support for optional overflow/rangecheck boolean parameters for
      operators
    * a lot of unification of the ppc32/ppc64 code generators
........
r6380 | jonas | 2007-02-08 21:25:36 +0100 (Thu, 08 Feb 2007) | 4 lines
Changed paths:
   M /branches/fpc_2_3/compiler/ncgld.pas
   M /branches/fpc_2_3/compiler/tgobj.pas
   A /branches/fpc_2_3/tests/webtbs/tw8283.pp
  + support for replacing the memory location of a temp (including
    local variables) with that of another temp to avoid unnecessary
    copies (mantis #8283)
........
r6381 | jonas | 2007-02-08 22:53:36 +0100 (Thu, 08 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/nflw.pas
   A /branches/fpc_2_3/tests/webtbs/tw8282.pp
  + simplify support for ifn (based on patch by Florian)
........
r6386 | peter | 2007-02-09 13:48:53 +0100 (Fri, 09 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/htypechk.pas
   M /branches/fpc_2_3/compiler/ncal.pas
   M /branches/fpc_2_3/compiler/symconst.pas
  * overflow,rangecheck optional parameters for operators, patch from 8281
........
r6391 | jonas | 2007-02-09 23:52:13 +0100 (Fri, 09 Feb 2007) | 4 lines
Changed paths:
   M /branches/fpc_2_3/compiler/powerpc/agppcgas.pas
   M /branches/fpc_2_3/compiler/powerpc64/cpunode.pas
   D /branches/fpc_2_3/compiler/powerpc64/nppcinl.pas
   M /branches/fpc_2_3/compiler/ppcgen/ngppcinl.pas
  * merged fsqrt(s) support to common powerpc unit, activate for ppc32
    if -Op970 is used (still default for ppc64, since default cpu there
    is already ppc970)
........
r6394 | jonas | 2007-02-10 18:58:47 +0100 (Sat, 10 Feb 2007) | 4 lines
Changed paths:
   M /branches/fpc_2_3/compiler/powerpc/cgcpu.pas
   M /branches/fpc_2_3/compiler/powerpc64/cgcpu.pas
   M /branches/fpc_2_3/compiler/ppcgen/cgppc.pas
  * 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
Changed paths:
   M /branches/fpc_2_3/compiler/cgobj.pas
  + darwin/ppc64 support for g_indirect_sym_load
........
r6397 | jonas | 2007-02-10 20:22:49 +0100 (Sat, 10 Feb 2007) | 4 lines
Changed paths:
   M /branches/fpc_2_3/compiler/powerpc/cgcpu.pas
   M /branches/fpc_2_3/compiler/powerpc64/cgcpu.pas
   M /branches/fpc_2_3/compiler/ppcgen/cgppc.pas
  + 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
Changed paths:
   M /branches/fpc_2_3/compiler/systems.pas
  + system_x86_64_darwin identifier
  + set default source system for system_x86_64_darwin and
    system_powerpc64_darwin
........
r6404 | jonas | 2007-02-10 23:01:23 +0100 (Sat, 10 Feb 2007) | 5 lines
Changed paths:
   M /branches/fpc_2_3/compiler/aasmdata.pas
   M /branches/fpc_2_3/compiler/aggas.pas
   M /branches/fpc_2_3/compiler/cgobj.pas
   M /branches/fpc_2_3/compiler/cgutils.pas
   M /branches/fpc_2_3/compiler/cresstr.pas
   M /branches/fpc_2_3/compiler/dbgdwarf.pas
   M /branches/fpc_2_3/compiler/dbgstabs.pas
   M /branches/fpc_2_3/compiler/ncgutil.pas
   M /branches/fpc_2_3/compiler/ogelf.pas
   M /branches/fpc_2_3/compiler/pdecvar.pas
   M /branches/fpc_2_3/compiler/pmodules.pas
   M /branches/fpc_2_3/compiler/symdef.pas
   M /branches/fpc_2_3/compiler/systems.pas
  + system_x86_64_darwin identifier
  + systems_darwin set which collects all darwin variants
  + added support for darwin/ppc64 and darwin/x86_64 where needed in
    the generic code
........
r6406 | jonas | 2007-02-10 23:24:32 +0100 (Sat, 10 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/cgobj.pas
  * ifdef cpu64 -> ifdef cpu64bit
........
r6409 | jonas | 2007-02-11 00:34:04 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/pdecvar.pas
  * fixed ppc64 compilation
........
r6413 | jonas | 2007-02-11 12:41:27 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/rtl/bsd/system.pp
   M /branches/fpc_2_3/rtl/darwin/powerpc/sig_cpu.inc
   M /branches/fpc_2_3/rtl/darwin/signal.inc
  + darwin/ppc64 support for signal routines
........
r6415 | jonas | 2007-02-11 13:54:53 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/systems/i_linux.pas
  * set abi of linux/ppc64 to abi_powerpc_sysv
........
r6416 | jonas | 2007-02-11 13:55:51 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/powerpc64/cputarg.pas
   M /branches/fpc_2_3/compiler/systems/i_bsd.pas
   M /branches/fpc_2_3/compiler/systems/t_bsd.pas
  + darwin/ppc64 source and target information
........
r6418 | jonas | 2007-02-11 14:19:55 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/rtl/powerpc64/math.inc
  * darwin/ppc64 compilation fixes
........
r6419 | jonas | 2007-02-11 14:22:22 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/powerpc/cgcpu.pas
   M /branches/fpc_2_3/compiler/powerpc64/cgcpu.pas
   M /branches/fpc_2_3/compiler/ppcgen/cgppc.pas
  * darwin/ppc64 needs the 32 bit version of a_loadaddr_ref_reg
........
r6420 | jonas | 2007-02-11 14:22:55 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/utils/fpcm/fpcmmain.pp
  + darwin/ppc64 support
........
r6426 | jonas | 2007-02-11 16:13:19 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/powerpc64/rappcgas.pas
  * fixed refaddr parsing for darwin/ppc64
........
r6427 | jonas | 2007-02-11 16:14:21 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/powerpc/agppcgas.pas
   M /branches/fpc_2_3/compiler/powerpc64/agppcgas.pas
   A /branches/fpc_2_3/compiler/ppcgen/agppcutl.pas
  * moved ppc32/ppc64 assembler writer helpers to a common unit
........
r6430 | jonas | 2007-02-11 17:53:23 +0100 (Sun, 11 Feb 2007) | 4 lines
Changed paths:
   D /branches/fpc_2_3/rtl/darwin/powerpc/sig_cpu.inc
   D /branches/fpc_2_3/rtl/darwin/powerpc/sighnd.inc
   A /branches/fpc_2_3/rtl/darwin/powerpc64
   A /branches/fpc_2_3/rtl/darwin/powerpc64/sig_cpu.inc
   A /branches/fpc_2_3/rtl/darwin/powerpc64/sighnd.inc
   A /branches/fpc_2_3/rtl/darwin/ppcgen
   A /branches/fpc_2_3/rtl/darwin/ppcgen/ppchnd.inc (from /branches/fpc_2_3/rtl/darwin/powerpc/sighnd.inc:6422)
   A /branches/fpc_2_3/rtl/darwin/ppcgen/sig_ppc.inc (from /branches/fpc_2_3/rtl/darwin/powerpc/sig_cpu.inc:6422)
   M /branches/fpc_2_3/rtl/darwin/signal.inc
  * fixed ppc/ppc64 signal include handling (both real files are in
    ppcgen, dummies in powerpc and powerpc64 which include those files)
    (1st step because pre-commit filter can't handle replaced files)
........
r6431 | jonas | 2007-02-11 17:53:47 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   A /branches/fpc_2_3/rtl/darwin/powerpc/sig_cpu.inc
   A /branches/fpc_2_3/rtl/darwin/powerpc/sighnd.inc
  * second step of signal include patch
........
r6432 | jonas | 2007-02-11 19:00:12 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/systems/t_bsd.pas
  * changed darwin checks to use systems_darwin constant
........
r6433 | jonas | 2007-02-11 19:05:38 +0100 (Sun, 11 Feb 2007) | 3 lines
Changed paths:
   M /branches/fpc_2_3/compiler/powerpc64/cgcpu.pas
  * handle non-multiple-of-4 offsets with 64 bit loads/stores for
    darwin/ppc64
........
r6434 | jonas | 2007-02-11 19:05:56 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   D /branches/fpc_2_3/compiler/powerpc/agppcgas.pas
   D /branches/fpc_2_3/compiler/powerpc64/agppcgas.pas
   A /branches/fpc_2_3/compiler/ppcgen/agppcgas.pas (from /branches/fpc_2_3/compiler/ppcgen/agppcutl.pas:6427)
   D /branches/fpc_2_3/compiler/ppcgen/agppcutl.pas
  * completely merged ppc assembler writers
........
r6435 | jonas | 2007-02-11 19:06:40 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/rtl/darwin/console.pp
   M /branches/fpc_2_3/rtl/darwin/termiosproc.inc
  * fixed 64 bit compilation
........
r6436 | jonas | 2007-02-11 19:09:28 +0100 (Sun, 11 Feb 2007) | 3 lines
Changed paths:
   M /branches/fpc_2_3/packages/extra/Makefile.fpc
  * universal interfaces aren't 64 bit ready yet -> only compile for
    darwin/ppc and darwin/i386
........
r6438 | jonas | 2007-02-11 19:22:34 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   A /branches/fpc_2_3/tests/test/cg/obj/darwin/powerpc64
   A /branches/fpc_2_3/tests/test/cg/obj/darwin/powerpc64/ctest.o
   A /branches/fpc_2_3/tests/test/cg/obj/darwin/powerpc64/tcext3.o
   A /branches/fpc_2_3/tests/test/cg/obj/darwin/powerpc64/tcext4.o
   A /branches/fpc_2_3/tests/test/cg/obj/darwin/powerpc64/tcext5.o
  + compiled for darwin/ppc64
........
r6439 | jonas | 2007-02-11 20:24:42 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/ppcgen/cgppc.pas
  * patch from Thomas to fix linux/ppc64
........
r6440 | jonas | 2007-02-11 20:25:15 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/systems.pas
  * fixed setting source OS for darwin/ppc64
........
r6444 | florian | 2007-02-11 22:24:20 +0100 (Sun, 11 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/globtype.pas
   M /branches/fpc_2_3/compiler/nopt.pas
   M /branches/fpc_2_3/compiler/nutils.pas
   M /branches/fpc_2_3/compiler/optcse.pas
   M /branches/fpc_2_3/compiler/psub.pas
+ first node cse implementation
........
r6445 | jonas | 2007-02-11 22:30:07 +0100 (Sun, 11 Feb 2007) | 6 lines
Changed paths:
   M /branches/fpc_2_3/compiler/cresstr.pas
  * 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
Changed paths:
   M /branches/fpc_2_3/compiler/systems/i_bsd.pas
  * 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
Changed paths:
   M /branches/fpc_2_3/compiler/ppcgen/ngppcset.pas
  * disable jump tables for darwin/ppc64 for now, don't work
    yet for some reason
........
r6451 | florian | 2007-02-11 23:54:37 +0100 (Sun, 11 Feb 2007) | 3 lines
Changed paths:
   M /branches/fpc_2_3/compiler/ncal.pas
   M /branches/fpc_2_3/compiler/nutils.pas
   M /branches/fpc_2_3/compiler/optcse.pas
* improved cse
* better complexity calculation for subscript nodes with classes or interfaces
........
r6456 | jonas | 2007-02-12 19:33:22 +0100 (Mon, 12 Feb 2007) | 4 lines
Changed paths:
   M /branches/fpc_2_3/compiler/nutils.pas
  + support for notn,shln,shrn,equaln,unequaln,gtn,gten,ltn,lten in
    node_cplexity()
  * mark muln,divn,modn as more complex
........
r6469 | jonas | 2007-02-13 15:56:01 +0100 (Tue, 13 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/optcse.pas
  * fixed when cross-compiling a 64 bit compiler from a 32 bit platform
........
r6471 | jonas | 2007-02-13 16:17:16 +0100 (Tue, 13 Feb 2007) | 3 lines
Changed paths:
   M /branches/fpc_2_3/compiler/powerpc64/cputarg.pas
  * include stabs support (can work on darwin/ppc64, but doesn't work
    yet)
........
r6473 | jonas | 2007-02-13 16:45:48 +0100 (Tue, 13 Feb 2007) | 3 lines
Changed paths:
   M /branches/fpc_2_3/compiler/powerpc64/cgcpu.pas
   M /branches/fpc_2_3/compiler/powerpc64/cpupara.pas
  * R2 is a volatile and usable register under darwin/ppc64
  * R13 is a reserved non-volatile register under darwin/ppc64 (tls)
........
r6479 | jonas | 2007-02-13 20:40:50 +0100 (Tue, 13 Feb 2007) | 3 lines
Changed paths:
   M /branches/fpc_2_3/compiler/systems/i_bsd.pas
  * maxCrecordalign seems to have to be 8 rather 4, in spite of what
    the ABI docs say (although they are contradictory to some extent)
........
r6487 | jonas | 2007-02-14 15:57:40 +0100 (Wed, 14 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/tests/webtbs/tw8153a.pp
  * fixed for darwin/ppc64
........
r6488 | jonas | 2007-02-14 15:58:56 +0100 (Wed, 14 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/tests/webtbs/tw7851a.pp
  * fixed for darwin/ppc64
........
r6494 | jonas | 2007-02-15 19:36:55 +0100 (Thu, 15 Feb 2007) | 3 lines
Changed paths:
   M /branches/fpc_2_3/compiler/systems/i_bsd.pas
  * set default debug info for darwin/ppc64 to dwarf2 since
    it works better than stabs currently
........
r6500 | jonas | 2007-02-15 21:38:16 +0100 (Thu, 15 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/version.pas
  * updated version to 2.3.0
........
r6505 | jonas | 2007-02-15 22:39:28 +0100 (Thu, 15 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/version.pas
  * changed version to 2.3.1
........
r6511 | jonas | 2007-02-16 15:17:24 +0100 (Fri, 16 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/powerpc64/itcpugas.pas
  * system_powerpc_darwin -> system_powerpc64_darwin
........
r6546 | daniel | 2007-02-18 15:48:54 +0100 (Sun, 18 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/ncginl.pas
   M /branches/fpc_2_3/compiler/ncgld.pas
   M /branches/fpc_2_3/compiler/ncgrtti.pas
   M /branches/fpc_2_3/compiler/ncnv.pas
   M /branches/fpc_2_3/compiler/ninl.pas
   M /branches/fpc_2_3/compiler/nld.pas
   M /branches/fpc_2_3/compiler/nutils.pas
   M /branches/fpc_2_3/compiler/pinline.pas
   M /branches/fpc_2_3/rtl/inc/astrings.inc
   M /branches/fpc_2_3/rtl/inc/compproc.inc
   M /branches/fpc_2_3/rtl/inc/sstrings.inc
   M /branches/fpc_2_3/rtl/inc/text.inc
   M /branches/fpc_2_3/rtl/inc/wstrings.inc
  + Val/str/read/write support for enumeration types.
........
r6547 | daniel | 2007-02-18 17:01:20 +0100 (Sun, 18 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/rtl/inc/sstrings.inc
  * Fix val code that I broke.
........
r6571 | daniel | 2007-02-20 09:27:44 +0100 (Tue, 20 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/rtl/inc/astrings.inc
   M /branches/fpc_2_3/rtl/inc/sstrings.inc
   M /branches/fpc_2_3/rtl/inc/text.inc
   M /branches/fpc_2_3/rtl/inc/wstrings.inc
  * o2s -> ord2str, s2o -> str2ord
........
r6572 | daniel | 2007-02-20 09:33:30 +0100 (Tue, 20 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/ncgld.pas
   M /branches/fpc_2_3/compiler/ncgrtti.pas
   M /branches/fpc_2_3/compiler/ninl.pas
   M /branches/fpc_2_3/compiler/nld.pas
  * o2s -> ord2str, s2o -> str2ord
........
r6574 | daniel | 2007-02-20 12:07:58 +0100 (Tue, 20 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/rtl/inc/compproc.inc
  * o2s -> ord2str, s2o -> str2ord
........
r6578 | daniel | 2007-02-20 22:18:49 +0100 (Tue, 20 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/rtl/inc/text.inc
  * Change longint to valsint.
........
r6579 | daniel | 2007-02-20 22:29:09 +0100 (Tue, 20 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/ninl.pas
  * Handle ordinal currency types.
........
r6580 | jonas | 2007-02-20 22:29:11 +0100 (Tue, 20 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/ncgrtti.pas
  * fixed compilation for cpurequiresproperalignment
........
r6581 | jonas | 2007-02-20 22:30:21 +0100 (Tue, 20 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/ninl.pas
  * fixed typo
........
r6582 | daniel | 2007-02-20 22:36:19 +0100 (Tue, 20 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/ninl.pas
  * Set is_real to true.
........
r6590 | jonas | 2007-02-21 20:23:54 +0100 (Wed, 21 Feb 2007) | 2 lines
Changed paths:
   M /branches/fpc_2_3/compiler/systems/i_bsd.pas
  * set tf_dwarf_only_local_labels for darwin/ppc64
git-svn-id: trunk@6720 -
		
	
			
		
			
				
	
	
		
			709 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			709 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{
 | 
						|
    Copyright (c) 2006 by Florian Klaempfl
 | 
						|
 | 
						|
    This unit implements the common part of the code generator for the PowerPC
 | 
						|
 | 
						|
    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
 | 
						|
    the Free Software Foundation; either version 2 of the License, or
 | 
						|
    (at your option) any later version.
 | 
						|
 | 
						|
    This program is distributed in the hope that it will be useful,
 | 
						|
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
    GNU General Public License for more details.
 | 
						|
 | 
						|
    You should have received a copy of the GNU General Public License
 | 
						|
    along with this program; if not, write to the Free Software
 | 
						|
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
						|
 | 
						|
 ****************************************************************************
 | 
						|
}
 | 
						|
unit cgppc;
 | 
						|
 | 
						|
{$i fpcdefs.inc}
 | 
						|
 | 
						|
  interface
 | 
						|
 | 
						|
    uses
 | 
						|
       globtype,symtype,symdef,
 | 
						|
       cgbase,cgobj,
 | 
						|
       aasmbase,aasmcpu,aasmtai,aasmdata,
 | 
						|
       cpubase,cpuinfo,cgutils,rgcpu,
 | 
						|
       parabase;
 | 
						|
 | 
						|
    type
 | 
						|
      tcgppcgen = class(tcg)
 | 
						|
        procedure a_param_const(list: TAsmList; size: tcgsize; a: aint; const paraloc : tcgpara); override;
 | 
						|
        procedure a_paramaddr_ref(list : TAsmList;const r : treference;const paraloc : tcgpara); override;
 | 
						|
 | 
						|
        procedure a_call_reg(list : TAsmList;reg: tregister); override;
 | 
						|
        procedure a_call_ref(list : TAsmList;ref: treference); override;
 | 
						|
 | 
						|
        { stores the contents of register reg to the memory location described by
 | 
						|
        ref }
 | 
						|
        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;
 | 
						|
        procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override;
 | 
						|
 | 
						|
        { overflow checking }
 | 
						|
        procedure g_overflowcheck(list: TAsmList; const l: tlocation; def: tdef);override;
 | 
						|
 | 
						|
        { entry code }
 | 
						|
        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;
 | 
						|
        { 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
 | 
						|
    TOpCmp2AsmCond: Array[topcmp] of TAsmCondFlag = (C_NONE,C_EQ,C_GT,
 | 
						|
                         C_LT,C_GE,C_LE,C_NE,C_LE,C_LT,C_GE,C_GT);  
 | 
						|
 | 
						|
 | 
						|
  implementation
 | 
						|
 | 
						|
    uses
 | 
						|
       globals,verbose,systems,cutils,
 | 
						|
       symconst,symsym,fmodule,
 | 
						|
       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
 | 
						|
      ref: treference;
 | 
						|
    begin
 | 
						|
      paraloc.check_simple_location;
 | 
						|
      case paraloc.location^.loc of
 | 
						|
        LOC_REGISTER, LOC_CREGISTER:
 | 
						|
          a_load_const_reg(list, size, a, paraloc.location^.register);
 | 
						|
        LOC_REFERENCE:
 | 
						|
          begin
 | 
						|
            reference_reset(ref);
 | 
						|
            ref.base := paraloc.location^.reference.index;
 | 
						|
            ref.offset := paraloc.location^.reference.offset;
 | 
						|
            a_load_const_ref(list, size, a, ref);
 | 
						|
          end;
 | 
						|
      else
 | 
						|
        internalerror(2002081101);
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
 | 
						|
 | 
						|
    procedure tcgppcgen.a_paramaddr_ref(list : TAsmList;const r : treference;const paraloc : tcgpara);
 | 
						|
      var
 | 
						|
        ref: treference;
 | 
						|
        tmpreg: tregister;
 | 
						|
 | 
						|
      begin
 | 
						|
        paraloc.check_simple_location;
 | 
						|
        case paraloc.location^.loc of
 | 
						|
           LOC_REGISTER,LOC_CREGISTER:
 | 
						|
             a_loadaddr_ref_reg(list,r,paraloc.location^.register);
 | 
						|
           LOC_REFERENCE:
 | 
						|
             begin
 | 
						|
               reference_reset(ref);
 | 
						|
               ref.base := paraloc.location^.reference.index;
 | 
						|
               ref.offset := paraloc.location^.reference.offset;
 | 
						|
               tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
 | 
						|
               a_loadaddr_ref_reg(list,r,tmpreg);
 | 
						|
               a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
 | 
						|
             end;
 | 
						|
           else
 | 
						|
             internalerror(2002080701);
 | 
						|
        end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tcgppcgen.get_darwin_call_stub(const s: string): tasmsymbol;
 | 
						|
      var
 | 
						|
        stubname: string;
 | 
						|
        href: treference;
 | 
						|
        l1: tasmsymbol;
 | 
						|
      begin
 | 
						|
        { function declared in the current unit? }
 | 
						|
        { doesn't work correctly, because this will also return a hit if we }
 | 
						|
        { previously took the address of an external procedure. It doesn't  }
 | 
						|
        { really matter, the linker will remove all unnecessary stubs.      }
 | 
						|
        stubname := 'L'+s+'$stub';
 | 
						|
        result := current_asmdata.getasmsymbol(stubname);
 | 
						|
        if assigned(result) then
 | 
						|
          exit;
 | 
						|
 | 
						|
        if current_asmdata.asmlists[al_imports]=nil then
 | 
						|
          current_asmdata.asmlists[al_imports]:=TAsmList.create;
 | 
						|
 | 
						|
        current_asmdata.asmlists[al_imports].concat(Tai_section.create(sec_stub,'',0));
 | 
						|
        current_asmdata.asmlists[al_imports].concat(Tai_align.Create(16));
 | 
						|
        result := current_asmdata.RefAsmSymbol(stubname);
 | 
						|
        current_asmdata.asmlists[al_imports].concat(Tai_symbol.Create(result,0));
 | 
						|
        current_asmdata.asmlists[al_imports].concat(tai_directive.create(asd_indirect_symbol,s));
 | 
						|
        l1 := current_asmdata.RefAsmSymbol('L'+s+'$lazy_ptr');
 | 
						|
        reference_reset_symbol(href,l1,0);
 | 
						|
        href.refaddr := addr_hi;
 | 
						|
        current_asmdata.asmlists[al_imports].concat(taicpu.op_reg_ref(A_LIS,NR_R11,href));
 | 
						|
        href.refaddr := addr_lo;
 | 
						|
        href.base := NR_R11;
 | 
						|
{$ifndef cpu64bit}
 | 
						|
        current_asmdata.asmlists[al_imports].concat(taicpu.op_reg_ref(A_LWZU,NR_R12,href));
 | 
						|
{$else cpu64bit}
 | 
						|
        { darwin/ppc64 uses a 32 bit absolute address here, strange... }
 | 
						|
        current_asmdata.asmlists[al_imports].concat(taicpu.op_reg_ref(A_LDU,NR_R12,href));
 | 
						|
{$endif cpu64bit}
 | 
						|
        current_asmdata.asmlists[al_imports].concat(taicpu.op_reg(A_MTCTR,NR_R12));
 | 
						|
        current_asmdata.asmlists[al_imports].concat(taicpu.op_none(A_BCTR));
 | 
						|
        current_asmdata.asmlists[al_imports].concat(tai_directive.create(asd_lazy_symbol_pointer,''));
 | 
						|
        current_asmdata.asmlists[al_imports].concat(Tai_symbol.Create(l1,0));
 | 
						|
        current_asmdata.asmlists[al_imports].concat(tai_directive.create(asd_indirect_symbol,s));
 | 
						|
        current_asmdata.asmlists[al_imports].concat(tai_const.createname('dyld_stub_binding_helper',0));
 | 
						|
      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
 | 
						|
        list.concat(taicpu.op_reg(A_MTCTR,reg));
 | 
						|
        list.concat(taicpu.op_none(A_BCTRL));
 | 
						|
        include(current_procinfo.flags,pi_do_call);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tcgppcgen.a_call_ref(list : TAsmList;ref: treference);
 | 
						|
      var
 | 
						|
        tempreg : TRegister;
 | 
						|
      begin
 | 
						|
        tempreg := getintregister(list, OS_ADDR);
 | 
						|
        a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,tempreg);
 | 
						|
        a_call_reg(list,tempreg);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tcgppcgen.a_load_reg_ref(list: TAsmList; fromsize, tosize: TCGSize;
 | 
						|
      reg: tregister; const ref: treference);
 | 
						|
    
 | 
						|
    const
 | 
						|
      StoreInstr: array[OS_8..OS_INT, boolean, boolean] of TAsmOp =
 | 
						|
      { indexed? updating?}
 | 
						|
      (((A_STB, A_STBU), (A_STBX, A_STBUX)),
 | 
						|
        ((A_STH, A_STHU), (A_STHX, A_STHUX)),
 | 
						|
        ((A_STW, A_STWU), (A_STWX, A_STWUX))
 | 
						|
{$ifdef cpu64bit}
 | 
						|
        ,
 | 
						|
        ((A_STD, A_STDU), (A_STDX, A_STDUX))
 | 
						|
{$endif cpu64bit}
 | 
						|
        );
 | 
						|
    var
 | 
						|
      op: TAsmOp;
 | 
						|
      ref2: TReference;
 | 
						|
    begin
 | 
						|
      if not (fromsize in [OS_8..OS_INT,OS_S8..OS_SINT]) then
 | 
						|
        internalerror(2002090903);
 | 
						|
      if not (tosize in [OS_8..OS_INT,OS_S8..OS_SINT]) then
 | 
						|
        internalerror(2002090905);
 | 
						|
    
 | 
						|
      ref2 := ref;
 | 
						|
      fixref(list, ref2);
 | 
						|
      if tosize in [OS_S8..OS_SINT] then
 | 
						|
        { storing is the same for signed and unsigned values }
 | 
						|
        tosize := tcgsize(ord(tosize) - (ord(OS_S8) - ord(OS_8)));
 | 
						|
      op := storeinstr[tcgsize2unsigned[tosize], ref2.index <> NR_NO, false];
 | 
						|
      a_load_store(list, op, reg, ref2);
 | 
						|
    end;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
     procedure tcgppcgen.a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister);
 | 
						|
 | 
						|
       var
 | 
						|
         op: tasmop;
 | 
						|
         instr: taicpu;
 | 
						|
       begin
 | 
						|
         if not(fromsize in [OS_F32,OS_F64]) or
 | 
						|
            not(tosize in [OS_F32,OS_F64]) then
 | 
						|
           internalerror(2006123110);
 | 
						|
         if (tosize < fromsize) then
 | 
						|
           op:=A_FRSP
 | 
						|
         else
 | 
						|
           op:=A_FMR;
 | 
						|
         instr := taicpu.op_reg_reg(op,reg2,reg1);
 | 
						|
         list.concat(instr);
 | 
						|
         if (op = A_FMR) then
 | 
						|
           rg[R_FPUREGISTER].add_move_instruction(instr);
 | 
						|
       end;
 | 
						|
 | 
						|
 | 
						|
     procedure tcgppcgen.a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister);
 | 
						|
 | 
						|
       const
 | 
						|
         FpuLoadInstr: Array[OS_F32..OS_F64,boolean, boolean] of TAsmOp =
 | 
						|
                          { indexed? updating?}
 | 
						|
                    (((A_LFS,A_LFSU),(A_LFSX,A_LFSUX)),
 | 
						|
                     ((A_LFD,A_LFDU),(A_LFDX,A_LFDUX)));
 | 
						|
       var
 | 
						|
         op: tasmop;
 | 
						|
         ref2: treference;
 | 
						|
 | 
						|
       begin
 | 
						|
         if not(fromsize in [OS_F32,OS_F64]) or
 | 
						|
            not(tosize in [OS_F32,OS_F64]) then
 | 
						|
           internalerror(200201121);
 | 
						|
         ref2 := ref;
 | 
						|
         fixref(list,ref2);
 | 
						|
         op := fpuloadinstr[fromsize,ref2.index <> NR_NO,false];
 | 
						|
         a_load_store(list,op,reg,ref2);
 | 
						|
         if (fromsize > tosize) then
 | 
						|
           a_loadfpu_reg_reg(list,fromsize,tosize,reg,reg);
 | 
						|
       end;
 | 
						|
 | 
						|
 | 
						|
     procedure tcgppcgen.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
 | 
						|
 | 
						|
       const
 | 
						|
         FpuStoreInstr: Array[OS_F32..OS_F64,boolean, boolean] of TAsmOp =
 | 
						|
                            { indexed? updating?}
 | 
						|
                    (((A_STFS,A_STFSU),(A_STFSX,A_STFSUX)),
 | 
						|
                     ((A_STFD,A_STFDU),(A_STFDX,A_STFDUX)));
 | 
						|
       var
 | 
						|
         op: tasmop;
 | 
						|
         ref2: treference;
 | 
						|
{$ifndef cpu64bit}
 | 
						|
         reg2: tregister;
 | 
						|
{$endif cpu64bit}
 | 
						|
 | 
						|
       begin
 | 
						|
         if not(fromsize in [OS_F32,OS_F64]) or
 | 
						|
            not(tosize in [OS_F32,OS_F64]) then
 | 
						|
           internalerror(200201122);
 | 
						|
         ref2 := ref;
 | 
						|
         fixref(list,ref2);
 | 
						|
         op := fpustoreinstr[tosize,ref2.index <> NR_NO,false];
 | 
						|
{$ifndef cpu64bit}
 | 
						|
         { some ppc's have a bug whereby storing a double to memory }
 | 
						|
         { as single corrupts the value -> convert double to single }
 | 
						|
         { first                                                    }
 | 
						|
         if (tosize < fromsize) then
 | 
						|
           begin
 | 
						|
             reg2:=getfpuregister(list,tosize);
 | 
						|
             a_loadfpu_reg_reg(list,fromsize,tosize,reg,reg2);
 | 
						|
             reg:=reg2;
 | 
						|
           end;
 | 
						|
{$endif not cpu64bit}
 | 
						|
         a_load_store(list,op,reg,ref2);
 | 
						|
       end;
 | 
						|
 | 
						|
 | 
						|
  procedure tcgppcgen.a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tcgsize; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister);
 | 
						|
    var
 | 
						|
      fromsreg, tosreg: tsubsetregister;
 | 
						|
      restbits: byte;
 | 
						|
    begin
 | 
						|
      restbits := (sref.bitlen - (loadbitsize - sref.startbit));
 | 
						|
      if (subsetsize in [OS_S8..OS_S128]) then
 | 
						|
        begin
 | 
						|
         { sign extend }
 | 
						|
         a_op_const_reg(list,OP_SHL,OS_INT,AIntBits-loadbitsize+sref.startbit,valuereg);
 | 
						|
         a_op_const_reg(list,OP_SAR,OS_INT,AIntBits-sref.bitlen,valuereg);
 | 
						|
        end
 | 
						|
      else
 | 
						|
        begin
 | 
						|
          a_op_const_reg(list,OP_SHL,OS_INT,restbits,valuereg);
 | 
						|
          { mask other bits }
 | 
						|
          if (sref.bitlen <> AIntBits) then
 | 
						|
            a_op_const_reg(list,OP_AND,OS_INT,(aword(1) shl sref.bitlen)-1,valuereg);
 | 
						|
        end;
 | 
						|
      { use subsetreg routine, it may have been overridden with an optimized version }
 | 
						|
      fromsreg.subsetreg := extra_value_reg;
 | 
						|
      fromsreg.subsetregsize := OS_INT;
 | 
						|
      { subsetregs always count bits from right to left }
 | 
						|
      fromsreg.startbit := loadbitsize-restbits;
 | 
						|
      fromsreg.bitlen := restbits;
 | 
						|
  
 | 
						|
      tosreg.subsetreg := valuereg;
 | 
						|
      tosreg.subsetregsize := OS_INT;
 | 
						|
      tosreg.startbit := 0;
 | 
						|
      tosreg.bitlen := restbits;
 | 
						|
  
 | 
						|
      a_load_subsetreg_subsetreg(list,subsetsize,subsetsize,fromsreg,tosreg);
 | 
						|
    end;
 | 
						|
 | 
						|
 | 
						|
  procedure tcgppcgen.g_overflowcheck(list: TAsmList; const l: tlocation; def: tdef);
 | 
						|
    var
 | 
						|
      hl : tasmlabel;
 | 
						|
      flags : TResFlags;
 | 
						|
    begin
 | 
						|
      if not(cs_check_overflow in current_settings.localswitches) then
 | 
						|
        exit;
 | 
						|
      current_asmdata.getjumplabel(hl);
 | 
						|
      if not ((def.typ=pointerdef) or
 | 
						|
             ((def.typ=orddef) and
 | 
						|
              (torddef(def).ordtype in [u64bit,u16bit,u32bit,u8bit,uchar,
 | 
						|
                                        bool8bit,bool16bit,bool32bit,bool64bit]))) then
 | 
						|
        begin
 | 
						|
          if (current_settings.optimizecputype >= cpu_ppc970) or
 | 
						|
             (current_settings.cputype >= cpu_ppc970) then
 | 
						|
            begin
 | 
						|
              { ... instructions setting overflow flag ...
 | 
						|
              mfxerf R0
 | 
						|
              mtcrf 128, R0
 | 
						|
              ble cr0, label }
 | 
						|
              list.concat(taicpu.op_reg(A_MFXER, NR_R0));
 | 
						|
              list.concat(taicpu.op_const_reg(A_MTCRF, 128, NR_R0));
 | 
						|
              flags.cr := RS_CR0;
 | 
						|
              flags.flag := F_LE;
 | 
						|
              a_jmp_flags(list, flags, hl);
 | 
						|
            end
 | 
						|
          else
 | 
						|
            begin
 | 
						|
              list.concat(taicpu.op_reg(A_MCRXR,NR_CR7));
 | 
						|
              a_jmp(list,A_BC,C_NO,7,hl)
 | 
						|
            end;
 | 
						|
        end
 | 
						|
      else
 | 
						|
        a_jmp_cond(list,OC_AE,hl);
 | 
						|
      a_call_name(list,'FPC_OVERFLOW');
 | 
						|
      a_label(list,hl);
 | 
						|
    end;
 | 
						|
 | 
						|
 | 
						|
  procedure tcgppcgen.g_profilecode(list: TAsmList);
 | 
						|
    var
 | 
						|
      paraloc1 : tcgpara;
 | 
						|
      reg: tregister;
 | 
						|
    begin
 | 
						|
      if (target_info.system in [system_powerpc_darwin]) then
 | 
						|
        begin
 | 
						|
          paraloc1.init;
 | 
						|
          paramanager.getintparaloc(pocall_cdecl,1,paraloc1);
 | 
						|
          a_param_reg(list,OS_ADDR,NR_R0,paraloc1);
 | 
						|
          paramanager.freeparaloc(list,paraloc1);
 | 
						|
          paraloc1.done;
 | 
						|
          allocallcpuregisters(list);
 | 
						|
          a_call_name(list,'mcount');
 | 
						|
          deallocallcpuregisters(list);
 | 
						|
          a_reg_dealloc(list,NR_R0);
 | 
						|
        end;
 | 
						|
    end;
 | 
						|
 | 
						|
 | 
						|
  procedure tcgppcgen.a_jmp_cond(list : TAsmList;cond : TOpCmp; l: tasmlabel);
 | 
						|
    begin
 | 
						|
      a_jmp(list,A_BC,TOpCmp2AsmCond[cond],0,l);
 | 
						|
    end;
 | 
						|
 | 
						|
 | 
						|
 procedure tcgppcgen.a_jmp(list: TAsmList; op: tasmop; c: tasmcondflag;
 | 
						|
             crval: longint; l: tasmlabel);
 | 
						|
   var
 | 
						|
     p: taicpu;
 | 
						|
 | 
						|
   begin
 | 
						|
     p := taicpu.op_sym(op,l);
 | 
						|
     if op <> A_B then
 | 
						|
       create_cond_norm(c,crval,p.condition);
 | 
						|
     p.is_jmp := true;
 | 
						|
     list.concat(p)
 | 
						|
   end;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
    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.
 | 
						|
 |