mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-11-26 00:57:19 +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.
|
|
|