PowerPC reorg and support for powerpc64-*-linux*.
2001-07-31 Daniel Berlin <dan@cgsoftware.com> PowerPC reorg and support for powerpc64-*-linux*. Also fixes emitting of constants on 32 bit and 64 bit platforms. * config.gcc: powerpc64-*-linux* is a new target. Things that needed aix.h now also include xcoff.h * config/rs6000/rs6000.h: Split XCOFF specific stuff into xcoff.h. Move AIX specific stuff into aix.h. (ASM_LONG): Use DOUBLE_INT_ASM_OP if we are on a 64 bit target. (ASM_OUTPUT_DOUBLE_INT): Ditto. (TARGET_AIX): Renamed to TARGET_XCOFF, since the AIX ABI is used with more than just XCOFF now. (SET_ASM_OP): Remove, now defined where needed. (FUNCTION_PROLOGUE): New macro definition. (FUNCTION_EPILOGUE): New macro definition. (CONST_OK_FOR_LETTER_P): Change N to require that value is positive, too. (ASM_OPEN_PAREN, ASM_CLOSE_PAREN): New macro definition. (PREDICATE_CODES): Added exact_log2_cint_operand, reg_or_add_cint64_operand, reg_or_sub_cint64_operand. * config/rs6000/rs6000.c: #ifdef XCOFF debugging info stuff on XCOFF_DEBUGGING_INFO. Use DOUBLE_INT_ASM_OP where approriate. (rs6000_emit_set_long_const): New function. (rs6000_emit_set_const): New function. (reg_or_sub_cint64_operand): New function. (reg_or_add_cint64_operand): New function. (exact_log2_cint_operand): New function. * config/rs6000/rs6000.md: Fix emitting of constants. Fix patterns that were AIX ABI specific, but depended on !TARGET_ELF (instead of DEFAULT_ABI == ABI_AIX). * config/rs6000/xcoff.h: New file. * config/rs6000/linux64.h: New file. * config/rs6000/darwin.h: Copy needed AIX alignment definitions. From-SVN: r44516
This commit is contained in:
parent
befe7c6146
commit
2bfcf29777
12 changed files with 1432 additions and 871 deletions
|
@ -1,3 +1,49 @@
|
|||
2001-07-31 Daniel Berlin <dan@cgsoftware.com>
|
||||
|
||||
PowerPC reorg and support for powerpc64-*-linux*.
|
||||
|
||||
Also fixes emitting of constants on 32 bit and 64 bit
|
||||
platforms.
|
||||
|
||||
* config.gcc: powerpc64-*-linux* is a new target.
|
||||
Things that needed aix.h now also include xcoff.h
|
||||
|
||||
* config/rs6000/rs6000.h: Split XCOFF specific stuff into
|
||||
xcoff.h.
|
||||
Move AIX specific stuff into aix.h.
|
||||
(ASM_LONG): Use DOUBLE_INT_ASM_OP if we are on a 64 bit target.
|
||||
(ASM_OUTPUT_DOUBLE_INT): Ditto.
|
||||
(TARGET_AIX): Renamed to TARGET_XCOFF, since the AIX ABI is used
|
||||
with more than just XCOFF now.
|
||||
(SET_ASM_OP): Remove, now defined where needed.
|
||||
(FUNCTION_PROLOGUE): New macro definition.
|
||||
(FUNCTION_EPILOGUE): New macro definition.
|
||||
(CONST_OK_FOR_LETTER_P): Change N to require that value is
|
||||
positive, too.
|
||||
(ASM_OPEN_PAREN, ASM_CLOSE_PAREN): New macro definition.
|
||||
(PREDICATE_CODES): Added exact_log2_cint_operand,
|
||||
reg_or_add_cint64_operand, reg_or_sub_cint64_operand.
|
||||
|
||||
* config/rs6000/rs6000.c: #ifdef XCOFF debugging info stuff on
|
||||
XCOFF_DEBUGGING_INFO.
|
||||
Use DOUBLE_INT_ASM_OP where approriate.
|
||||
(rs6000_emit_set_long_const): New function.
|
||||
(rs6000_emit_set_const): New function.
|
||||
(reg_or_sub_cint64_operand): New function.
|
||||
(reg_or_add_cint64_operand): New function.
|
||||
(exact_log2_cint_operand): New function.
|
||||
|
||||
* config/rs6000/rs6000.md: Fix emitting of constants.
|
||||
Fix patterns that were AIX ABI specific, but depended on
|
||||
!TARGET_ELF (instead of DEFAULT_ABI == ABI_AIX).
|
||||
|
||||
* config/rs6000/xcoff.h: New file.
|
||||
|
||||
* config/rs6000/linux64.h: New file.
|
||||
|
||||
* config/rs6000/darwin.h: Copy needed AIX alignment definitions.
|
||||
|
||||
|
||||
2001-07-31 Graham Stott <grahams@redhat.com>
|
||||
|
||||
* function.c (pad_below): Revert 2001-07-26 patch.
|
||||
|
|
|
@ -2559,9 +2559,16 @@ romp-*-openbsd*)
|
|||
powerpc-*-openbsd*)
|
||||
tmake_file="${tmake_file} rs6000/t-rs6000 rs6000/t-openbsd"
|
||||
;;
|
||||
powerpc64-*-linux*)
|
||||
tm_file="${tm_file} svr4.h rs6000/sysv4.h rs6000/linux64.h"
|
||||
out_file=rs6000/rs6000.c
|
||||
tmake_file="rs6000/t-ppcos t-slibgcc-elf-ver t-linux rs6000/t-ppccomm"
|
||||
xmake_file=x-linux
|
||||
extra_headers=ppc-asm.h
|
||||
;;
|
||||
powerpc-*-beos*)
|
||||
cpu_type=rs6000
|
||||
tm_file="${tm_file} rs6000/aix.h rs6000/beos.h"
|
||||
tm_file="${tm_file} rs6000/aix.h rs6000/beos.h rs6000/xcoff.h"
|
||||
xm_defines=POSIX
|
||||
xm_file=rs6000/xm-beos.h
|
||||
tmake_file=rs6000/t-beos
|
||||
|
@ -2700,27 +2707,27 @@ powerpcle-*-solaris2*)
|
|||
;;
|
||||
rs6000-ibm-aix3.[01]*)
|
||||
xm_defines=POSIX
|
||||
tm_file="${tm_file} rs6000/aix.h rs6000/aix31.h"
|
||||
tm_file="${tm_file} rs6000/aix.h rs6000/aix31.h rs6000/xcoff.h"
|
||||
float_format=none
|
||||
use_collect2=yes
|
||||
;;
|
||||
rs6000-ibm-aix3.2.[456789]* | powerpc-ibm-aix3.2.[456789]*)
|
||||
xm_defines=POSIX
|
||||
tm_file="${tm_file} rs6000/aix.h rs6000/aix3newas.h"
|
||||
tm_file="${tm_file} rs6000/aix.h rs6000/aix3newas.h rs6000/xcoff.h"
|
||||
tmake_file=rs6000/t-newas
|
||||
float_format=none
|
||||
use_collect2=yes
|
||||
;;
|
||||
rs6000-ibm-aix4.[12]* | powerpc-ibm-aix4.[12]*)
|
||||
xm_defines=POSIX
|
||||
tm_file="${tm_file} rs6000/aix.h rs6000/aix41.h"
|
||||
tm_file="${tm_file} rs6000/aix.h rs6000/aix41.h rs6000/xcoff.h"
|
||||
tmake_file=rs6000/t-newas
|
||||
float_format=none
|
||||
use_collect2=yes
|
||||
;;
|
||||
rs6000-ibm-aix4.[3456789]* | powerpc-ibm-aix4.[3456789]*)
|
||||
xm_defines=POSIX
|
||||
tm_file="${tm_file} rs6000/aix.h rs6000/aix43.h"
|
||||
tm_file="${tm_file} rs6000/aix.h rs6000/aix43.h rs6000/xcoff.h"
|
||||
tmake_file=rs6000/t-aix43
|
||||
float_format=none
|
||||
use_collect2=yes
|
||||
|
@ -2728,7 +2735,7 @@ rs6000-ibm-aix4.[3456789]* | powerpc-ibm-aix4.[3456789]*)
|
|||
;;
|
||||
rs6000-ibm-aix[56789].* | powerpc-ibm-aix[56789].*)
|
||||
xm_defines=POSIX
|
||||
tm_file="${tm_file} rs6000/aix.h rs6000/aix51.h"
|
||||
tm_file="${tm_file} rs6000/aix.h rs6000/aix51.h rs6000/xcoff.h"
|
||||
tmake_file=rs6000/t-aix43
|
||||
float_format=none
|
||||
use_collect2=yes
|
||||
|
@ -2736,13 +2743,13 @@ rs6000-ibm-aix[56789].* | powerpc-ibm-aix[56789].*)
|
|||
;;
|
||||
rs6000-ibm-aix*)
|
||||
xm_defines=POSIX
|
||||
tm_file="${tm_file} rs6000/aix.h"
|
||||
tm_file="${tm_file} rs6000/aix.h rs6000/xcoff.h"
|
||||
float_format=none
|
||||
use_collect2=yes
|
||||
;;
|
||||
rs6000-bull-bosx)
|
||||
xm_defines=POSIX
|
||||
tm_file="${tm_file} rs6000/aix.h"
|
||||
tm_file="${tm_file} rs6000/aix.h rs6000/xcoff.h"
|
||||
float_format=none
|
||||
use_collect2=yes
|
||||
;;
|
||||
|
|
|
@ -21,58 +21,20 @@ Boston, MA 02111-1307, USA. */
|
|||
|
||||
/* Yes! We are AIX! */
|
||||
#define DEFAULT_ABI ABI_AIX
|
||||
#define TARGET_OBJECT_FORMAT OBJECT_XCOFF
|
||||
|
||||
#undef TARGET_AIX
|
||||
#define TARGET_AIX 1
|
||||
/* The AIX linker will discard static constructors in object files before
|
||||
collect has a chance to see them, so scan the object files directly. */
|
||||
#define COLLECT_EXPORT_LIST
|
||||
|
||||
/* The RS/6000 uses the XCOFF format. */
|
||||
#define XCOFF_DEBUGGING_INFO
|
||||
|
||||
/* Define if the object format being used is COFF or a superset. */
|
||||
#define OBJECT_FORMAT_COFF
|
||||
|
||||
/* Define the magic numbers that we recognize as COFF.
|
||||
|
||||
AIX 4.3 adds U803XTOCMAGIC (0757) for 64-bit objects and AIX V5 adds
|
||||
U64_TOCMAGIC (0767), but collect2.c does not include files in the
|
||||
correct order to conditionally define the symbolic name in this macro.
|
||||
|
||||
The AIX linker accepts import/export files as object files,
|
||||
so accept "#!" (0x2321) magic number. */
|
||||
#define MY_ISCOFF(magic) \
|
||||
((magic) == U802WRMAGIC || (magic) == U802ROMAGIC \
|
||||
|| (magic) == U802TOCMAGIC || (magic) == 0757 || (magic) == 0767 \
|
||||
|| (magic) == 0x2321)
|
||||
|
||||
/* This is the only version of nm that collect2 can work with. */
|
||||
#define REAL_NM_FILE_NAME "/usr/ucb/nm"
|
||||
|
||||
/* We don't have GAS for the RS/6000 yet, so don't write out special
|
||||
.stabs in cc1plus. */
|
||||
|
||||
#define FASCIST_ASSEMBLER
|
||||
|
||||
/* We define this to prevent the name mangler from putting dollar signs into
|
||||
function names. */
|
||||
|
||||
#define NO_DOLLAR_IN_LABEL
|
||||
|
||||
/* We define this to 0 so that gcc will never accept a dollar sign in a
|
||||
variable name. This is needed because the AIX assembler will not accept
|
||||
dollar signs. */
|
||||
|
||||
#define DOLLARS_IN_IDENTIFIERS 0
|
||||
|
||||
/* AIX does not have any init/fini or ctor/dtor sections, so create
|
||||
static constructors and destructors as normal functions. */
|
||||
/* #define ASM_OUTPUT_CONSTRUCTOR(file, name) */
|
||||
/* #define ASM_OUTPUT_DESTRUCTOR(file, name) */
|
||||
|
||||
/* The prefix to add to user-visible assembler symbols. */
|
||||
#define USER_LABEL_PREFIX ""
|
||||
|
||||
#define USER_LABEL_PREFIX ""
|
||||
/* Don't turn -B into -L if the argument specifies a relative file name. */
|
||||
#define RELATIVE_PREFIX_NOT_LINKDIR
|
||||
|
||||
|
@ -90,6 +52,82 @@ Boston, MA 02111-1307, USA. */
|
|||
%{ansi: -D_ANSI_C_SOURCE}\
|
||||
%(cpp_cpu)"
|
||||
|
||||
/* Common CPP definitions used by CPP_SPEC among the various targets
|
||||
for handling -mcpu=xxx switches. */
|
||||
#define CPP_CPU_SPEC \
|
||||
"%{!mcpu*: \
|
||||
%{mpower: %{!mpower2: -D_ARCH_PWR}} \
|
||||
%{mpower2: -D_ARCH_PWR2} \
|
||||
%{mpowerpc*: -D_ARCH_PPC} \
|
||||
%{mno-power: %{!mpowerpc*: -D_ARCH_COM}} \
|
||||
%{!mno-power: %{!mpower2: %(cpp_default)}}} \
|
||||
%{mcpu=common: -D_ARCH_COM} \
|
||||
%{mcpu=power: -D_ARCH_PWR} \
|
||||
%{mcpu=power2: -D_ARCH_PWR2} \
|
||||
%{mcpu=powerpc: -D_ARCH_PPC} \
|
||||
%{mcpu=rios: -D_ARCH_PWR} \
|
||||
%{mcpu=rios1: -D_ARCH_PWR} \
|
||||
%{mcpu=rios2: -D_ARCH_PWR2} \
|
||||
%{mcpu=rsc: -D_ARCH_PWR} \
|
||||
%{mcpu=rsc1: -D_ARCH_PWR} \
|
||||
%{mcpu=401: -D_ARCH_PPC} \
|
||||
%{mcpu=403: -D_ARCH_PPC} \
|
||||
%{mcpu=505: -D_ARCH_PPC} \
|
||||
%{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \
|
||||
%{mcpu=602: -D_ARCH_PPC} \
|
||||
%{mcpu=603: -D_ARCH_PPC} \
|
||||
%{mcpu=603e: -D_ARCH_PPC} \
|
||||
%{mcpu=ec603e: -D_ARCH_PPC} \
|
||||
%{mcpu=604: -D_ARCH_PPC} \
|
||||
%{mcpu=604e: -D_ARCH_PPC} \
|
||||
%{mcpu=620: -D_ARCH_PPC} \
|
||||
%{mcpu=740: -D_ARCH_PPC} \
|
||||
%{mcpu=750: -D_ARCH_PPC} \
|
||||
%{mcpu=801: -D_ARCH_PPC} \
|
||||
%{mcpu=821: -D_ARCH_PPC} \
|
||||
%{mcpu=823: -D_ARCH_PPC} \
|
||||
%{mcpu=860: -D_ARCH_PPC}"
|
||||
|
||||
#define CPP_DEFAULT_SPEC "-D_ARCH_PWR"
|
||||
|
||||
/* Common ASM definitions used by ASM_SPEC among the various targets
|
||||
for handling -mcpu=xxx switches. */
|
||||
#define ASM_CPU_SPEC \
|
||||
"%{!mcpu*: \
|
||||
%{mpower: %{!mpower2: -mpwr}} \
|
||||
%{mpower2: -mpwrx} \
|
||||
%{mpowerpc*: -mppc} \
|
||||
%{mno-power: %{!mpowerpc*: -mcom}} \
|
||||
%{!mno-power: %{!mpower2: %(asm_default)}}} \
|
||||
%{mcpu=common: -mcom} \
|
||||
%{mcpu=power: -mpwr} \
|
||||
%{mcpu=power2: -mpwrx} \
|
||||
%{mcpu=powerpc: -mppc} \
|
||||
%{mcpu=rios: -mpwr} \
|
||||
%{mcpu=rios1: -mpwr} \
|
||||
%{mcpu=rios2: -mpwrx} \
|
||||
%{mcpu=rsc: -mpwr} \
|
||||
%{mcpu=rsc1: -mpwr} \
|
||||
%{mcpu=401: -mppc} \
|
||||
%{mcpu=403: -mppc} \
|
||||
%{mcpu=505: -mppc} \
|
||||
%{mcpu=601: -m601} \
|
||||
%{mcpu=602: -mppc} \
|
||||
%{mcpu=603: -mppc} \
|
||||
%{mcpu=603e: -mppc} \
|
||||
%{mcpu=ec603e: -mppc} \
|
||||
%{mcpu=604: -mppc} \
|
||||
%{mcpu=604e: -mppc} \
|
||||
%{mcpu=620: -mppc} \
|
||||
%{mcpu=740: -mppc} \
|
||||
%{mcpu=750: -mppc} \
|
||||
%{mcpu=801: -mppc} \
|
||||
%{mcpu=821: -mppc} \
|
||||
%{mcpu=823: -mppc} \
|
||||
%{mcpu=860: -mppc}"
|
||||
|
||||
#define ASM_DEFAULT_SPEC ""
|
||||
|
||||
/* Tell the assembler to assume that all undefined names are external.
|
||||
|
||||
Don't do this until the fixed IBM assembler is more generally available.
|
||||
|
@ -136,161 +174,25 @@ Boston, MA 02111-1307, USA. */
|
|||
#define LIB_SPEC "%{pg:-L/lib/profiled -L/usr/lib/profiled}\
|
||||
%{p:-L/lib/profiled -L/usr/lib/profiled} %{!shared:%{g*:-lg}} -lc"
|
||||
|
||||
/* Define the extra sections we need. We define three: one is the read-only
|
||||
data section which is used for constants. This is a csect whose name is
|
||||
derived from the name of the input file. The second is for initialized
|
||||
global variables. This is a csect whose name is that of the variable.
|
||||
The third is the TOC. */
|
||||
/* AIX word-aligns FP doubles but doubleword-aligns 64-bit ints. */
|
||||
#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) \
|
||||
(TYPE_MODE (TREE_CODE (TREE_TYPE (FIELD)) == ARRAY_TYPE \
|
||||
? get_inner_array_type (FIELD) \
|
||||
: TREE_TYPE (FIELD)) == DFmode \
|
||||
? MIN ((COMPUTED), 32) : (COMPUTED))
|
||||
|
||||
#define EXTRA_SECTIONS \
|
||||
read_only_data, private_data, read_only_private_data, toc, bss
|
||||
/* AIX increases natural record alignment to doubleword if the first
|
||||
field is an FP double while the FP fields remain word aligned. */
|
||||
#define ROUND_TYPE_ALIGN(STRUCT, COMPUTED, SPECIFIED) \
|
||||
((TREE_CODE (STRUCT) == RECORD_TYPE \
|
||||
|| TREE_CODE (STRUCT) == UNION_TYPE \
|
||||
|| TREE_CODE (STRUCT) == QUAL_UNION_TYPE) \
|
||||
&& TYPE_FIELDS (STRUCT) != 0 \
|
||||
&& DECL_MODE (TYPE_FIELDS (STRUCT)) == DFmode \
|
||||
? MAX (MAX ((COMPUTED), (SPECIFIED)), BIGGEST_ALIGNMENT) \
|
||||
: MAX ((COMPUTED), (SPECIFIED)))
|
||||
|
||||
/* Define the routines to implement these extra sections.
|
||||
BIGGEST_ALIGNMENT is 64, so align the sections that much. */
|
||||
|
||||
#define EXTRA_SECTION_FUNCTIONS \
|
||||
\
|
||||
void \
|
||||
read_only_data_section () \
|
||||
{ \
|
||||
if (in_section != read_only_data) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "\t.csect %s[RO],3\n", \
|
||||
xcoff_read_only_section_name); \
|
||||
in_section = read_only_data; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
private_data_section () \
|
||||
{ \
|
||||
if (in_section != private_data) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "\t.csect %s[RW],3\n", \
|
||||
xcoff_private_data_section_name); \
|
||||
in_section = private_data; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
read_only_private_data_section () \
|
||||
{ \
|
||||
if (in_section != read_only_private_data) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "\t.csect %s[RO],3\n", \
|
||||
xcoff_private_data_section_name); \
|
||||
in_section = read_only_private_data; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
toc_section () \
|
||||
{ \
|
||||
if (TARGET_MINIMAL_TOC) \
|
||||
{ \
|
||||
/* toc_section is always called at least once from ASM_FILE_START, \
|
||||
so this is guaranteed to always be defined once and only once \
|
||||
in each file. */ \
|
||||
if (! toc_initialized) \
|
||||
{ \
|
||||
fputs ("\t.toc\nLCTOC..1:\n", asm_out_file); \
|
||||
fputs ("\t.tc toc_table[TC],toc_table[RW]\n", asm_out_file); \
|
||||
toc_initialized = 1; \
|
||||
} \
|
||||
\
|
||||
if (in_section != toc) \
|
||||
fprintf (asm_out_file, "\t.csect toc_table[RW]%s\n", \
|
||||
(TARGET_32BIT ? "" : ",3")); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (in_section != toc) \
|
||||
fputs ("\t.toc\n", asm_out_file); \
|
||||
} \
|
||||
in_section = toc; \
|
||||
}
|
||||
|
||||
/* Define the name of our readonly data section. */
|
||||
|
||||
#define READONLY_DATA_SECTION read_only_data_section
|
||||
|
||||
/* Select the section for an initialized data object.
|
||||
|
||||
On the RS/6000, we have a special section for all variables except those
|
||||
that are static. */
|
||||
|
||||
#define SELECT_SECTION(EXP,RELOC) \
|
||||
{ \
|
||||
if ((TREE_CODE (EXP) == STRING_CST \
|
||||
&& ! flag_writable_strings) \
|
||||
|| (TREE_CODE_CLASS (TREE_CODE (EXP)) == 'd' \
|
||||
&& TREE_READONLY (EXP) && ! TREE_THIS_VOLATILE (EXP) \
|
||||
&& DECL_INITIAL (EXP) \
|
||||
&& (DECL_INITIAL (EXP) == error_mark_node \
|
||||
|| TREE_CONSTANT (DECL_INITIAL (EXP))) \
|
||||
&& ! (RELOC))) \
|
||||
{ \
|
||||
if (TREE_PUBLIC (EXP)) \
|
||||
read_only_data_section (); \
|
||||
else \
|
||||
read_only_private_data_section (); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (TREE_PUBLIC (EXP)) \
|
||||
data_section (); \
|
||||
else \
|
||||
private_data_section (); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Return non-zero if this entry is to be written into the constant
|
||||
pool in a special way. We do so if this is a SYMBOL_REF, LABEL_REF
|
||||
or a CONST containing one of them. If -mfp-in-toc (the default),
|
||||
we also do this for floating-point constants. We actually can only
|
||||
do this if the FP formats of the target and host machines are the
|
||||
same, but we can't check that since not every file that uses
|
||||
GO_IF_LEGITIMATE_ADDRESS_P includes real.h. We also do this when
|
||||
we can write the entry into the TOC and the entry is not larger
|
||||
than a TOC entry. */
|
||||
|
||||
#define ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X, MODE) \
|
||||
(TARGET_TOC \
|
||||
&& (GET_CODE (X) == SYMBOL_REF \
|
||||
|| (GET_CODE (X) == CONST && GET_CODE (XEXP (X, 0)) == PLUS \
|
||||
&& GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF) \
|
||||
|| GET_CODE (X) == LABEL_REF \
|
||||
|| (GET_CODE (X) == CONST_INT \
|
||||
&& GET_MODE_BITSIZE (MODE) <= GET_MODE_BITSIZE (Pmode)) \
|
||||
|| (GET_CODE (X) == CONST_DOUBLE \
|
||||
&& (TARGET_POWERPC64 \
|
||||
|| TARGET_MINIMAL_TOC \
|
||||
|| (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
|
||||
&& ! TARGET_NO_FP_IN_TOC)))))
|
||||
|
||||
/* Select section for constant in constant pool.
|
||||
|
||||
On RS/6000, all constants are in the private read-only data area.
|
||||
However, if this is being placed in the TOC it must be output as a
|
||||
toc entry. */
|
||||
|
||||
#define SELECT_RTX_SECTION(MODE, X) \
|
||||
{ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (X, MODE)) \
|
||||
toc_section (); \
|
||||
else \
|
||||
read_only_private_data_section (); \
|
||||
}
|
||||
|
||||
/* If we are referencing a function that is static or is known to be
|
||||
in this file, make the SYMBOL_REF special. We can use this to indicate
|
||||
that we can branch to this function without emitting a no-op after the
|
||||
call. Do not set this flag if the function is weakly defined. */
|
||||
|
||||
#define ENCODE_SECTION_INFO(DECL) \
|
||||
if (TREE_CODE (DECL) == FUNCTION_DECL \
|
||||
&& (TREE_ASM_WRITTEN (DECL) || ! TREE_PUBLIC (DECL)) \
|
||||
&& ! DECL_WEAK (DECL)) \
|
||||
SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1;
|
||||
|
||||
/* Indicate that jump tables go in the text section. */
|
||||
|
||||
|
@ -315,23 +217,9 @@ toc_section () \
|
|||
{ "link_syscalls", LINK_SYSCALLS_SPEC }, \
|
||||
{ "link_libg", LINK_LIBG_SPEC }
|
||||
|
||||
/* FP save and restore routines. */
|
||||
#define SAVE_FP_PREFIX "._savef"
|
||||
#define SAVE_FP_SUFFIX ""
|
||||
#define RESTORE_FP_PREFIX "._restf"
|
||||
#define RESTORE_FP_SUFFIX ""
|
||||
|
||||
/* Define cutoff for using external functions to save floating point. */
|
||||
#define FP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) == 62 || (FIRST_REG) == 63)
|
||||
|
||||
/* Function name to call to do profiling. */
|
||||
#define RS6000_MCOUNT ".__mcount"
|
||||
|
||||
/* Function names to call to do floating point truncation. */
|
||||
|
||||
#define RS6000_ITRUNC "__itrunc"
|
||||
#define RS6000_UITRUNC "__uitrunc"
|
||||
|
||||
/* Optabs entries for the int->float routines, using the standard
|
||||
AIX names. */
|
||||
#define INIT_TARGET_OPTABS \
|
||||
|
@ -350,250 +238,6 @@ toc_section () \
|
|||
/* AIX allows r13 to be used. */
|
||||
#define FIXED_R13 0
|
||||
|
||||
/* This outputs NAME to FILE up to the first null or '['. */
|
||||
|
||||
#define RS6000_OUTPUT_BASENAME(FILE, NAME) \
|
||||
{ \
|
||||
const char *_p; \
|
||||
\
|
||||
STRIP_NAME_ENCODING (_p, (NAME)); \
|
||||
assemble_name ((FILE), _p); \
|
||||
}
|
||||
|
||||
/* This is how to output the definition of a user-level label named NAME,
|
||||
such as the label on a static function or variable NAME. */
|
||||
|
||||
#define ASM_OUTPUT_LABEL(FILE,NAME) \
|
||||
do { RS6000_OUTPUT_BASENAME (FILE, NAME); fputs (":\n", FILE); } while (0)
|
||||
|
||||
/* This is how to output a command to make the user-level label named NAME
|
||||
defined for reference from other files. */
|
||||
|
||||
#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
|
||||
do { fputs ("\t.globl ", FILE); \
|
||||
RS6000_OUTPUT_BASENAME (FILE, NAME); putc ('\n', FILE);} while (0)
|
||||
|
||||
/* Remove any trailing [DS] or the like from the symbol name. */
|
||||
|
||||
#define STRIP_NAME_ENCODING(VAR,NAME) \
|
||||
do \
|
||||
{ \
|
||||
const char *_name = (NAME); \
|
||||
size_t _len; \
|
||||
if (*_name == '*') \
|
||||
_name++; \
|
||||
_len = strlen (_name); \
|
||||
if (_name[_len - 1] != ']') \
|
||||
(VAR) = _name; \
|
||||
else \
|
||||
{ \
|
||||
char *_new_name = (char *) alloca (_len + 1); \
|
||||
strcpy (_new_name, _name); \
|
||||
_new_name[_len - 4] = '\0'; \
|
||||
(VAR) = _new_name; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Output at beginning of assembler file.
|
||||
|
||||
Initialize the section names for the RS/6000 at this point.
|
||||
|
||||
Specify filename, including full path, to assembler.
|
||||
|
||||
We want to go into the TOC section so at least one .toc will be emitted.
|
||||
Also, in order to output proper .bs/.es pairs, we need at least one static
|
||||
[RW] section emitted.
|
||||
|
||||
Finally, declare mcount when profiling to make the assembler happy. */
|
||||
|
||||
#define ASM_FILE_START(FILE) \
|
||||
{ \
|
||||
rs6000_gen_section_name (&xcoff_bss_section_name, \
|
||||
main_input_filename, ".bss_"); \
|
||||
rs6000_gen_section_name (&xcoff_private_data_section_name, \
|
||||
main_input_filename, ".rw_"); \
|
||||
rs6000_gen_section_name (&xcoff_read_only_section_name, \
|
||||
main_input_filename, ".ro_"); \
|
||||
\
|
||||
fprintf (FILE, "\t.file\t\"%s\"\n", main_input_filename); \
|
||||
if (TARGET_64BIT) \
|
||||
fputs ("\t.machine\t\"ppc64\"\n", FILE); \
|
||||
toc_section (); \
|
||||
if (write_symbols != NO_DEBUG) \
|
||||
private_data_section (); \
|
||||
text_section (); \
|
||||
if (profile_flag) \
|
||||
fprintf (FILE, "\t.extern %s\n", RS6000_MCOUNT); \
|
||||
rs6000_file_start (FILE, TARGET_CPU_DEFAULT); \
|
||||
}
|
||||
|
||||
/* Output at end of assembler file.
|
||||
|
||||
On the RS/6000, referencing data should automatically pull in text. */
|
||||
|
||||
#define ASM_FILE_END(FILE) \
|
||||
{ \
|
||||
text_section (); \
|
||||
fputs ("_section_.text:\n", FILE); \
|
||||
data_section (); \
|
||||
fputs (TARGET_32BIT \
|
||||
? "\t.long _section_.text\n" : "\t.llong _section_.text\n", FILE); \
|
||||
}
|
||||
|
||||
/* This macro produces the initial definition of a function name.
|
||||
On the RS/6000, we need to place an extra '.' in the function name and
|
||||
output the function descriptor.
|
||||
|
||||
The csect for the function will have already been created by the
|
||||
`text_section' call previously done. We do have to go back to that
|
||||
csect, however.
|
||||
|
||||
The third and fourth parameters to the .function pseudo-op (16 and 044)
|
||||
are placeholders which no longer have any use. */
|
||||
|
||||
#define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL) \
|
||||
{ if (TREE_PUBLIC (DECL)) \
|
||||
{ \
|
||||
fputs ("\t.globl .", FILE); \
|
||||
RS6000_OUTPUT_BASENAME (FILE, NAME); \
|
||||
putc ('\n', FILE); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
fputs ("\t.lglobl .", FILE); \
|
||||
RS6000_OUTPUT_BASENAME (FILE, NAME); \
|
||||
putc ('\n', FILE); \
|
||||
} \
|
||||
fputs ("\t.csect ", FILE); \
|
||||
RS6000_OUTPUT_BASENAME (FILE, NAME); \
|
||||
fputs (TARGET_32BIT ? "[DS]\n" : "[DS],3\n", FILE); \
|
||||
RS6000_OUTPUT_BASENAME (FILE, NAME); \
|
||||
fputs (":\n", FILE); \
|
||||
fputs (TARGET_32BIT ? "\t.long ." : "\t.llong .", FILE); \
|
||||
RS6000_OUTPUT_BASENAME (FILE, NAME); \
|
||||
fputs (", TOC[tc0], 0\n", FILE); \
|
||||
in_section = no_section; \
|
||||
function_section(DECL); \
|
||||
putc ('.', FILE); \
|
||||
RS6000_OUTPUT_BASENAME (FILE, NAME); \
|
||||
fputs (":\n", FILE); \
|
||||
if (write_symbols == XCOFF_DEBUG) \
|
||||
xcoffout_declare_function (FILE, DECL, NAME); \
|
||||
}
|
||||
|
||||
/* Output a reference to SYM on FILE. */
|
||||
|
||||
#define ASM_OUTPUT_SYMBOL_REF(FILE, SYM) \
|
||||
rs6000_output_symbol_ref (FILE, SYM)
|
||||
|
||||
/* This says how to output an external. */
|
||||
|
||||
#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \
|
||||
{ rtx _symref = XEXP (DECL_RTL (DECL), 0); \
|
||||
if ((TREE_CODE (DECL) == VAR_DECL \
|
||||
|| TREE_CODE (DECL) == FUNCTION_DECL) \
|
||||
&& (NAME)[strlen (NAME) - 1] != ']') \
|
||||
{ \
|
||||
char *_name = (char *) permalloc (strlen (XSTR (_symref, 0)) + 5); \
|
||||
strcpy (_name, XSTR (_symref, 0)); \
|
||||
strcat (_name, TREE_CODE (DECL) == FUNCTION_DECL ? "[DS]" : "[RW]"); \
|
||||
XSTR (_symref, 0) = _name; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* This is how to output an internal numbered label where
|
||||
PREFIX is the class of label and NUM is the number within the class. */
|
||||
|
||||
#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
|
||||
fprintf (FILE, "%s..%d:\n", PREFIX, NUM)
|
||||
|
||||
/* This is how to output an internal label prefix. rs6000.c uses this
|
||||
when generating traceback tables. */
|
||||
|
||||
#define ASM_OUTPUT_INTERNAL_LABEL_PREFIX(FILE,PREFIX) \
|
||||
fprintf (FILE, "%s..", PREFIX)
|
||||
|
||||
/* This is how to output a label for a jump table. Arguments are the same as
|
||||
for ASM_OUTPUT_INTERNAL_LABEL, except the insn for the jump table is
|
||||
passed. */
|
||||
|
||||
#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLEINSN) \
|
||||
{ ASM_OUTPUT_ALIGN (FILE, 2); ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); }
|
||||
|
||||
/* This is how to store into the string LABEL
|
||||
the symbol_ref name of an internal numbered label where
|
||||
PREFIX is the class of label and NUM is the number within the class.
|
||||
This is suitable for output with `assemble_name'. */
|
||||
|
||||
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
|
||||
sprintf (LABEL, "*%s..%ld", (PREFIX), (long)(NUM))
|
||||
|
||||
/* This is how to output an assembler line to define N characters starting
|
||||
at P to FILE. */
|
||||
|
||||
#define ASM_OUTPUT_ASCII(FILE, P, N) output_ascii ((FILE), (P), (N))
|
||||
|
||||
/* This is how to advance the location counter by SIZE bytes. */
|
||||
|
||||
#define ASM_OUTPUT_SKIP(FILE,SIZE) \
|
||||
fprintf (FILE, "\t.space %d\n", (SIZE))
|
||||
|
||||
/* This says how to output an assembler line
|
||||
to define a global common symbol. */
|
||||
|
||||
#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGNMENT) \
|
||||
do { fputs (".comm ", (FILE)); \
|
||||
RS6000_OUTPUT_BASENAME ((FILE), (NAME)); \
|
||||
if ( (SIZE) > 4) \
|
||||
fprintf ((FILE), ",%d,3\n", (SIZE)); \
|
||||
else \
|
||||
fprintf( (FILE), ",%d\n", (SIZE)); \
|
||||
} while (0)
|
||||
|
||||
/* These are various definitions for DWARF output. They could just
|
||||
use '.long' or '.word', but that aligns to a 4-byte boundary which
|
||||
is not what is required. So we define a million macros... */
|
||||
|
||||
#define UNALIGNED_SHORT_ASM_OP "\t.vbyte\t2,"
|
||||
#define UNALIGNED_INT_ASM_OP "\t.vbyte\t4,"
|
||||
#define UNALIGNED_DOUBLE_INT_ASM_OP "\t.vbyte\t8,"
|
||||
|
||||
/* Output before instructions. */
|
||||
#define TEXT_SECTION_ASM_OP "\t.csect .text[PR]"
|
||||
|
||||
/* Output before writable data.
|
||||
Align entire section to BIGGEST_ALIGNMENT. */
|
||||
#define DATA_SECTION_ASM_OP "\t.csect .data[RW],3"
|
||||
|
||||
/* Define unique section name -- functions only. */
|
||||
#define UNIQUE_SECTION(DECL,RELOC) \
|
||||
do { \
|
||||
int len; \
|
||||
const char *name; \
|
||||
char *string; \
|
||||
\
|
||||
if (TREE_CODE (DECL) == FUNCTION_DECL) { \
|
||||
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL)); \
|
||||
len = strlen (name) + 5; \
|
||||
string = alloca (len) + 1; \
|
||||
sprintf (string, ".%s[PR]", name); \
|
||||
DECL_SECTION_NAME (DECL) = build_string (len, string); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ASM_OUTPUT_SECTION_NAME(ASM_OUT_FILE,DECL,NAME,RELOC) \
|
||||
do { fputs ("\t.csect ", ASM_OUT_FILE); \
|
||||
fputs (TREE_STRING_POINTER (DECL_SECTION_NAME (DECL)), ASM_OUT_FILE); \
|
||||
putc ('\n', ASM_OUT_FILE); \
|
||||
} while (0)
|
||||
|
||||
/* Define the name of the section to use for the exception tables.
|
||||
TODO: test and see if we can use read_only_data_section, if so,
|
||||
remove this. */
|
||||
|
||||
#define EXCEPTION_SECTION data_section
|
||||
|
||||
/* __throw will restore its own return address to be the same as the
|
||||
return address of the function that the throw is being made to.
|
||||
This is unfortunate, because we want to check the original
|
||||
|
|
|
@ -173,3 +173,21 @@ Boston, MA 02111-1307, USA. */
|
|||
|
||||
/* Fix for emit_group_load (): force large constants to be pushed via regs. */
|
||||
#define ALWAYS_PUSH_CONSTS_USING_REGS_P 1
|
||||
|
||||
/* Darwin word-aligns FP doubles but doubleword-aligns 64-bit ints. */
|
||||
#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) \
|
||||
(TYPE_MODE (TREE_CODE (TREE_TYPE (FIELD)) == ARRAY_TYPE \
|
||||
? get_inner_array_type (FIELD) \
|
||||
: TREE_TYPE (FIELD)) == DFmode \
|
||||
? MIN ((COMPUTED), 32) : (COMPUTED))
|
||||
|
||||
/* Darwin increases natural record alignment to doubleword if the first
|
||||
field is an FP double while the FP fields remain word aligned. */
|
||||
#define ROUND_TYPE_ALIGN(STRUCT, COMPUTED, SPECIFIED) \
|
||||
((TREE_CODE (STRUCT) == RECORD_TYPE \
|
||||
|| TREE_CODE (STRUCT) == UNION_TYPE \
|
||||
|| TREE_CODE (STRUCT) == QUAL_UNION_TYPE) \
|
||||
&& TYPE_FIELDS (STRUCT) != 0 \
|
||||
&& DECL_MODE (TYPE_FIELDS (STRUCT)) == DFmode \
|
||||
? MAX (MAX ((COMPUTED), (SPECIFIED)), BIGGEST_ALIGNMENT) \
|
||||
: MAX ((COMPUTED), (SPECIFIED)))
|
||||
|
|
|
@ -69,6 +69,11 @@ Boston, MA 02111-1307, USA. */
|
|||
#undef ASM_APP_OFF
|
||||
#define ASM_APP_OFF "#NO_APP\n"
|
||||
|
||||
#undef DEFAULT_VTABLE_THUNKS
|
||||
#ifndef USE_GNULIBC_1
|
||||
#define DEFAULT_VTABLE_THUNKS 1
|
||||
#endif
|
||||
|
||||
/* Do code reading to identify a signal frame, and set the frame
|
||||
state data appropriately. See unwind-dw2.c for the structs. */
|
||||
|
||||
|
|
307
gcc/config/rs6000/linux64.h
Normal file
307
gcc/config/rs6000/linux64.h
Normal file
|
@ -0,0 +1,307 @@
|
|||
/* Definitions of target machine for GNU compiler,
|
||||
for 64 bit powerpc linux.
|
||||
Copyright (C) 2000, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Yes! We are AIX! Err. Wait. We're Linux!. No, wait, we're a
|
||||
combo of both!*/
|
||||
#undef DEFAULT_ABI
|
||||
#define DEFAULT_ABI ABI_AIX
|
||||
|
||||
#undef TARGET_AIX
|
||||
#define TARGET_AIX 1
|
||||
|
||||
#undef TARGET_DEFAULT
|
||||
#define TARGET_DEFAULT (MASK_POWERPC | MASK_POWERPC64 | MASK_64BIT | MASK_NEW_MNEMONICS)
|
||||
|
||||
/* AIX does not have any init/fini or ctor/dtor sections, so create
|
||||
static constructors and destructors as normal functions. */
|
||||
/* #define ASM_OUTPUT_CONSTRUCTOR(file, name) */
|
||||
/* #define ASM_OUTPUT_DESTRUCTOR(file, name) */
|
||||
#define USER_LABEL_PREFIX ""
|
||||
|
||||
/* Tell the assembler to assume that all undefined names are external.
|
||||
|
||||
Don't do this until the fixed IBM assembler is more generally available.
|
||||
When this becomes permanently defined, the ASM_OUTPUT_EXTERNAL,
|
||||
ASM_OUTPUT_EXTERNAL_LIBCALL, and RS6000_OUTPUT_BASENAME macros will no
|
||||
longer be needed. Also, the extern declaration of mcount in ASM_FILE_START
|
||||
will no longer be needed. */
|
||||
|
||||
/* #define ASM_SPEC "-u %(asm_cpu)" */
|
||||
|
||||
/* AIX word-aligns FP doubles but doubleword-aligns 64-bit ints. */
|
||||
#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) \
|
||||
(TYPE_MODE (TREE_CODE (TREE_TYPE (FIELD)) == ARRAY_TYPE \
|
||||
? get_inner_array_type (FIELD) \
|
||||
: TREE_TYPE (FIELD)) == DFmode \
|
||||
? MIN ((COMPUTED), 32) : (COMPUTED))
|
||||
|
||||
/* AIX increases natural record alignment to doubleword if the first
|
||||
field is an FP double while the FP fields remain word aligned. */
|
||||
#define ROUND_TYPE_ALIGN(STRUCT, COMPUTED, SPECIFIED) \
|
||||
((TREE_CODE (STRUCT) == RECORD_TYPE \
|
||||
|| TREE_CODE (STRUCT) == UNION_TYPE \
|
||||
|| TREE_CODE (STRUCT) == QUAL_UNION_TYPE) \
|
||||
&& TYPE_FIELDS (STRUCT) != 0 \
|
||||
&& DECL_MODE (TYPE_FIELDS (STRUCT)) == DFmode \
|
||||
? MAX (MAX ((COMPUTED), (SPECIFIED)), BIGGEST_ALIGNMENT) \
|
||||
: MAX ((COMPUTED), (SPECIFIED)))
|
||||
|
||||
/* Indicate that jump tables go in the text section. */
|
||||
#undef JUMP_TABLES_IN_TEXT_SECTION
|
||||
#define JUMP_TABLES_IN_TEXT_SECTION 1
|
||||
|
||||
/* Define cutoff for using external functions to save floating point. */
|
||||
#undef FP_SAVE_INLINE
|
||||
#define FP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) == 62 || (FIRST_REG) == 63)
|
||||
|
||||
#undef TARGET_NO_TOC
|
||||
#undef TARGET_TOC
|
||||
|
||||
/* 64-bit PowerPC Linux always has a TOC. */
|
||||
#define TARGET_NO_TOC 0
|
||||
#define TARGET_TOC 1
|
||||
|
||||
/* 64-bit PowerPC Linux always has GPR13 fixed. */
|
||||
#define FIXED_R13 1
|
||||
|
||||
/* __throw will restore its own return address to be the same as the
|
||||
return address of the function that the throw is being made to.
|
||||
This is unfortunate, because we want to check the original
|
||||
return address to see if we need to restore the TOC.
|
||||
So we have to squirrel it away with this. */
|
||||
#define SETUP_FRAME_ADDRESSES() rs6000_aix_emit_builtin_unwind_init ()
|
||||
|
||||
#define PROFILE_HOOK(LABEL) output_profile_hook (LABEL)
|
||||
/* Don't assume anything about the header files. */
|
||||
#define NO_IMPLICIT_EXTERN_C
|
||||
|
||||
#undef MD_EXEC_PREFIX
|
||||
#undef MD_STARTFILE_PREFIX
|
||||
|
||||
#undef CPP_PREDEFINES
|
||||
#define CPP_PREDEFINES \
|
||||
"-D_PPC_ -D__PPC__ -D_PPC64_ -D__PPC64__ -D__powerpc__ -D__powerpc64__ \
|
||||
-D_PIC_ -D__PIC__ -D_BIG_ENDIAN -D__BIG_ENDIAN__ -D__ELF__ \
|
||||
-D__LONG_MAX__=9223372036854775807L \
|
||||
-Acpu=powerpc64 -Amachine=powerpc64"
|
||||
|
||||
#undef CPP_OS_DEFAULT_SPEC
|
||||
#define CPP_OS_DEFAULT_SPEC "%(cpp_os_linux)"
|
||||
|
||||
/* The GNU C++ standard library currently requires _GNU_SOURCE being
|
||||
defined on glibc-based systems. This temporary hack accomplishes this,
|
||||
it should go away as soon as libstdc++-v3 has a real fix. */
|
||||
#undef CPLUSPLUS_CPP_SPEC
|
||||
#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
|
||||
|
||||
#undef LINK_SHLIB_SPEC
|
||||
#define LINK_SHLIB_SPEC "%{shared:-shared} %{!shared: %{static:-static}}"
|
||||
|
||||
#undef LIB_DEFAULT_SPEC
|
||||
#define LIB_DEFAULT_SPEC "%(lib_linux)"
|
||||
|
||||
#undef STARTFILE_DEFAULT_SPEC
|
||||
#define STARTFILE_DEFAULT_SPEC "%(startfile_linux)"
|
||||
|
||||
#undef ENDFILE_DEFAULT_SPEC
|
||||
#define ENDFILE_DEFAULT_SPEC "%(endfile_linux)"
|
||||
|
||||
#undef LINK_START_DEFAULT_SPEC
|
||||
#define LINK_START_DEFAULT_SPEC "%(link_start_linux)"
|
||||
|
||||
#undef LINK_OS_DEFAULT_SPEC
|
||||
#define LINK_OS_DEFAULT_SPEC "%(link_os_linux)"
|
||||
|
||||
#undef LINK_OS_LINUX_SPEC
|
||||
#define LINK_OS_LINUX_SPEC "-m elf64ppc %{!shared: %{!static: \
|
||||
%{rdynamic:-export-dynamic} \
|
||||
%{!dynamic-linker:-dynamic-linker /lib/ld.so.1}}}"
|
||||
|
||||
#undef TOC_SECTION_ASM_OP
|
||||
#define TOC_SECTION_ASM_OP "\t.section\t\".toc\",\"aw\""
|
||||
|
||||
#undef MINIMAL_TOC_SECTION_ASM_OP
|
||||
#define MINIMAL_TOC_SECTION_ASM_OP "\t.section\t\".toc1\",\"aw\"\n\t.align 3"
|
||||
|
||||
#undef TARGET_VERSION
|
||||
#define TARGET_VERSION fprintf (stderr, " (PowerPC64 GNU/Linux)");
|
||||
|
||||
/* Must be at least as big as our pointer type. */
|
||||
#undef SIZE_TYPE
|
||||
#define SIZE_TYPE "long unsigned int"
|
||||
|
||||
#undef PTRDIFF_TYPE
|
||||
#define PTRDIFF_TYPE "long int"
|
||||
|
||||
#undef WCHAR_TYPE
|
||||
#define WCHAR_TYPE "int"
|
||||
#undef WCHAR_TYPE_SIZE
|
||||
#define WCHAR_TYPE_SIZE 32
|
||||
|
||||
/* Override rs6000.h definition. */
|
||||
#undef ASM_APP_ON
|
||||
#define ASM_APP_ON "#APP\n"
|
||||
|
||||
/* Override rs6000.h definition. */
|
||||
#undef ASM_APP_OFF
|
||||
#define ASM_APP_OFF "#NO_APP\n"
|
||||
|
||||
#undef DEFAULT_VTABLE_THUNKS
|
||||
#ifndef USE_GNULIBC_1
|
||||
#define DEFAULT_VTABLE_THUNKS 1
|
||||
#endif
|
||||
|
||||
/* PowerPC no-op instruction. */
|
||||
#undef RS6000_CALL_GLUE
|
||||
#define RS6000_CALL_GLUE "nop"
|
||||
|
||||
/* Dwarf2 debugging. */
|
||||
#undef PREFERRED_DEBUGGING_TYPE
|
||||
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
|
||||
|
||||
/* This macro gets just the user-specified name
|
||||
out of the string in a SYMBOL_REF. Discard
|
||||
a leading * or @. */
|
||||
#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \
|
||||
do { \
|
||||
const char *_name = SYMBOL_NAME; \
|
||||
while (*_name == '*' || *_name == '@') \
|
||||
_name++; \
|
||||
(VAR) = _name; \
|
||||
} while (0)
|
||||
|
||||
/* This is how to output a reference to a user-level label named NAME.
|
||||
`assemble_name' uses this. */
|
||||
|
||||
/* Override elfos.h definition. */
|
||||
#undef ASM_OUTPUT_LABELREF
|
||||
#define ASM_OUTPUT_LABELREF(FILE,NAME) \
|
||||
do { \
|
||||
const char *_name = NAME; \
|
||||
if (*_name == '@') \
|
||||
_name++; \
|
||||
\
|
||||
if (*_name == '*') \
|
||||
fprintf (FILE, "%s", _name + 1); \
|
||||
else \
|
||||
asm_fprintf (FILE, "%U%s", _name); \
|
||||
} while (0)
|
||||
|
||||
#undef ASM_DECLARE_FUNCTION_NAME
|
||||
#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
|
||||
do { \
|
||||
if (TARGET_RELOCATABLE && (get_pool_size () != 0 || profile_flag) \
|
||||
&& uses_TOC()) \
|
||||
{ \
|
||||
char buf[256]; \
|
||||
\
|
||||
ASM_OUTPUT_INTERNAL_LABEL (FILE, "LCL", rs6000_pic_labelno); \
|
||||
\
|
||||
ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 1); \
|
||||
fputs ("\t.quad ", FILE); \
|
||||
assemble_name (FILE, buf); \
|
||||
putc ('-', FILE); \
|
||||
ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno); \
|
||||
assemble_name (FILE, buf); \
|
||||
putc ('\n', FILE); \
|
||||
} \
|
||||
\
|
||||
fprintf (FILE, "%s", TYPE_ASM_OP); \
|
||||
assemble_name (FILE, NAME); \
|
||||
putc (',', FILE); \
|
||||
fprintf (FILE, TYPE_OPERAND_FMT, "function"); \
|
||||
putc ('\n', FILE); \
|
||||
ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
|
||||
\
|
||||
if (DEFAULT_ABI == ABI_AIX) \
|
||||
{ \
|
||||
const char *desc_name, *orig_name; \
|
||||
\
|
||||
STRIP_NAME_ENCODING (orig_name, NAME); \
|
||||
desc_name = orig_name; \
|
||||
while (*desc_name == '.') \
|
||||
desc_name++; \
|
||||
\
|
||||
if (TREE_PUBLIC (DECL)) \
|
||||
fprintf (FILE, "\t.globl %s\n", desc_name); \
|
||||
\
|
||||
fputs ("\t.section\t\".opd\",\"aw\"\n", FILE); \
|
||||
fprintf (FILE, "%s:\n", desc_name); \
|
||||
fprintf (FILE, "\t.quad %s\n", orig_name); \
|
||||
fputs ("\t.quad .TOC.@tocbase\n", FILE); \
|
||||
if (DEFAULT_ABI == ABI_AIX) \
|
||||
fputs ("\t.quad 0\n", FILE); \
|
||||
fprintf (FILE, "\t.previous\n"); \
|
||||
} \
|
||||
ASM_OUTPUT_LABEL (FILE, NAME); \
|
||||
} while (0)
|
||||
|
||||
/* Return non-zero if this entry is to be written into the constant
|
||||
pool in a special way. We do so if this is a SYMBOL_REF, LABEL_REF
|
||||
or a CONST containing one of them. If -mfp-in-toc (the default),
|
||||
we also do this for floating-point constants. We actually can only
|
||||
do this if the FP formats of the target and host machines are the
|
||||
same, but we can't check that since not every file that uses
|
||||
GO_IF_LEGITIMATE_ADDRESS_P includes real.h. We also do this when
|
||||
we can write the entry into the TOC and the entry is not larger
|
||||
than a TOC entry. */
|
||||
|
||||
#undef ASM_OUTPUT_SPECIAL_POOL_ENTRY_P
|
||||
#define ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X, MODE) \
|
||||
(TARGET_TOC \
|
||||
&& (GET_CODE (X) == SYMBOL_REF \
|
||||
|| (GET_CODE (X) == CONST && GET_CODE (XEXP (X, 0)) == PLUS \
|
||||
&& GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF) \
|
||||
|| GET_CODE (X) == LABEL_REF \
|
||||
|| (GET_CODE (X) == CONST_INT \
|
||||
&& GET_MODE_BITSIZE (MODE) <= GET_MODE_BITSIZE (Pmode)) \
|
||||
|| (GET_CODE (X) == CONST_DOUBLE \
|
||||
&& (TARGET_POWERPC64 \
|
||||
|| TARGET_MINIMAL_TOC \
|
||||
|| (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
|
||||
&& ! TARGET_NO_FP_IN_TOC)))))
|
||||
|
||||
/* This is how to output an assembler line defining an `int'
|
||||
constant. */
|
||||
#undef ASM_OUTPUT_INT
|
||||
#define ASM_OUTPUT_INT(FILE, VALUE) \
|
||||
do \
|
||||
{ \
|
||||
fputs ("\t.long ", (FILE)); \
|
||||
output_addr_const ((FILE), (VALUE)); \
|
||||
putc ('\n', (FILE)); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* This is how to output an assembler line defining a `double int'
|
||||
constant. */
|
||||
#undef ASM_OUTPUT_DOUBLE_INT
|
||||
#define ASM_OUTPUT_DOUBLE_INT(FILE, VALUE) \
|
||||
do \
|
||||
{ \
|
||||
fputs (DOUBLE_INT_ASM_OP, (FILE)); \
|
||||
output_addr_const ((FILE), (VALUE)); \
|
||||
putc ('\n', (FILE)); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#undef ASM_DEFAULT_SPEC
|
||||
#define ASM_DEFAULT_SPEC "-mppc64"
|
|
@ -34,6 +34,7 @@ extern int any_operand PARAMS ((rtx, enum machine_mode));
|
|||
extern int short_cint_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int u_short_cint_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int non_short_cint_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int exact_log2_cint_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int gpc_reg_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int cc_reg_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int cc_reg_not_cr0_operand PARAMS ((rtx, enum machine_mode));
|
||||
|
@ -42,6 +43,8 @@ extern int reg_or_neg_short_operand PARAMS ((rtx, enum machine_mode));
|
|||
extern int reg_or_u_short_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int reg_or_cint_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int reg_or_arith_cint_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int reg_or_add_cint64_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int reg_or_sub_cint64_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int reg_or_logical_cint_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int got_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int got_no_const_operand PARAMS ((rtx, enum machine_mode));
|
||||
|
@ -96,6 +99,7 @@ extern enum rtx_code rs6000_reverse_condition PARAMS ((enum machine_mode,
|
|||
extern void rs6000_emit_sCOND PARAMS ((enum rtx_code, rtx));
|
||||
extern void rs6000_emit_cbranch PARAMS ((enum rtx_code, rtx));
|
||||
extern char * output_cbranch PARAMS ((rtx, const char *, int, rtx));
|
||||
extern rtx rs6000_emit_set_const PARAMS ((rtx, enum machine_mode, rtx, int));
|
||||
extern int rs6000_emit_cmove PARAMS ((rtx, rtx, rtx, rtx));
|
||||
extern void rs6000_emit_minmax PARAMS ((rtx, enum rtx_code, rtx, rtx));
|
||||
extern void output_toc PARAMS ((FILE *, rtx, int, enum machine_mode));
|
||||
|
|
|
@ -128,6 +128,8 @@ static int rs6000_ra_ever_killed PARAMS ((void));
|
|||
static int rs6000_valid_type_attribute_p PARAMS ((tree, tree, tree, tree));
|
||||
static void rs6000_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||
static void rs6000_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||
static rtx rs6000_emit_set_long_const PARAMS ((rtx,
|
||||
HOST_WIDE_INT, HOST_WIDE_INT));
|
||||
|
||||
/* Default register names. */
|
||||
char rs6000_reg_names[][8] =
|
||||
|
@ -364,15 +366,16 @@ rs6000_override_options (default_cpu)
|
|||
}
|
||||
}
|
||||
|
||||
if (flag_pic && (DEFAULT_ABI == ABI_AIX))
|
||||
if (flag_pic && DEFAULT_ABI == ABI_AIX)
|
||||
{
|
||||
warning ("-f%s ignored for AIX (all code is position independent)",
|
||||
warning ("-f%s ignored (all code is position independent)",
|
||||
(flag_pic > 1) ? "PIC" : "pic");
|
||||
flag_pic = 0;
|
||||
}
|
||||
|
||||
#ifdef XCOFF_DEBUGGING_INFO
|
||||
if (flag_function_sections && (write_symbols != NO_DEBUG)
|
||||
&& (DEFAULT_ABI == ABI_AIX))
|
||||
&& DEFAULT_ABI == ABI_AIX)
|
||||
{
|
||||
warning ("-ffunction-sections disabled on AIX when debugging");
|
||||
flag_function_sections = 0;
|
||||
|
@ -383,6 +386,7 @@ rs6000_override_options (default_cpu)
|
|||
warning ("-fdata-sections not supported on AIX");
|
||||
flag_data_sections = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set debug flags */
|
||||
if (rs6000_debug_name)
|
||||
|
@ -585,6 +589,19 @@ non_short_cint_operand (op, mode)
|
|||
&& (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x8000) >= 0x10000);
|
||||
}
|
||||
|
||||
/* Returns 1 if OP is a CONST_INT that is a positive value
|
||||
and an exact power of 2. */
|
||||
|
||||
int
|
||||
exact_log2_cint_operand (op, mode)
|
||||
register rtx op;
|
||||
enum machine_mode mode ATTRIBUTE_UNUSED;
|
||||
{
|
||||
return (GET_CODE (op) == CONST_INT
|
||||
&& INTVAL (op) > 0
|
||||
&& exact_log2 (INTVAL (op)) >= 0);
|
||||
}
|
||||
|
||||
/* Returns 1 if OP is a register that is not special (i.e., not MQ,
|
||||
ctr, or lr). */
|
||||
|
||||
|
@ -693,6 +710,42 @@ reg_or_arith_cint_operand (op, mode)
|
|||
));
|
||||
}
|
||||
|
||||
/* Return 1 is the operand is either a non-special register or a 32-bit
|
||||
signed constant integer valid for 64-bit addition. */
|
||||
|
||||
int
|
||||
reg_or_add_cint64_operand (op, mode)
|
||||
register rtx op;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
return (gpc_reg_operand (op, mode)
|
||||
|| (GET_CODE (op) == CONST_INT
|
||||
&& INTVAL (op) < 0x7fff8000
|
||||
#if HOST_BITS_PER_WIDE_INT != 32
|
||||
&& ((unsigned HOST_WIDE_INT) (INTVAL (op) + 0x80008000)
|
||||
< 0x100000000ll)
|
||||
#endif
|
||||
));
|
||||
}
|
||||
|
||||
/* Return 1 is the operand is either a non-special register or a 32-bit
|
||||
signed constant integer valid for 64-bit subtraction. */
|
||||
|
||||
int
|
||||
reg_or_sub_cint64_operand (op, mode)
|
||||
register rtx op;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
return (gpc_reg_operand (op, mode)
|
||||
|| (GET_CODE (op) == CONST_INT
|
||||
&& (- INTVAL (op)) < 0x7fff8000
|
||||
#if HOST_BITS_PER_WIDE_INT != 32
|
||||
&& ((unsigned HOST_WIDE_INT) ((- INTVAL (op)) + 0x80008000)
|
||||
< 0x100000000ll)
|
||||
#endif
|
||||
));
|
||||
}
|
||||
|
||||
/* Return 1 is the operand is either a non-special register or ANY
|
||||
32-bit unsigned constant integer. */
|
||||
|
||||
|
@ -996,9 +1049,11 @@ add_operand (op, mode)
|
|||
register rtx op;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
return (reg_or_short_operand (op, mode)
|
||||
|| (GET_CODE (op) == CONST_INT
|
||||
&& CONST_OK_FOR_LETTER_P (INTVAL (op), 'L')));
|
||||
if (GET_CODE (op) == CONST_INT)
|
||||
return (CONST_OK_FOR_LETTER_P (INTVAL(op), 'I')
|
||||
|| CONST_OK_FOR_LETTER_P (INTVAL(op), 'L'));
|
||||
|
||||
return gpc_reg_operand (op, mode);
|
||||
}
|
||||
|
||||
/* Return 1 if OP is a constant but not a valid add_operand. */
|
||||
|
@ -1636,6 +1691,124 @@ rs6000_legitimate_address (mode, x, reg_ok_strict)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Try to output insns to set TARGET equal to the constant C if it can be
|
||||
done in less than N insns. Do all computations in MODE. Returns the place
|
||||
where the output has been placed if it can be done and the insns have been
|
||||
emitted. If it would take more than N insns, zero is returned and no
|
||||
insns and emitted. */
|
||||
|
||||
rtx
|
||||
rs6000_emit_set_const (dest, mode, source, n)
|
||||
rtx dest, source;
|
||||
enum machine_mode mode;
|
||||
int n ATTRIBUTE_UNUSED;
|
||||
{
|
||||
HOST_WIDE_INT c0, c1;
|
||||
|
||||
if (mode == QImode || mode == HImode || mode == SImode)
|
||||
{
|
||||
if (dest == NULL)
|
||||
dest = gen_reg_rtx (mode);
|
||||
emit_insn (gen_rtx_SET (VOIDmode, dest, source));
|
||||
return dest;
|
||||
}
|
||||
|
||||
if (GET_CODE (source) == CONST_INT)
|
||||
{
|
||||
c0 = INTVAL (source);
|
||||
c1 = -(c0 < 0);
|
||||
}
|
||||
else if (GET_CODE (source) == CONST_DOUBLE)
|
||||
{
|
||||
#if HOST_BITS_PER_WIDE_INT >= 64
|
||||
c0 = CONST_DOUBLE_LOW (source);
|
||||
c1 = -(c0 < 0);
|
||||
#else
|
||||
c0 = CONST_DOUBLE_LOW (source);
|
||||
c1 = CONST_DOUBLE_HIGH (source);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
abort();
|
||||
|
||||
return rs6000_emit_set_long_const (dest, c0, c1);
|
||||
}
|
||||
|
||||
/* Having failed to find a 3 insn sequence in rs6000_emit_set_const,
|
||||
fall back to a straight forward decomposition. We do this to avoid
|
||||
exponential run times encountered when looking for longer sequences
|
||||
with rs6000_emit_set_const. */
|
||||
static rtx
|
||||
rs6000_emit_set_long_const (dest, c1, c2)
|
||||
rtx dest;
|
||||
HOST_WIDE_INT c1, c2;
|
||||
{
|
||||
if (!TARGET_POWERPC64)
|
||||
{
|
||||
rtx operand1, operand2;
|
||||
|
||||
operand1 = operand_subword_force (dest, WORDS_BIG_ENDIAN == 0,
|
||||
DImode);
|
||||
operand2 = operand_subword_force (dest, WORDS_BIG_ENDIAN != 0,
|
||||
DImode);
|
||||
emit_move_insn (operand1, GEN_INT (c1));
|
||||
emit_move_insn (operand2, GEN_INT (c2));
|
||||
}
|
||||
else
|
||||
{
|
||||
HOST_WIDE_INT d1, d2, d3, d4;
|
||||
|
||||
/* Decompose the entire word */
|
||||
#if HOST_BITS_PER_WIDE_INT >= 64
|
||||
if (c2 != -(c1 < 0))
|
||||
abort ();
|
||||
d1 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
|
||||
c1 -= d1;
|
||||
d2 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
|
||||
c1 = (c1 - d2) >> 32;
|
||||
d3 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
|
||||
c1 -= d3;
|
||||
d4 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
|
||||
if (c1 != d4)
|
||||
abort ();
|
||||
#else
|
||||
d1 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
|
||||
c1 -= d1;
|
||||
d2 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
|
||||
if (c1 != d2)
|
||||
abort ();
|
||||
c2 += (d2 < 0);
|
||||
d3 = ((c2 & 0xffff) ^ 0x8000) - 0x8000;
|
||||
c2 -= d3;
|
||||
d4 = ((c2 & 0xffffffff) ^ 0x80000000) - 0x80000000;
|
||||
if (c2 != d4)
|
||||
abort ();
|
||||
#endif
|
||||
|
||||
/* Construct the high word */
|
||||
if (d4)
|
||||
{
|
||||
emit_move_insn (dest, GEN_INT (d4));
|
||||
if (d3)
|
||||
emit_move_insn (dest,
|
||||
gen_rtx_PLUS (DImode, dest, GEN_INT (d3)));
|
||||
}
|
||||
else
|
||||
emit_move_insn (dest, GEN_INT (d3));
|
||||
|
||||
/* Shift it into place */
|
||||
emit_move_insn (dest, gen_rtx_ASHIFT (DImode, dest, GEN_INT (32)));
|
||||
|
||||
/* Add in the low bits. */
|
||||
if (d2)
|
||||
emit_move_insn (dest, gen_rtx_PLUS (DImode, dest, GEN_INT (d2)));
|
||||
if (d1)
|
||||
emit_move_insn (dest, gen_rtx_PLUS (DImode, dest, GEN_INT (d1)));
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* Emit a move from SOURCE to DEST in mode MODE. */
|
||||
void
|
||||
rs6000_emit_move (dest, source, mode)
|
||||
|
@ -4107,6 +4280,7 @@ print_operand (file, x, code)
|
|||
case 'p':
|
||||
/* X is a CONST_INT that is a power of two. Output the logarithm. */
|
||||
if (! INT_P (x)
|
||||
|| INT_LOWPART (x) < 0
|
||||
|| (i = exact_log2 (INT_LOWPART (x))) < 0)
|
||||
output_operand_lossage ("invalid %%p value");
|
||||
else
|
||||
|
@ -4512,19 +4686,33 @@ print_operand_address (file, x)
|
|||
#endif
|
||||
else if (LEGITIMATE_CONSTANT_POOL_ADDRESS_P (x))
|
||||
{
|
||||
if (TARGET_AIX)
|
||||
if (TARGET_AIX && (!TARGET_ELF || !TARGET_MINIMAL_TOC))
|
||||
{
|
||||
rtx contains_minus = XEXP (x, 1);
|
||||
rtx minus;
|
||||
rtx contains_minus = XEXP (x, 1);
|
||||
rtx minus, symref;
|
||||
const char *name;
|
||||
|
||||
/* Find the (minus (sym) (toc)) buried in X, and temporarily
|
||||
turn it into (sym) for output_addr_const. */
|
||||
while (GET_CODE (XEXP (contains_minus, 0)) != MINUS)
|
||||
contains_minus = XEXP (contains_minus, 0);
|
||||
|
||||
minus = XEXP (contains_minus, 0);
|
||||
XEXP (contains_minus, 0) = XEXP (minus, 0);
|
||||
output_addr_const (file, XEXP (x, 1));
|
||||
minus = XEXP (contains_minus, 0);
|
||||
symref = XEXP (minus, 0);
|
||||
XEXP (contains_minus, 0) = symref;
|
||||
if (TARGET_ELF)
|
||||
{
|
||||
char *newname;
|
||||
|
||||
name = XSTR (symref, 0);
|
||||
newname = alloca (strlen (name) + sizeof ("@toc"));
|
||||
strcpy (newname, name);
|
||||
strcat (newname, "@toc");
|
||||
XSTR (symref, 0) = newname;
|
||||
}
|
||||
output_addr_const (file, XEXP (x, 1));
|
||||
if (TARGET_ELF)
|
||||
XSTR (symref, 0) = name;
|
||||
XEXP (contains_minus, 0) = minus;
|
||||
}
|
||||
else
|
||||
|
@ -5137,8 +5325,9 @@ rs6000_stack_info ()
|
|||
info_ptr->first_gp_reg_save = first_reg_to_save ();
|
||||
/* Assume that we will have to save PIC_OFFSET_TABLE_REGNUM,
|
||||
even if it currently looks like we won't. */
|
||||
if (((flag_pic == 1
|
||||
&& (abi == ABI_V4 || abi == ABI_SOLARIS))
|
||||
if (((TARGET_TOC && TARGET_MINIMAL_TOC)
|
||||
|| (flag_pic == 1
|
||||
&& (abi == ABI_V4 || abi == ABI_SOLARIS))
|
||||
|| (flag_pic &&
|
||||
abi == ABI_DARWIN))
|
||||
&& info_ptr->first_gp_reg_save > PIC_OFFSET_TABLE_REGNUM)
|
||||
|
@ -5459,7 +5648,7 @@ rs6000_emit_load_toc_table (fromprolog)
|
|||
rtx dest;
|
||||
dest = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
|
||||
|
||||
if (TARGET_ELF)
|
||||
if (TARGET_ELF && DEFAULT_ABI != ABI_AIX)
|
||||
{
|
||||
if ((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
|
||||
&& flag_pic == 1)
|
||||
|
@ -5467,10 +5656,7 @@ rs6000_emit_load_toc_table (fromprolog)
|
|||
rtx temp = (fromprolog
|
||||
? gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)
|
||||
: gen_reg_rtx (Pmode));
|
||||
if (TARGET_32BIT)
|
||||
rs6000_maybe_dead (emit_insn (gen_load_toc_v4_pic_si (temp)));
|
||||
else
|
||||
rs6000_maybe_dead (emit_insn (gen_load_toc_v4_pic_di (temp)));
|
||||
rs6000_maybe_dead (emit_insn (gen_load_toc_v4_pic_si (temp)));
|
||||
rs6000_maybe_dead (emit_move_insn (dest, temp));
|
||||
}
|
||||
else if (flag_pic == 2)
|
||||
|
@ -7259,19 +7445,19 @@ output_toc (file, x, labelno, mode)
|
|||
if (TARGET_64BIT)
|
||||
{
|
||||
if (TARGET_MINIMAL_TOC)
|
||||
fprintf (file, "\t.llong 0x%lx%08lx\n", k[0], k[1]);
|
||||
fputs (DOUBLE_INT_ASM_OP, file);
|
||||
else
|
||||
fprintf (file, "\t.tc FD_%lx_%lx[TC],0x%lx%08lx\n",
|
||||
k[0], k[1], k[0] & 0xffffffff, k[1] & 0xffffffff);
|
||||
fprintf (file, "\t.tc FD_%lx_%lx[TC],", k[0], k[1]);
|
||||
fprintf (file, "0x%lx%08lx\n", k[0], k[1]);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TARGET_MINIMAL_TOC)
|
||||
fprintf (file, "\t.long 0x%lx\n\t.long 0x%lx\n", k[0], k[1]);
|
||||
fputs ("\t.long ", file);
|
||||
else
|
||||
fprintf (file, "\t.tc FD_%lx_%lx[TC],0x%lx,0x%lx\n",
|
||||
k[0], k[1], k[0], k[1]);
|
||||
fprintf (file, "\t.tc FD_%lx_%lx[TC],", k[0], k[1]);
|
||||
fprintf (file, "0x%lx,0x%lx\n", k[0], k[1]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -7286,17 +7472,19 @@ output_toc (file, x, labelno, mode)
|
|||
if (TARGET_64BIT)
|
||||
{
|
||||
if (TARGET_MINIMAL_TOC)
|
||||
fprintf (file, "\t.llong 0x%lx00000000\n", l);
|
||||
fputs (DOUBLE_INT_ASM_OP, file);
|
||||
else
|
||||
fprintf (file, "\t.tc FS_%lx[TC],0x%lx00000000\n", l, l);
|
||||
fprintf (file, "\t.tc FS_%lx[TC],", l);
|
||||
fprintf (file, "0x%lx00000000\n", l);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TARGET_MINIMAL_TOC)
|
||||
fprintf (file, "\t.long 0x%lx\n", l);
|
||||
fputs ("\t.long ", file);
|
||||
else
|
||||
fprintf (file, "\t.tc FS_%lx[TC],0x%lx\n", l, l);
|
||||
fprintf (file, "\t.tc FS_%lx[TC],", l);
|
||||
fprintf (file, "0x%lx\n", l);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -7344,10 +7532,10 @@ output_toc (file, x, labelno, mode)
|
|||
if (TARGET_64BIT)
|
||||
{
|
||||
if (TARGET_MINIMAL_TOC)
|
||||
fprintf (file, "\t.llong 0x%lx%08lx\n", (long)high, (long)low);
|
||||
fputs (DOUBLE_INT_ASM_OP, file);
|
||||
else
|
||||
fprintf (file, "\t.tc ID_%lx_%lx[TC],0x%lx%08lx\n",
|
||||
(long)high, (long)low, (long)high, (long)low);
|
||||
fprintf (file, "\t.tc ID_%lx_%lx[TC],", (long)high, (long)low);
|
||||
fprintf (file, "0x%lx%08lx\n", (long) high, (long) low);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
@ -7355,20 +7543,19 @@ output_toc (file, x, labelno, mode)
|
|||
if (POINTER_SIZE < GET_MODE_BITSIZE (mode))
|
||||
{
|
||||
if (TARGET_MINIMAL_TOC)
|
||||
fprintf (file, "\t.long 0x%lx\n\t.long 0x%lx\n",
|
||||
(long)high, (long)low);
|
||||
fputs ("\t.long ", file);
|
||||
else
|
||||
fprintf (file, "\t.tc ID_%lx_%lx[TC],0x%lx,0x%lx\n",
|
||||
(long)high, (long)low, (long)high, (long)low);
|
||||
fprintf (file, "\t.tc ID_%lx_%lx[TC],",
|
||||
(long)high, (long)low);
|
||||
fprintf (file, "0x%lx,0x%lx\n", (long) high, (long) low);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TARGET_MINIMAL_TOC)
|
||||
fprintf (file, "\t.long 0x%lx\n",
|
||||
(long)low);
|
||||
fputs ("\t.long ", file);
|
||||
else
|
||||
fprintf (file, "\t.tc IS_%lx[TC],0x%lx\n",
|
||||
(long)low, (long)low);
|
||||
fprintf (file, "\t.tc IS_%lx[TC],", (long) low);
|
||||
fprintf (file, "0x%lx\n", (long) low);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -7376,6 +7563,9 @@ output_toc (file, x, labelno, mode)
|
|||
|
||||
if (GET_CODE (x) == CONST)
|
||||
{
|
||||
if (GET_CODE (XEXP (x, 0)) != PLUS)
|
||||
abort ();
|
||||
|
||||
base = XEXP (XEXP (x, 0), 0);
|
||||
offset = INTVAL (XEXP (XEXP (x, 0), 1));
|
||||
}
|
||||
|
@ -7391,7 +7581,7 @@ output_toc (file, x, labelno, mode)
|
|||
|
||||
STRIP_NAME_ENCODING (real_name, name);
|
||||
if (TARGET_MINIMAL_TOC)
|
||||
fputs (TARGET_32BIT ? "\t.long " : "\t.llong ", file);
|
||||
fputs (TARGET_32BIT ? "\t.long " : DOUBLE_INT_ASM_OP, file);
|
||||
else
|
||||
{
|
||||
fprintf (file, "\t.tc %s", real_name);
|
||||
|
|
|
@ -33,10 +33,14 @@ Boston, MA 02111-1307, USA. */
|
|||
#define OBJECT_MACHO 4
|
||||
|
||||
#define TARGET_ELF (TARGET_OBJECT_FORMAT == OBJECT_ELF)
|
||||
#define TARGET_AIX (TARGET_OBJECT_FORMAT == OBJECT_XCOFF)
|
||||
#define TARGET_XCOFF (TARGET_OBJECT_FORMAT == OBJECT_XCOFF)
|
||||
#define TARGET_MACOS (TARGET_OBJECT_FORMAT == OBJECT_PEF)
|
||||
#define TARGET_MACHO (TARGET_OBJECT_FORMAT == OBJECT_MACHO)
|
||||
|
||||
#ifndef TARGET_AIX
|
||||
#define TARGET_AIX 0
|
||||
#endif
|
||||
|
||||
/* Print subsidiary information on the compiler version in use. */
|
||||
#define TARGET_VERSION ;
|
||||
|
||||
|
@ -45,82 +49,6 @@ Boston, MA 02111-1307, USA. */
|
|||
#define TARGET_CPU_DEFAULT ((char *)0)
|
||||
#endif
|
||||
|
||||
/* Common CPP definitions used by CPP_SPEC among the various targets
|
||||
for handling -mcpu=xxx switches. */
|
||||
#define CPP_CPU_SPEC \
|
||||
"%{!mcpu*: \
|
||||
%{mpower: %{!mpower2: -D_ARCH_PWR}} \
|
||||
%{mpower2: -D_ARCH_PWR2} \
|
||||
%{mpowerpc*: -D_ARCH_PPC} \
|
||||
%{mno-power: %{!mpowerpc*: -D_ARCH_COM}} \
|
||||
%{!mno-power: %{!mpower2: %(cpp_default)}}} \
|
||||
%{mcpu=common: -D_ARCH_COM} \
|
||||
%{mcpu=power: -D_ARCH_PWR} \
|
||||
%{mcpu=power2: -D_ARCH_PWR2} \
|
||||
%{mcpu=powerpc: -D_ARCH_PPC} \
|
||||
%{mcpu=rios: -D_ARCH_PWR} \
|
||||
%{mcpu=rios1: -D_ARCH_PWR} \
|
||||
%{mcpu=rios2: -D_ARCH_PWR2} \
|
||||
%{mcpu=rsc: -D_ARCH_PWR} \
|
||||
%{mcpu=rsc1: -D_ARCH_PWR} \
|
||||
%{mcpu=401: -D_ARCH_PPC} \
|
||||
%{mcpu=403: -D_ARCH_PPC} \
|
||||
%{mcpu=505: -D_ARCH_PPC} \
|
||||
%{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \
|
||||
%{mcpu=602: -D_ARCH_PPC} \
|
||||
%{mcpu=603: -D_ARCH_PPC} \
|
||||
%{mcpu=603e: -D_ARCH_PPC} \
|
||||
%{mcpu=ec603e: -D_ARCH_PPC} \
|
||||
%{mcpu=604: -D_ARCH_PPC} \
|
||||
%{mcpu=604e: -D_ARCH_PPC} \
|
||||
%{mcpu=620: -D_ARCH_PPC} \
|
||||
%{mcpu=740: -D_ARCH_PPC} \
|
||||
%{mcpu=750: -D_ARCH_PPC} \
|
||||
%{mcpu=801: -D_ARCH_PPC} \
|
||||
%{mcpu=821: -D_ARCH_PPC} \
|
||||
%{mcpu=823: -D_ARCH_PPC} \
|
||||
%{mcpu=860: -D_ARCH_PPC}"
|
||||
|
||||
#define CPP_DEFAULT_SPEC "-D_ARCH_PWR"
|
||||
|
||||
/* Common ASM definitions used by ASM_SPEC among the various targets
|
||||
for handling -mcpu=xxx switches. */
|
||||
#define ASM_CPU_SPEC \
|
||||
"%{!mcpu*: \
|
||||
%{mpower: %{!mpower2: -mpwr}} \
|
||||
%{mpower2: -mpwrx} \
|
||||
%{mpowerpc*: -mppc} \
|
||||
%{mno-power: %{!mpowerpc*: -mcom}} \
|
||||
%{!mno-power: %{!mpower2: %(asm_default)}}} \
|
||||
%{mcpu=common: -mcom} \
|
||||
%{mcpu=power: -mpwr} \
|
||||
%{mcpu=power2: -mpwrx} \
|
||||
%{mcpu=powerpc: -mppc} \
|
||||
%{mcpu=rios: -mpwr} \
|
||||
%{mcpu=rios1: -mpwr} \
|
||||
%{mcpu=rios2: -mpwrx} \
|
||||
%{mcpu=rsc: -mpwr} \
|
||||
%{mcpu=rsc1: -mpwr} \
|
||||
%{mcpu=401: -mppc} \
|
||||
%{mcpu=403: -mppc} \
|
||||
%{mcpu=505: -mppc} \
|
||||
%{mcpu=601: -m601} \
|
||||
%{mcpu=602: -mppc} \
|
||||
%{mcpu=603: -mppc} \
|
||||
%{mcpu=603e: -mppc} \
|
||||
%{mcpu=ec603e: -mppc} \
|
||||
%{mcpu=604: -mppc} \
|
||||
%{mcpu=604e: -mppc} \
|
||||
%{mcpu=620: -mppc} \
|
||||
%{mcpu=740: -mppc} \
|
||||
%{mcpu=750: -mppc} \
|
||||
%{mcpu=801: -mppc} \
|
||||
%{mcpu=821: -mppc} \
|
||||
%{mcpu=823: -mppc} \
|
||||
%{mcpu=860: -mppc}"
|
||||
|
||||
#define ASM_DEFAULT_SPEC ""
|
||||
|
||||
/* This macro defines names of additional specifications to put in the specs
|
||||
that can be used in various specifications like CC1_SPEC. Its definition
|
||||
is an initializer with a subgrouping for each command option.
|
||||
|
@ -574,13 +502,6 @@ extern int rs6000_debug_arg; /* debug argument handling */
|
|||
/* Handle #pragma pack. */
|
||||
#define HANDLE_PRAGMA_PACK 1
|
||||
|
||||
/* AIX word-aligns FP doubles but doubleword-aligns 64-bit ints. */
|
||||
#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) \
|
||||
(TYPE_MODE (TREE_CODE (TREE_TYPE (FIELD)) == ARRAY_TYPE \
|
||||
? get_inner_array_type (FIELD) \
|
||||
: TREE_TYPE (FIELD)) == DFmode \
|
||||
? MIN ((COMPUTED), 32) : (COMPUTED))
|
||||
|
||||
/* Alignment of field after `int : 0' in a structure. */
|
||||
#define EMPTY_FIELD_BOUNDARY 32
|
||||
|
||||
|
@ -590,17 +511,6 @@ extern int rs6000_debug_arg; /* debug argument handling */
|
|||
/* A bitfield declared as `int' forces `int' alignment for the struct. */
|
||||
#define PCC_BITFIELD_TYPE_MATTERS 1
|
||||
|
||||
/* AIX increases natural record alignment to doubleword if the first
|
||||
field is an FP double while the FP fields remain word aligned. */
|
||||
#define ROUND_TYPE_ALIGN(STRUCT, COMPUTED, SPECIFIED) \
|
||||
((TREE_CODE (STRUCT) == RECORD_TYPE \
|
||||
|| TREE_CODE (STRUCT) == UNION_TYPE \
|
||||
|| TREE_CODE (STRUCT) == QUAL_UNION_TYPE) \
|
||||
&& TYPE_FIELDS (STRUCT) != 0 \
|
||||
&& DECL_MODE (TYPE_FIELDS (STRUCT)) == DFmode \
|
||||
? MAX (MAX ((COMPUTED), (SPECIFIED)), BIGGEST_ALIGNMENT) \
|
||||
: MAX ((COMPUTED), (SPECIFIED)))
|
||||
|
||||
/* Make strings word-aligned so strcpy from constants will be faster. */
|
||||
#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
|
||||
(TREE_CODE (EXP) == STRING_CST \
|
||||
|
@ -796,7 +706,7 @@ extern int rs6000_debug_arg; /* debug argument handling */
|
|||
registers is expensive. */
|
||||
|
||||
#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) \
|
||||
((CLASS1) == FLOAT_REGS && (CLASS2) == FLOAT_REGS ? 2 \
|
||||
((CLASS1) == FLOAT_REGS && (CLASS2) == FLOAT_REGS ? 2 \
|
||||
: (CLASS1) == FLOAT_REGS && (CLASS2) != FLOAT_REGS ? 10 \
|
||||
: (CLASS1) != FLOAT_REGS && (CLASS2) == FLOAT_REGS ? 10 \
|
||||
: (((CLASS1) == SPECIAL_REGS || (CLASS1) == MQ_REGS \
|
||||
|
@ -1050,7 +960,7 @@ enum reg_class
|
|||
`K' is a constant with only the low-order 16 bits non-zero
|
||||
`L' is a signed 16-bit constant shifted left 16 bits
|
||||
`M' is a constant that is greater than 31
|
||||
`N' is a constant that is an exact power of two
|
||||
`N' is a positive constant that is an exact power of two
|
||||
`O' is the constant zero
|
||||
`P' is a constant whose negation is a signed 16-bit constant */
|
||||
|
||||
|
@ -1061,7 +971,7 @@ enum reg_class
|
|||
: (C) == 'L' ? (((VALUE) & 0xffff) == 0 \
|
||||
&& ((VALUE) >> 31 == -1 || (VALUE) >> 31 == 0)) \
|
||||
: (C) == 'M' ? (VALUE) > 31 \
|
||||
: (C) == 'N' ? exact_log2 (VALUE) >= 0 \
|
||||
: (C) == 'N' ? (VALUE) > 0 && exact_log2 (VALUE) >= 0 \
|
||||
: (C) == 'O' ? (VALUE) == 0 \
|
||||
: (C) == 'P' ? (unsigned HOST_WIDE_INT) ((- (VALUE)) + 0x8000) < 0x10000 \
|
||||
: 0)
|
||||
|
@ -1384,8 +1294,8 @@ typedef struct rs6000_stack {
|
|||
/* 1 if N is a possible register number for function argument passing.
|
||||
On RS/6000, these are r3-r10 and fp1-fp13. */
|
||||
#define FUNCTION_ARG_REGNO_P(N) \
|
||||
(((unsigned)((N) - GP_ARG_MIN_REG) < (unsigned)(GP_ARG_NUM_REG)) \
|
||||
|| ((unsigned)((N) - FP_ARG_MIN_REG) < (unsigned)(FP_ARG_NUM_REG)))
|
||||
((((N) - GP_ARG_MIN_REG) < (GP_ARG_NUM_REG)) \
|
||||
|| (((N) - FP_ARG_MIN_REG) < (FP_ARG_NUM_REG)))
|
||||
|
||||
|
||||
/* A C structure for machine-specific, per-function data.
|
||||
|
@ -1551,6 +1461,16 @@ typedef struct rs6000_args
|
|||
argument is passed depends on whether or not it is a named argument. */
|
||||
#define STRICT_ARGUMENT_NAMING 1
|
||||
|
||||
/* This macro generates the assembly code for function entry.
|
||||
FILE is a stdio stream to output the code to.
|
||||
SIZE is an int: how many units of temporary storage to allocate.
|
||||
Refer to the array `regs_ever_live' to determine which registers
|
||||
to save; `regs_ever_live[I]' is nonzero if register number I
|
||||
is ever used in the function. This macro is responsible for
|
||||
knowing which registers should not be saved even if used. */
|
||||
|
||||
#define FUNCTION_PROLOGUE(FILE, SIZE) output_prolog (FILE, SIZE)
|
||||
|
||||
/* Output assembler code to FILE to increment profiler label # LABELNO
|
||||
for profiling a function entry. */
|
||||
|
||||
|
@ -1575,6 +1495,18 @@ typedef struct rs6000_args
|
|||
|| (current_function_calls_eh_return \
|
||||
&& TARGET_AIX \
|
||||
&& (REGNO) == TOC_REGISTER))
|
||||
|
||||
/* This macro generates the assembly code for function exit,
|
||||
on machines that need it. If FUNCTION_EPILOGUE is not defined
|
||||
then individual return instructions are generated for each
|
||||
return statement. Args are same as for FUNCTION_PROLOGUE.
|
||||
|
||||
The function epilogue should not depend on the current stack pointer!
|
||||
It should use the frame pointer only. This is mandatory because
|
||||
of alloca; we also take advantage of it to omit stack adjustments
|
||||
before returning. */
|
||||
|
||||
#define FUNCTION_EPILOGUE(FILE, SIZE) output_epilog (FILE, SIZE)
|
||||
|
||||
/* TRAMPOLINE_TEMPLATE deleted */
|
||||
|
||||
|
@ -2281,10 +2213,6 @@ extern int toc_initialized;
|
|||
} \
|
||||
}
|
||||
|
||||
/* This is how we tell the assembler that two symbols have the same value. */
|
||||
|
||||
#define SET_ASM_OP "\t.set\t"
|
||||
|
||||
/* This implementes the `alias' attribute. */
|
||||
|
||||
#define ASM_OUTPUT_DEF_FROM_DECLS(FILE,decl,target) \
|
||||
|
@ -2498,7 +2426,7 @@ do { \
|
|||
} \
|
||||
else \
|
||||
{ \
|
||||
fputs ("\t.llong ", FILE); \
|
||||
fprintf (FILE, "\t%s ", DOUBLE_INT_ASM_OP); \
|
||||
output_addr_const (FILE, (VALUE)); \
|
||||
putc ('\n', FILE); \
|
||||
} \
|
||||
|
@ -2527,7 +2455,7 @@ do { \
|
|||
fprintf (FILE, "\t.byte 0x%x\n", (VALUE))
|
||||
|
||||
/* This is used by the definition of ASM_OUTPUT_ADDR_ELT in defaults.h. */
|
||||
#define ASM_LONG (TARGET_32BIT ? ".long" : ".quad")
|
||||
#define ASM_LONG (TARGET_32BIT ? ".long" : DOUBLE_INT_ASM_OP)
|
||||
|
||||
/* This is how to output an element of a case-vector that is relative. */
|
||||
|
||||
|
@ -2550,19 +2478,6 @@ do { \
|
|||
if ((LOG) != 0) \
|
||||
fprintf (FILE, "\t.align %d\n", (LOG))
|
||||
|
||||
/* This says how to output an assembler line
|
||||
to define a local common symbol.
|
||||
Alignment cannot be specified, but we can try to maintain
|
||||
alignment after preceding TOC section if it was aligned
|
||||
for 64-bit mode. */
|
||||
|
||||
#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
|
||||
do { fputs (".lcomm ", (FILE)); \
|
||||
RS6000_OUTPUT_BASENAME ((FILE), (NAME)); \
|
||||
fprintf ((FILE), ",%d,%s\n", (TARGET_32BIT ? (SIZE) : (ROUNDED)), \
|
||||
xcoff_bss_section_name); \
|
||||
} while (0)
|
||||
|
||||
/* Store in OUTPUT a string (made with alloca) containing
|
||||
an assembler-name for a local static variable named NAME.
|
||||
LABELNO is an integer which is different for each call. */
|
||||
|
@ -2571,6 +2486,12 @@ do { \
|
|||
( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
|
||||
sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
|
||||
|
||||
/* Define the parentheses used to group arithmetic operations
|
||||
in assembler code. */
|
||||
|
||||
#define ASM_OPEN_PAREN "("
|
||||
#define ASM_CLOSE_PAREN ")"
|
||||
|
||||
/* Pick up the return address upon entry to a procedure. Used for
|
||||
dwarf2 unwind information. This also enables the table driven
|
||||
mechanism. */
|
||||
|
@ -2603,6 +2524,7 @@ do { \
|
|||
{"short_cint_operand", {CONST_INT}}, \
|
||||
{"u_short_cint_operand", {CONST_INT}}, \
|
||||
{"non_short_cint_operand", {CONST_INT}}, \
|
||||
{"exact_log2_cint_operand", {CONST_INT}}, \
|
||||
{"gpc_reg_operand", {SUBREG, REG}}, \
|
||||
{"cc_reg_operand", {SUBREG, REG}}, \
|
||||
{"cc_reg_not_cr0_operand", {SUBREG, REG}}, \
|
||||
|
@ -2611,6 +2533,8 @@ do { \
|
|||
{"reg_or_u_short_operand", {SUBREG, REG, CONST_INT}}, \
|
||||
{"reg_or_cint_operand", {SUBREG, REG, CONST_INT}}, \
|
||||
{"reg_or_arith_cint_operand", {SUBREG, REG, CONST_INT}}, \
|
||||
{"reg_or_add_cint64_operand", {SUBREG, REG, CONST_INT}}, \
|
||||
{"reg_or_sub_cint64_operand", {SUBREG, REG, CONST_INT}}, \
|
||||
{"reg_or_logical_cint_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
|
||||
{"got_operand", {SYMBOL_REF, CONST, LABEL_REF}}, \
|
||||
{"got_no_const_operand", {SYMBOL_REF, LABEL_REF}}, \
|
||||
|
|
|
@ -1422,19 +1422,14 @@
|
|||
rtx tmp = ((no_new_pseudos || rtx_equal_p (operands[0], operands[1]))
|
||||
? operands[0] : gen_reg_rtx (SImode));
|
||||
|
||||
HOST_WIDE_INT low = INTVAL (operands[2]) & 0xffff;
|
||||
HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff);
|
||||
|
||||
if (low & 0x8000)
|
||||
{
|
||||
high = trunc_int_for_mode (high + 0x10000, SImode);
|
||||
low = trunc_int_for_mode (low, HImode);
|
||||
}
|
||||
HOST_WIDE_INT val = INTVAL (operands[2]);
|
||||
HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000);
|
||||
HOST_WIDE_INT rest = trunc_int_for_mode (val - low, SImode);
|
||||
|
||||
/* The ordering here is important for the prolog expander.
|
||||
When space is allocated from the stack, adding 'low' first may
|
||||
produce a temporary deallocation (which would be bad). */
|
||||
emit_insn (gen_addsi3 (tmp, operands[1], GEN_INT (high)));
|
||||
emit_insn (gen_addsi3 (tmp, operands[1], GEN_INT (rest)));
|
||||
emit_insn (gen_addsi3 (operands[0], tmp, GEN_INT (low)));
|
||||
DONE;
|
||||
}
|
||||
|
@ -1536,16 +1531,11 @@
|
|||
(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 4)))]
|
||||
"
|
||||
{
|
||||
HOST_WIDE_INT low = INTVAL (operands[2]) & 0xffff;
|
||||
HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff);
|
||||
HOST_WIDE_INT val = INTVAL (operands[2]);
|
||||
HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000);
|
||||
HOST_WIDE_INT rest = trunc_int_for_mode (val - low, SImode);
|
||||
|
||||
if (low & 0x8000)
|
||||
{
|
||||
high = trunc_int_for_mode (high + 0x10000, SImode);
|
||||
low = trunc_int_for_mode (low, HImode);
|
||||
}
|
||||
|
||||
operands[3] = GEN_INT (high);
|
||||
operands[3] = GEN_INT (rest);
|
||||
operands[4] = GEN_INT (low);
|
||||
}")
|
||||
|
||||
|
@ -2277,6 +2267,7 @@
|
|||
"
|
||||
{
|
||||
if (GET_CODE (operands[2]) == CONST_INT
|
||||
&& INTVAL (operands[2]) > 0
|
||||
&& exact_log2 (INTVAL (operands[2])) >= 0)
|
||||
;
|
||||
else if (TARGET_POWERPC)
|
||||
|
@ -2328,12 +2319,9 @@
|
|||
rtx temp1;
|
||||
rtx temp2;
|
||||
|
||||
if (GET_CODE (operands[2]) != CONST_INT)
|
||||
FAIL;
|
||||
|
||||
i = exact_log2 (INTVAL (operands[2]));
|
||||
|
||||
if (i < 0)
|
||||
if (GET_CODE (operands[2]) != CONST_INT
|
||||
|| INTVAL (operands[2]) < 0
|
||||
|| (i = exact_log2 (INTVAL (operands[2]))) < 0)
|
||||
FAIL;
|
||||
|
||||
temp1 = gen_reg_rtx (SImode);
|
||||
|
@ -2348,18 +2336,18 @@
|
|||
(define_insn ""
|
||||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||||
(div:SI (match_operand:SI 1 "gpc_reg_operand" "r")
|
||||
(match_operand:SI 2 "const_int_operand" "N")))]
|
||||
"exact_log2 (INTVAL (operands[2])) >= 0"
|
||||
(match_operand:SI 2 "exact_log2_cint_operand" "N")))]
|
||||
""
|
||||
"{srai|srawi} %0,%1,%p2\;{aze|addze} %0,%0"
|
||||
[(set_attr "length" "8")])
|
||||
|
||||
(define_insn ""
|
||||
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
|
||||
(compare:CC (div:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
|
||||
(match_operand:SI 2 "const_int_operand" "N,N"))
|
||||
(match_operand:SI 2 "exact_log2_cint_operand" "N,N"))
|
||||
(const_int 0)))
|
||||
(clobber (match_scratch:SI 3 "=r,r"))]
|
||||
"exact_log2 (INTVAL (operands[2])) >= 0"
|
||||
""
|
||||
"@
|
||||
{srai|srawi} %3,%1,%p2\;{aze.|addze.} %3,%3
|
||||
#"
|
||||
|
@ -2369,10 +2357,10 @@
|
|||
(define_split
|
||||
[(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
|
||||
(compare:CC (div:SI (match_operand:SI 1 "gpc_reg_operand" "")
|
||||
(match_operand:SI 2 "const_int_operand" ""))
|
||||
(match_operand:SI 2 "exact_log2_cint_operand" ""))
|
||||
(const_int 0)))
|
||||
(clobber (match_scratch:SI 3 ""))]
|
||||
"exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed"
|
||||
"reload_completed"
|
||||
[(set (match_dup 3)
|
||||
(div:SI (match_dup 1) (match_dup 2)))
|
||||
(set (match_dup 0)
|
||||
|
@ -2383,11 +2371,11 @@
|
|||
(define_insn ""
|
||||
[(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
|
||||
(compare:CC (div:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
|
||||
(match_operand:SI 2 "const_int_operand" "N,N"))
|
||||
(match_operand:SI 2 "exact_log2_cint_operand" "N,N"))
|
||||
(const_int 0)))
|
||||
(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
|
||||
(div:SI (match_dup 1) (match_dup 2)))]
|
||||
"exact_log2 (INTVAL (operands[2])) >= 0"
|
||||
""
|
||||
"@
|
||||
{srai|srawi} %0,%1,%p2\;{aze.|addze.} %0,%0
|
||||
#"
|
||||
|
@ -2397,11 +2385,11 @@
|
|||
(define_split
|
||||
[(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
|
||||
(compare:CC (div:SI (match_operand:SI 1 "gpc_reg_operand" "")
|
||||
(match_operand:SI 2 "const_int_operand" ""))
|
||||
(match_operand:SI 2 "exact_log2_cint_operand" ""))
|
||||
(const_int 0)))
|
||||
(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||||
(div:SI (match_dup 1) (match_dup 2)))]
|
||||
"exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed"
|
||||
"reload_completed"
|
||||
[(set (match_dup 0)
|
||||
(div:SI (match_dup 1) (match_dup 2)))
|
||||
(set (match_dup 3)
|
||||
|
@ -5589,7 +5577,7 @@
|
|||
(define_expand "adddi3"
|
||||
[(set (match_operand:DI 0 "gpc_reg_operand" "")
|
||||
(plus:DI (match_operand:DI 1 "gpc_reg_operand" "")
|
||||
(match_operand:DI 2 "reg_or_arith_cint_operand" "")))]
|
||||
(match_operand:DI 2 "reg_or_add_cint64_operand" "")))]
|
||||
""
|
||||
"
|
||||
{
|
||||
|
@ -5605,16 +5593,17 @@
|
|||
rtx tmp = ((no_new_pseudos || rtx_equal_p (operands[0], operands[1]))
|
||||
? operands[0] : gen_reg_rtx (DImode));
|
||||
|
||||
HOST_WIDE_INT low = INTVAL (operands[2]) & 0xffff;
|
||||
HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff);
|
||||
HOST_WIDE_INT val = INTVAL (operands[2]);
|
||||
HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000);
|
||||
HOST_WIDE_INT rest = trunc_int_for_mode (val - low, DImode);
|
||||
|
||||
if (low & 0x8000)
|
||||
{
|
||||
high = trunc_int_for_mode (high + 0x10000, SImode);
|
||||
low = trunc_int_for_mode (low, HImode);
|
||||
}
|
||||
if (!CONST_OK_FOR_LETTER_P (rest, 'L'))
|
||||
FAIL;
|
||||
|
||||
emit_insn (gen_adddi3 (tmp, operands[1], GEN_INT (high)));
|
||||
/* The ordering here is important for the prolog expander.
|
||||
When space is allocated from the stack, adding 'low' first may
|
||||
produce a temporary deallocation (which would be bad). */
|
||||
emit_insn (gen_adddi3 (tmp, operands[1], GEN_INT (rest)));
|
||||
emit_insn (gen_adddi3 (operands[0], tmp, GEN_INT (low)));
|
||||
DONE;
|
||||
}
|
||||
|
@ -5707,17 +5696,22 @@
|
|||
(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))]
|
||||
"
|
||||
{
|
||||
HOST_WIDE_INT low = INTVAL (operands[2]) & 0xffff;
|
||||
HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff);
|
||||
HOST_WIDE_INT val = INTVAL (operands[2]);
|
||||
HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000);
|
||||
HOST_WIDE_INT rest = trunc_int_for_mode (val - low, DImode);
|
||||
|
||||
if (low & 0x8000)
|
||||
{
|
||||
high = trunc_int_for_mode (high + 0x10000, SImode);
|
||||
low = trunc_int_for_mode (low, HImode);
|
||||
}
|
||||
|
||||
operands[3] = GEN_INT (high);
|
||||
operands[4] = GEN_INT (low);
|
||||
if (CONST_OK_FOR_LETTER_P (rest, 'L'))
|
||||
operands[3] = GEN_INT (rest);
|
||||
else if (! no_new_pseudos)
|
||||
{
|
||||
operands[3] = gen_reg_rtx (DImode);
|
||||
emit_move_insn (operands[3], operands[2]);
|
||||
emit_insn (gen_adddi3 (operands[0], operands[1], operands[3]));
|
||||
DONE;
|
||||
}
|
||||
else
|
||||
FAIL;
|
||||
}")
|
||||
|
||||
(define_insn "one_cmpldi2"
|
||||
|
@ -5846,7 +5840,7 @@
|
|||
(define_expand "subdi3"
|
||||
[(set (match_operand:DI 0 "gpc_reg_operand" "")
|
||||
(minus:DI (match_operand:DI 1 "reg_or_short_operand" "")
|
||||
(match_operand:DI 2 "reg_or_arith_cint_operand" "")))]
|
||||
(match_operand:DI 2 "reg_or_sub_cint64_operand" "")))]
|
||||
""
|
||||
"
|
||||
{
|
||||
|
@ -6005,6 +5999,7 @@
|
|||
"
|
||||
{
|
||||
if (GET_CODE (operands[2]) == CONST_INT
|
||||
&& INTVAL (operands[2]) > 0
|
||||
&& exact_log2 (INTVAL (operands[2])) >= 0)
|
||||
;
|
||||
else
|
||||
|
@ -6018,11 +6013,13 @@
|
|||
"TARGET_POWERPC64"
|
||||
"
|
||||
{
|
||||
int i = exact_log2 (INTVAL (operands[2]));
|
||||
int i;
|
||||
rtx temp1;
|
||||
rtx temp2;
|
||||
|
||||
if (GET_CODE (operands[2]) != CONST_INT || i < 0)
|
||||
if (GET_CODE (operands[2]) != CONST_INT
|
||||
|| INTVAL (operands[2]) <= 0
|
||||
|| (i = exact_log2 (INTVAL (operands[2]))) < 0)
|
||||
FAIL;
|
||||
|
||||
temp1 = gen_reg_rtx (DImode);
|
||||
|
@ -6037,18 +6034,18 @@
|
|||
(define_insn ""
|
||||
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
|
||||
(div:DI (match_operand:DI 1 "gpc_reg_operand" "r")
|
||||
(match_operand:DI 2 "const_int_operand" "N")))]
|
||||
"TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0"
|
||||
(match_operand:DI 2 "exact_log2_cint_operand" "N")))]
|
||||
"TARGET_POWERPC64"
|
||||
"sradi %0,%1,%p2\;addze %0,%0"
|
||||
[(set_attr "length" "8")])
|
||||
|
||||
(define_insn ""
|
||||
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
|
||||
(compare:CC (div:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
|
||||
(match_operand:DI 2 "const_int_operand" "N,N"))
|
||||
(match_operand:DI 2 "exact_log2_cint_operand" "N,N"))
|
||||
(const_int 0)))
|
||||
(clobber (match_scratch:DI 3 "=r,r"))]
|
||||
"TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0"
|
||||
"TARGET_POWERPC64"
|
||||
"@
|
||||
sradi %3,%1,%p2\;addze. %3,%3
|
||||
#"
|
||||
|
@ -6058,10 +6055,10 @@
|
|||
(define_split
|
||||
[(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
|
||||
(compare:CC (div:DI (match_operand:DI 1 "gpc_reg_operand" "")
|
||||
(match_operand:DI 2 "const_int_operand" ""))
|
||||
(match_operand:DI 2 "exact_log2_cint_operand" ""))
|
||||
(const_int 0)))
|
||||
(clobber (match_scratch:DI 3 ""))]
|
||||
"TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed"
|
||||
"TARGET_POWERPC64 && reload_completed"
|
||||
[(set (match_dup 3)
|
||||
(div:DI (match_dup 1) (match_dup 2)))
|
||||
(set (match_dup 0)
|
||||
|
@ -6072,11 +6069,11 @@
|
|||
(define_insn ""
|
||||
[(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
|
||||
(compare:CC (div:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
|
||||
(match_operand:DI 2 "const_int_operand" "N,N"))
|
||||
(match_operand:DI 2 "exact_log2_cint_operand" "N,N"))
|
||||
(const_int 0)))
|
||||
(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
|
||||
(div:DI (match_dup 1) (match_dup 2)))]
|
||||
"TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0"
|
||||
"TARGET_POWERPC64"
|
||||
"@
|
||||
sradi %0,%1,%p2\;addze. %0,%0
|
||||
#"
|
||||
|
@ -6086,11 +6083,11 @@
|
|||
(define_split
|
||||
[(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
|
||||
(compare:CC (div:DI (match_operand:DI 1 "gpc_reg_operand" "")
|
||||
(match_operand:DI 2 "const_int_operand" ""))
|
||||
(match_operand:DI 2 "exact_log2_cint_operand" ""))
|
||||
(const_int 0)))
|
||||
(set (match_operand:DI 0 "gpc_reg_operand" "")
|
||||
(div:DI (match_dup 1) (match_dup 2)))]
|
||||
"TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed"
|
||||
"TARGET_POWERPC64 && reload_completed"
|
||||
[(set (match_dup 0)
|
||||
(div:DI (match_dup 1) (match_dup 2)))
|
||||
(set (match_dup 3)
|
||||
|
@ -7877,135 +7874,6 @@
|
|||
? \"li %0,%1\" : \"lis %0,%v1\";
|
||||
}")
|
||||
|
||||
;; sign-extended 32-bit value
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "gpc_reg_operand" "")
|
||||
(match_operand:DI 1 "const_int_operand" ""))]
|
||||
"HOST_BITS_PER_WIDE_INT == 32 && TARGET_POWERPC64
|
||||
&& num_insns_constant (operands[1], DImode) > 1"
|
||||
[(set (match_dup 0)
|
||||
(match_dup 2))
|
||||
(set (match_dup 0)
|
||||
(ior:DI (match_dup 0)
|
||||
(match_dup 3)))]
|
||||
"
|
||||
{
|
||||
operands[2] = GEN_INT (INTVAL (operands[1]) & (~ (HOST_WIDE_INT) 0xffff));
|
||||
operands[3] = GEN_INT (INTVAL (operands[1]) & 0xffff);
|
||||
}")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "gpc_reg_operand" "")
|
||||
(match_operand:DI 1 "const_double_operand" ""))]
|
||||
"HOST_BITS_PER_WIDE_INT == 32 && TARGET_POWERPC64
|
||||
&& GET_CODE (operands[1]) == CONST_DOUBLE
|
||||
&& ((CONST_DOUBLE_HIGH (operands[1]) == 0
|
||||
&& (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) == 0)
|
||||
|| (CONST_DOUBLE_HIGH (operands[1]) == -1
|
||||
&& (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) != 0))"
|
||||
[(set (match_dup 0)
|
||||
(match_dup 2))
|
||||
(set (match_dup 0)
|
||||
(ior:DI (match_dup 0)
|
||||
(match_dup 3)))]
|
||||
"
|
||||
{
|
||||
operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[1]) & (~ (HOST_WIDE_INT) 0xffff));
|
||||
operands[3] = GEN_INT (CONST_DOUBLE_LOW (operands[1]) & 0xffff);
|
||||
}")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "gpc_reg_operand" "")
|
||||
(match_operand:DI 1 "const_int_operand" ""))]
|
||||
"HOST_BITS_PER_WIDE_INT != 32 && TARGET_POWERPC64
|
||||
&& GET_CODE (operands[1]) == CONST_INT
|
||||
&& (((INTVAL (operands[1]) >> 32) == 0
|
||||
&& (INTVAL (operands[1]) & 0x80000000) == 0)
|
||||
|| ((INTVAL (operands[1]) >> 32) == -1
|
||||
&& (INTVAL (operands[1]) & 0x80000000) != 0))
|
||||
&& num_insns_constant (operands[1], DImode) > 1"
|
||||
[(set (match_dup 0)
|
||||
(match_dup 2))
|
||||
(set (match_dup 0)
|
||||
(ior:DI (match_dup 0)
|
||||
(match_dup 3)))]
|
||||
"
|
||||
{
|
||||
operands[2] = GEN_INT (INTVAL (operands[1]) & (~ (HOST_WIDE_INT) 0xffff));
|
||||
operands[3] = GEN_INT (INTVAL (operands[1]) & 0xffff);
|
||||
}")
|
||||
|
||||
;; zero-extended 32-bit value
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "gpc_reg_operand" "")
|
||||
(match_operand:DI 1 "const_double_operand" ""))]
|
||||
"HOST_BITS_PER_WIDE_INT == 32 && TARGET_POWERPC64
|
||||
&& GET_CODE (operands[1]) == CONST_DOUBLE
|
||||
&& CONST_DOUBLE_HIGH (operands[1]) == 0
|
||||
&& (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) != 0"
|
||||
[(set (match_dup 0)
|
||||
(match_dup 2))
|
||||
(set (match_dup 0)
|
||||
(zero_extend:DI (match_dup 3)))]
|
||||
"
|
||||
{
|
||||
operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
|
||||
operands[3] = gen_lowpart_common (SImode, operands[0]);
|
||||
}")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "gpc_reg_operand" "")
|
||||
(match_operand:DI 1 "const_int_operand" ""))]
|
||||
"HOST_BITS_PER_WIDE_INT != 32 && TARGET_POWERPC64
|
||||
&& GET_CODE (operands[1]) == CONST_INT
|
||||
&& INTVAL (operands[1]) >> 32 == 0
|
||||
&& (INTVAL (operands[1]) & 0x80000000) != 0
|
||||
&& num_insns_constant (operands[1], DImode) > 1"
|
||||
[(set (match_dup 0)
|
||||
(match_dup 2))
|
||||
(set (match_dup 0)
|
||||
(zero_extend:DI (match_dup 3)))]
|
||||
"
|
||||
{
|
||||
#if HOST_BITS_PER_WIDE_INT != 32
|
||||
operands[2] = GEN_INT ((INTVAL (operands[1]) ^ 0x80000000) - 0x80000000);
|
||||
#endif
|
||||
operands[3] = gen_lowpart_common (SImode, operands[0]);
|
||||
}")
|
||||
|
||||
;; 32-bit value in upper half of doubleword
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "gpc_reg_operand" "")
|
||||
(match_operand:DI 1 "const_double_operand" ""))]
|
||||
"HOST_BITS_PER_WIDE_INT == 32 && TARGET_POWERPC64
|
||||
&& GET_CODE (operands[1]) == CONST_DOUBLE
|
||||
&& CONST_DOUBLE_LOW (operands[1]) == 0"
|
||||
[(set (match_dup 0)
|
||||
(match_dup 2))
|
||||
(set (match_dup 0)
|
||||
(ashift:DI (match_dup 0)
|
||||
(const_int 32)))]
|
||||
"
|
||||
{ operands[2] = GEN_INT (CONST_DOUBLE_HIGH (operands[1])); }")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "gpc_reg_operand" "")
|
||||
(match_operand:DI 1 "const_int_operand" ""))]
|
||||
"HOST_BITS_PER_WIDE_INT != 32 && TARGET_POWERPC64
|
||||
&& GET_CODE (operands[1]) == CONST_INT
|
||||
&& (INTVAL (operands[1]) & 0xffffffff) == 0"
|
||||
[(set (match_dup 0)
|
||||
(match_dup 2))
|
||||
(set (match_dup 0)
|
||||
(ashift:DI (match_dup 0)
|
||||
(const_int 32)))]
|
||||
"
|
||||
{
|
||||
#if HOST_BITS_PER_WIDE_INT != 32
|
||||
operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
|
||||
#endif
|
||||
}")
|
||||
|
||||
;; Generate all one-bits and clear left or right.
|
||||
;; Use (and:DI (rotate:DI ...)) to avoid anddi3 unnecessary clobber.
|
||||
(define_split
|
||||
|
@ -8025,55 +7893,35 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
|
|||
;; easy_fp_constant predicate.
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "gpc_reg_operand" "")
|
||||
(match_operand:DI 1 "const_double_operand" ""))]
|
||||
"HOST_BITS_PER_WIDE_INT == 32 && TARGET_POWERPC64
|
||||
&& num_insns_constant (operands[1], DImode) > 1"
|
||||
[(set (match_dup 0)
|
||||
(match_dup 2))
|
||||
(set (match_dup 0)
|
||||
(ashift:DI (match_dup 0)
|
||||
(const_int 32)))
|
||||
(set (match_dup 0)
|
||||
(ior:DI (match_dup 0)
|
||||
(match_dup 3)))]
|
||||
(match_operand:DI 1 "const_int_operand" ""))]
|
||||
"TARGET_POWERPC64 && num_insns_constant (operands[1], DImode) > 1"
|
||||
[(set (match_dup 0) (match_dup 2))
|
||||
(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))]
|
||||
"
|
||||
{
|
||||
if (GET_CODE (operands[1]) == CONST_DOUBLE)
|
||||
{
|
||||
operands[2] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
|
||||
operands[3] = immed_double_const (CONST_DOUBLE_LOW (operands[1]),
|
||||
0, DImode);
|
||||
}
|
||||
{ rtx tem = rs6000_emit_set_const (operands[0], DImode, operands[1], 5);
|
||||
|
||||
if (tem == operands[0])
|
||||
DONE;
|
||||
else
|
||||
{
|
||||
HOST_WIDE_INT value = INTVAL (operands[1]);
|
||||
operands[2] = (value & 0x80000000) ? constm1_rtx : const0_rtx;
|
||||
operands[3] = immed_double_const (value, 0, DImode);
|
||||
}
|
||||
FAIL;
|
||||
}")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "gpc_reg_operand" "")
|
||||
(match_operand:DI 1 "const_int_operand" ""))]
|
||||
"HOST_BITS_PER_WIDE_INT != 32 && TARGET_POWERPC64
|
||||
&& num_insns_constant (operands[1], DImode) > 1"
|
||||
[(set (match_dup 0)
|
||||
(match_dup 2))
|
||||
(set (match_dup 0)
|
||||
(ashift:DI (match_dup 0)
|
||||
(const_int 32)))
|
||||
(set (match_dup 0)
|
||||
(ior:DI (match_dup 0)
|
||||
(match_dup 3)))]
|
||||
(match_operand:DI 1 "const_double_operand" ""))]
|
||||
"TARGET_POWERPC64 && num_insns_constant (operands[1], DImode) > 1"
|
||||
[(set (match_dup 0) (match_dup 2))
|
||||
(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))]
|
||||
"
|
||||
{
|
||||
#if HOST_BITS_PER_WIDE_INT != 32
|
||||
HOST_WIDE_INT value = INTVAL (operands[1]);
|
||||
operands[2] = GEN_INT (value >> 32);
|
||||
operands[3] = GEN_INT ((value & 0x7fffffff) - (value & 0x80000000));
|
||||
#endif
|
||||
{ rtx tem = rs6000_emit_set_const (operands[0], DImode, operands[1], 5);
|
||||
|
||||
if (tem == operands[0])
|
||||
DONE;
|
||||
else
|
||||
FAIL;
|
||||
}")
|
||||
|
||||
;; Split a load of a large constant into the appropriate five-instruction
|
||||
(define_insn "*movdi_internal2"
|
||||
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
|
||||
(compare:CC (match_operand:DI 1 "gpc_reg_operand" "r,r")
|
||||
|
@ -9068,7 +8916,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
|
|||
(define_insn "load_toc_aix_si"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||
(unspec:SI [(const_int 0)] 7))]
|
||||
"! TARGET_ELF && TARGET_32BIT"
|
||||
"DEFAULT_ABI == ABI_AIX && TARGET_32BIT"
|
||||
"*
|
||||
{
|
||||
char buf[30];
|
||||
|
@ -9082,11 +8930,13 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
|
|||
(define_insn "load_toc_aix_di"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(unspec:DI [(const_int 0)] 7))]
|
||||
"! TARGET_ELF && TARGET_64BIT"
|
||||
"DEFAULT_ABI == ABI_AIX && TARGET_64BIT"
|
||||
"*
|
||||
{
|
||||
char buf[30];
|
||||
ASM_GENERATE_INTERNAL_LABEL (buf, \"LCTOC\", 1);
|
||||
if (TARGET_ELF)
|
||||
strcat (buf, \"@toc\");
|
||||
operands[1] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
|
||||
operands[2] = gen_rtx_REG (Pmode, 2);
|
||||
return \"ld %0,%1(%2)\";
|
||||
|
@ -9102,15 +8952,6 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
|
|||
[(set_attr "type" "branch")
|
||||
(set_attr "length" "4")])
|
||||
|
||||
(define_insn "load_toc_v4_pic_di"
|
||||
[(set (match_operand:DI 0 "register_operand" "=l")
|
||||
(unspec:DI [(const_int 0)] 7))]
|
||||
"(DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS) && flag_pic == 1
|
||||
&& TARGET_64BIT"
|
||||
"bl _GLOBAL_OFFSET_TABLE_@local-4"
|
||||
[(set_attr "type" "branch")
|
||||
(set_attr "length" "4")])
|
||||
|
||||
(define_insn "load_toc_v4_PIC_1"
|
||||
[(set (match_operand:SI 0 "register_operand" "=l")
|
||||
(match_operand:SI 1 "immediate_operand" "s"))
|
||||
|
|
|
@ -37,6 +37,79 @@ Boston, MA 02111-1307, USA. */
|
|||
/* Override rs6000.h definition. */
|
||||
#undef CPP_DEFAULT_SPEC
|
||||
#define CPP_DEFAULT_SPEC "-D_ARCH_PPC"
|
||||
/* Common CPP definitions used by CPP_SPEC among the various targets
|
||||
for handling -mcpu=xxx switches. */
|
||||
#define CPP_CPU_SPEC \
|
||||
"%{!mcpu*: \
|
||||
%{mpower: %{!mpower2: -D_ARCH_PWR}} \
|
||||
%{mpower2: -D_ARCH_PWR2} \
|
||||
%{mpowerpc*: -D_ARCH_PPC} \
|
||||
%{mno-power: %{!mpowerpc*: -D_ARCH_COM}} \
|
||||
%{!mno-power: %{!mpower2: %(cpp_default)}}} \
|
||||
%{mcpu=common: -D_ARCH_COM} \
|
||||
%{mcpu=power: -D_ARCH_PWR} \
|
||||
%{mcpu=power2: -D_ARCH_PWR2} \
|
||||
%{mcpu=powerpc: -D_ARCH_PPC} \
|
||||
%{mcpu=rios: -D_ARCH_PWR} \
|
||||
%{mcpu=rios1: -D_ARCH_PWR} \
|
||||
%{mcpu=rios2: -D_ARCH_PWR2} \
|
||||
%{mcpu=rsc: -D_ARCH_PWR} \
|
||||
%{mcpu=rsc1: -D_ARCH_PWR} \
|
||||
%{mcpu=401: -D_ARCH_PPC} \
|
||||
%{mcpu=403: -D_ARCH_PPC} \
|
||||
%{mcpu=505: -D_ARCH_PPC} \
|
||||
%{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \
|
||||
%{mcpu=602: -D_ARCH_PPC} \
|
||||
%{mcpu=603: -D_ARCH_PPC} \
|
||||
%{mcpu=603e: -D_ARCH_PPC} \
|
||||
%{mcpu=ec603e: -D_ARCH_PPC} \
|
||||
%{mcpu=604: -D_ARCH_PPC} \
|
||||
%{mcpu=604e: -D_ARCH_PPC} \
|
||||
%{mcpu=620: -D_ARCH_PPC} \
|
||||
%{mcpu=740: -D_ARCH_PPC} \
|
||||
%{mcpu=750: -D_ARCH_PPC} \
|
||||
%{mcpu=801: -D_ARCH_PPC} \
|
||||
%{mcpu=821: -D_ARCH_PPC} \
|
||||
%{mcpu=823: -D_ARCH_PPC} \
|
||||
%{mcpu=860: -D_ARCH_PPC}"
|
||||
|
||||
#define CPP_DEFAULT_SPEC "-D_ARCH_PPC"
|
||||
|
||||
/* Common ASM definitions used by ASM_SPEC among the various targets
|
||||
for handling -mcpu=xxx switches. */
|
||||
#define ASM_CPU_SPEC \
|
||||
"%{!mcpu*: \
|
||||
%{mpower: %{!mpower2: -mpwr}} \
|
||||
%{mpower2: -mpwrx} \
|
||||
%{mpowerpc*: -mppc} \
|
||||
%{mno-power: %{!mpowerpc*: -mcom}} \
|
||||
%{!mno-power: %{!mpower2: %(asm_default)}}} \
|
||||
%{mcpu=common: -mcom} \
|
||||
%{mcpu=power: -mpwr} \
|
||||
%{mcpu=power2: -mpwrx} \
|
||||
%{mcpu=powerpc: -mppc} \
|
||||
%{mcpu=rios: -mpwr} \
|
||||
%{mcpu=rios1: -mpwr} \
|
||||
%{mcpu=rios2: -mpwrx} \
|
||||
%{mcpu=rsc: -mpwr} \
|
||||
%{mcpu=rsc1: -mpwr} \
|
||||
%{mcpu=401: -mppc} \
|
||||
%{mcpu=403: -mppc} \
|
||||
%{mcpu=505: -mppc} \
|
||||
%{mcpu=601: -m601} \
|
||||
%{mcpu=602: -mppc} \
|
||||
%{mcpu=603: -mppc} \
|
||||
%{mcpu=603e: -mppc} \
|
||||
%{mcpu=ec603e: -mppc} \
|
||||
%{mcpu=604: -mppc} \
|
||||
%{mcpu=604e: -mppc} \
|
||||
%{mcpu=620: -mppc} \
|
||||
%{mcpu=740: -mppc} \
|
||||
%{mcpu=750: -mppc} \
|
||||
%{mcpu=801: -mppc} \
|
||||
%{mcpu=821: -mppc} \
|
||||
%{mcpu=823: -mppc} \
|
||||
%{mcpu=860: -mppc}"
|
||||
|
||||
/* Small data support types. */
|
||||
enum rs6000_sdata_type {
|
||||
|
@ -694,10 +767,9 @@ extern int rs6000_pic_labelno;
|
|||
the return address. Hence returning from FUNCTION will return to whoever
|
||||
called the current thunk'.
|
||||
|
||||
The effect must be as if FUNCTION had been called directly with
|
||||
the adjusted first argument. This macro is responsible for
|
||||
emitting all of the code for a thunk function;
|
||||
output_function_prologue() and output_function_epilogue() are not
|
||||
The effect must be as if FUNCTION had been called directly with the adjusted
|
||||
first argument. This macro is responsible for emitting all of the code for
|
||||
a thunk function; FUNCTION_PROLOGUE' and FUNCTION_EPILOGUE' are not
|
||||
invoked.
|
||||
|
||||
The THUNK_FNDECL is redundant. (DELTA and FUNCTION have already been
|
||||
|
@ -1191,11 +1263,11 @@ do { \
|
|||
|
||||
#define CPP_SYSV_DEFAULT_SPEC "-D_CALL_SYSV"
|
||||
|
||||
#define CPP_ENDIAN_BIG_SPEC "-D_BIG_ENDIAN -D__BIG_ENDIAN__ -Aendian=big"
|
||||
#define CPP_ENDIAN_BIG_SPEC "-D_BIG_ENDIAN -D__BIG_ENDIAN__ -Amachine=bigendian"
|
||||
|
||||
#define CPP_ENDIAN_LITTLE_SPEC "-D_LITTLE_ENDIAN -D__LITTLE_ENDIAN__ -Aendian=little"
|
||||
#define CPP_ENDIAN_LITTLE_SPEC "-D_LITTLE_ENDIAN -D__LITTLE_ENDIAN__ -Amachine=littleendian"
|
||||
|
||||
#define CPP_ENDIAN_SOLARIS_SPEC "-D__LITTLE_ENDIAN__ -Aendian=little"
|
||||
#define CPP_ENDIAN_SOLARIS_SPEC "-D__LITTLE_ENDIAN__ -Amachine=littleendian"
|
||||
|
||||
/* For solaris, don't define _LITTLE_ENDIAN, it conflicts with a header file. */
|
||||
#define CPP_ENDIAN_SPEC \
|
||||
|
@ -1606,3 +1678,4 @@ do { \
|
|||
: DW_EH_PE_absptr)
|
||||
|
||||
#define EXCEPTION_SECTION readonly_data_section
|
||||
#define DOUBLE_INT_ASM_OP ".quad"
|
||||
|
|
502
gcc/config/rs6000/xcoff.h
Normal file
502
gcc/config/rs6000/xcoff.h
Normal file
|
@ -0,0 +1,502 @@
|
|||
/* Definitions of target machine for GNU compiler,
|
||||
for some generic XCOFF file format
|
||||
Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
|
||||
#define TARGET_OBJECT_FORMAT OBJECT_XCOFF
|
||||
|
||||
/* The AIX linker will discard static constructors in object files before
|
||||
collect has a chance to see them, so scan the object files directly. */
|
||||
#define COLLECT_EXPORT_LIST
|
||||
|
||||
/* The RS/6000 uses the XCOFF format. */
|
||||
#define XCOFF_DEBUGGING_INFO
|
||||
|
||||
/* Define if the object format being used is COFF or a superset. */
|
||||
#define OBJECT_FORMAT_COFF
|
||||
|
||||
/* Define the magic numbers that we recognize as COFF.
|
||||
|
||||
AIX 4.3 adds U803XTOCMAGIC (0757) for 64-bit objects and AIX V5 adds
|
||||
U64_TOCMAGIC (0767), but collect2.c does not include files in the
|
||||
correct order to conditionally define the symbolic name in this macro.
|
||||
|
||||
The AIX linker accepts import/export files as object files,
|
||||
so accept "#!" (0x2321) magic number. */
|
||||
#define MY_ISCOFF(magic) \
|
||||
((magic) == U802WRMAGIC || (magic) == U802ROMAGIC \
|
||||
|| (magic) == U802TOCMAGIC || (magic) == 0757 || (magic) == 0767 \
|
||||
|| (magic) == 0x2321)
|
||||
|
||||
/* We don't have GAS for the RS/6000 yet, so don't write out special
|
||||
.stabs in cc1plus. */
|
||||
|
||||
#define FASCIST_ASSEMBLER
|
||||
|
||||
/* We define this to prevent the name mangler from putting dollar signs into
|
||||
function names. */
|
||||
|
||||
#define NO_DOLLAR_IN_LABEL
|
||||
|
||||
/* We define this to 0 so that gcc will never accept a dollar sign in a
|
||||
variable name. This is needed because the AIX assembler will not accept
|
||||
dollar signs. */
|
||||
|
||||
#define DOLLARS_IN_IDENTIFIERS 0
|
||||
|
||||
/* Define the extra sections we need. We define three: one is the read-only
|
||||
data section which is used for constants. This is a csect whose name is
|
||||
derived from the name of the input file. The second is for initialized
|
||||
global variables. This is a csect whose name is that of the variable.
|
||||
The third is the TOC. */
|
||||
|
||||
#define EXTRA_SECTIONS \
|
||||
read_only_data, private_data, read_only_private_data, toc, bss
|
||||
|
||||
/* Define the routines to implement these extra sections.
|
||||
BIGGEST_ALIGNMENT is 64, so align the sections that much. */
|
||||
|
||||
#define EXTRA_SECTION_FUNCTIONS \
|
||||
\
|
||||
void \
|
||||
read_only_data_section () \
|
||||
{ \
|
||||
if (in_section != read_only_data) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "\t.csect %s[RO],3\n", \
|
||||
xcoff_read_only_section_name); \
|
||||
in_section = read_only_data; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
private_data_section () \
|
||||
{ \
|
||||
if (in_section != private_data) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "\t.csect %s[RW],3\n", \
|
||||
xcoff_private_data_section_name); \
|
||||
in_section = private_data; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
read_only_private_data_section () \
|
||||
{ \
|
||||
if (in_section != read_only_private_data) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "\t.csect %s[RO],3\n", \
|
||||
xcoff_private_data_section_name); \
|
||||
in_section = read_only_private_data; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
toc_section () \
|
||||
{ \
|
||||
if (TARGET_MINIMAL_TOC) \
|
||||
{ \
|
||||
/* toc_section is always called at least once from ASM_FILE_START, \
|
||||
so this is guaranteed to always be defined once and only once \
|
||||
in each file. */ \
|
||||
if (! toc_initialized) \
|
||||
{ \
|
||||
fputs ("\t.toc\nLCTOC..1:\n", asm_out_file); \
|
||||
fputs ("\t.tc toc_table[TC],toc_table[RW]\n", asm_out_file); \
|
||||
toc_initialized = 1; \
|
||||
} \
|
||||
\
|
||||
if (in_section != toc) \
|
||||
fprintf (asm_out_file, "\t.csect toc_table[RW]%s\n", \
|
||||
(TARGET_32BIT ? "" : ",3")); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (in_section != toc) \
|
||||
fputs ("\t.toc\n", asm_out_file); \
|
||||
} \
|
||||
in_section = toc; \
|
||||
}
|
||||
|
||||
/* Define the name of our readonly data section. */
|
||||
|
||||
#define READONLY_DATA_SECTION read_only_data_section
|
||||
|
||||
/* Select the section for an initialized data object.
|
||||
|
||||
On the RS/6000, we have a special section for all variables except those
|
||||
that are static. */
|
||||
|
||||
#define SELECT_SECTION(EXP,RELOC) \
|
||||
{ \
|
||||
if ((TREE_CODE (EXP) == STRING_CST \
|
||||
&& ! flag_writable_strings) \
|
||||
|| (TREE_CODE_CLASS (TREE_CODE (EXP)) == 'd' \
|
||||
&& TREE_READONLY (EXP) && ! TREE_THIS_VOLATILE (EXP) \
|
||||
&& DECL_INITIAL (EXP) \
|
||||
&& (DECL_INITIAL (EXP) == error_mark_node \
|
||||
|| TREE_CONSTANT (DECL_INITIAL (EXP))) \
|
||||
&& ! (RELOC))) \
|
||||
{ \
|
||||
if (TREE_PUBLIC (EXP)) \
|
||||
read_only_data_section (); \
|
||||
else \
|
||||
read_only_private_data_section (); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (TREE_PUBLIC (EXP)) \
|
||||
data_section (); \
|
||||
else \
|
||||
private_data_section (); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Return non-zero if this entry is to be written into the constant
|
||||
pool in a special way. We do so if this is a SYMBOL_REF, LABEL_REF
|
||||
or a CONST containing one of them. If -mfp-in-toc (the default),
|
||||
we also do this for floating-point constants. We actually can only
|
||||
do this if the FP formats of the target and host machines are the
|
||||
same, but we can't check that since not every file that uses
|
||||
GO_IF_LEGITIMATE_ADDRESS_P includes real.h. We also do this when
|
||||
we can write the entry into the TOC and the entry is not larger
|
||||
than a TOC entry. */
|
||||
|
||||
#define ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X, MODE) \
|
||||
(TARGET_TOC \
|
||||
&& (GET_CODE (X) == SYMBOL_REF \
|
||||
|| (GET_CODE (X) == CONST && GET_CODE (XEXP (X, 0)) == PLUS \
|
||||
&& GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF) \
|
||||
|| GET_CODE (X) == LABEL_REF \
|
||||
|| (GET_CODE (X) == CONST_INT \
|
||||
&& GET_MODE_BITSIZE (MODE) <= GET_MODE_BITSIZE (Pmode)) \
|
||||
|| (GET_CODE (X) == CONST_DOUBLE \
|
||||
&& (TARGET_POWERPC64 \
|
||||
|| TARGET_MINIMAL_TOC \
|
||||
|| (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
|
||||
&& ! TARGET_NO_FP_IN_TOC)))))
|
||||
|
||||
/* Select section for constant in constant pool.
|
||||
|
||||
On RS/6000, all constants are in the private read-only data area.
|
||||
However, if this is being placed in the TOC it must be output as a
|
||||
toc entry. */
|
||||
|
||||
#define SELECT_RTX_SECTION(MODE, X) \
|
||||
{ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (X, MODE)) \
|
||||
toc_section (); \
|
||||
else \
|
||||
read_only_private_data_section (); \
|
||||
}
|
||||
|
||||
/* If we are referencing a function that is static or is known to be
|
||||
in this file, make the SYMBOL_REF special. We can use this to indicate
|
||||
that we can branch to this function without emitting a no-op after the
|
||||
call. Do not set this flag if the function is weakly defined. */
|
||||
|
||||
#define ENCODE_SECTION_INFO(DECL) \
|
||||
if (TREE_CODE (DECL) == FUNCTION_DECL \
|
||||
&& !TREE_PUBLIC (DECL) \
|
||||
&& !DECL_WEAK (DECL)) \
|
||||
SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1;
|
||||
|
||||
/* FP save and restore routines. */
|
||||
#define SAVE_FP_PREFIX "._savef"
|
||||
#define SAVE_FP_SUFFIX ""
|
||||
#define RESTORE_FP_PREFIX "._restf"
|
||||
#define RESTORE_FP_SUFFIX ""
|
||||
|
||||
/* Function name to call to do profiling. */
|
||||
#define RS6000_MCOUNT ".__mcount"
|
||||
|
||||
/* Function names to call to do floating point truncation. */
|
||||
|
||||
#define RS6000_ITRUNC "__itrunc"
|
||||
#define RS6000_UITRUNC "__uitrunc"
|
||||
|
||||
/* This outputs NAME to FILE up to the first null or '['. */
|
||||
|
||||
#define RS6000_OUTPUT_BASENAME(FILE, NAME) \
|
||||
{ \
|
||||
const char *_p; \
|
||||
\
|
||||
STRIP_NAME_ENCODING (_p, (NAME)); \
|
||||
assemble_name ((FILE), _p); \
|
||||
}
|
||||
|
||||
/* This is how to output the definition of a user-level label named NAME,
|
||||
such as the label on a static function or variable NAME. */
|
||||
|
||||
#define ASM_OUTPUT_LABEL(FILE,NAME) \
|
||||
do { RS6000_OUTPUT_BASENAME (FILE, NAME); fputs (":\n", FILE); } while (0)
|
||||
|
||||
/* This is how to output a command to make the user-level label named NAME
|
||||
defined for reference from other files. */
|
||||
|
||||
#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
|
||||
do { fputs ("\t.globl ", FILE); \
|
||||
RS6000_OUTPUT_BASENAME (FILE, NAME); putc ('\n', FILE);} while (0)
|
||||
|
||||
/* Remove any trailing [DS] or the like from the symbol name. */
|
||||
|
||||
#define STRIP_NAME_ENCODING(VAR,NAME) \
|
||||
do \
|
||||
{ \
|
||||
const char *_name = (NAME); \
|
||||
size_t _len; \
|
||||
if (*_name == '*') \
|
||||
_name++; \
|
||||
_len = strlen (_name); \
|
||||
if (_name[_len - 1] != ']') \
|
||||
(VAR) = _name; \
|
||||
else \
|
||||
{ \
|
||||
char *_new_name = (char *) alloca (_len + 1); \
|
||||
strcpy (_new_name, _name); \
|
||||
_new_name[_len - 4] = '\0'; \
|
||||
(VAR) = _new_name; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Output at beginning of assembler file.
|
||||
|
||||
Initialize the section names for the RS/6000 at this point.
|
||||
|
||||
Specify filename, including full path, to assembler.
|
||||
|
||||
We want to go into the TOC section so at least one .toc will be emitted.
|
||||
Also, in order to output proper .bs/.es pairs, we need at least one static
|
||||
[RW] section emitted.
|
||||
|
||||
Finally, declare mcount when profiling to make the assembler happy. */
|
||||
|
||||
#define ASM_FILE_START(FILE) \
|
||||
{ \
|
||||
rs6000_gen_section_name (&xcoff_bss_section_name, \
|
||||
main_input_filename, ".bss_"); \
|
||||
rs6000_gen_section_name (&xcoff_private_data_section_name, \
|
||||
main_input_filename, ".rw_"); \
|
||||
rs6000_gen_section_name (&xcoff_read_only_section_name, \
|
||||
main_input_filename, ".ro_"); \
|
||||
\
|
||||
fprintf (FILE, "\t.file\t\"%s\"\n", main_input_filename); \
|
||||
if (TARGET_64BIT) \
|
||||
fputs ("\t.machine\t\"ppc64\"\n", FILE); \
|
||||
toc_section (); \
|
||||
if (write_symbols != NO_DEBUG) \
|
||||
private_data_section (); \
|
||||
text_section (); \
|
||||
if (profile_flag) \
|
||||
fprintf (FILE, "\t.extern %s\n", RS6000_MCOUNT); \
|
||||
rs6000_file_start (FILE, TARGET_CPU_DEFAULT); \
|
||||
}
|
||||
|
||||
/* Output at end of assembler file.
|
||||
|
||||
On the RS/6000, referencing data should automatically pull in text. */
|
||||
|
||||
#define ASM_FILE_END(FILE) \
|
||||
{ \
|
||||
text_section (); \
|
||||
fputs ("_section_.text:\n", FILE); \
|
||||
data_section (); \
|
||||
fputs (TARGET_32BIT \
|
||||
? "\t.long _section_.text\n" : "\t.llong _section_.text\n", FILE); \
|
||||
}
|
||||
|
||||
/* This macro produces the initial definition of a function name.
|
||||
On the RS/6000, we need to place an extra '.' in the function name and
|
||||
output the function descriptor.
|
||||
|
||||
The csect for the function will have already been created by the
|
||||
`text_section' call previously done. We do have to go back to that
|
||||
csect, however.
|
||||
|
||||
We also record that the function exists in the current compilation
|
||||
unit, reachable by short branch, by setting SYMBOL_REF_FLAG.
|
||||
|
||||
The third and fourth parameters to the .function pseudo-op (16 and 044)
|
||||
are placeholders which no longer have any use. */
|
||||
|
||||
#define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL) \
|
||||
{ rtx sym_ref = XEXP (DECL_RTL (DECL), 0); \
|
||||
if (!DECL_WEAK (DECL)) \
|
||||
SYMBOL_REF_FLAG (sym_ref) = 1; \
|
||||
if (TREE_PUBLIC (DECL)) \
|
||||
{ \
|
||||
fputs ("\t.globl .", FILE); \
|
||||
RS6000_OUTPUT_BASENAME (FILE, NAME); \
|
||||
putc ('\n', FILE); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
fputs ("\t.lglobl .", FILE); \
|
||||
RS6000_OUTPUT_BASENAME (FILE, NAME); \
|
||||
putc ('\n', FILE); \
|
||||
} \
|
||||
fputs ("\t.csect ", FILE); \
|
||||
RS6000_OUTPUT_BASENAME (FILE, NAME); \
|
||||
fputs (TARGET_32BIT ? "[DS]\n" : "[DS],3\n", FILE); \
|
||||
RS6000_OUTPUT_BASENAME (FILE, NAME); \
|
||||
fputs (":\n", FILE); \
|
||||
fputs (TARGET_32BIT ? "\t.long ." : "\t.llong .", FILE); \
|
||||
RS6000_OUTPUT_BASENAME (FILE, NAME); \
|
||||
fputs (", TOC[tc0], 0\n", FILE); \
|
||||
in_section = no_section; \
|
||||
function_section(DECL); \
|
||||
putc ('.', FILE); \
|
||||
RS6000_OUTPUT_BASENAME (FILE, NAME); \
|
||||
fputs (":\n", FILE); \
|
||||
if (write_symbols == XCOFF_DEBUG) \
|
||||
xcoffout_declare_function (FILE, DECL, NAME); \
|
||||
}
|
||||
|
||||
/* Output a reference to SYM on FILE. */
|
||||
|
||||
#define ASM_OUTPUT_SYMBOL_REF(FILE, SYM) \
|
||||
rs6000_output_symbol_ref (FILE, SYM)
|
||||
|
||||
/* This says how to output an external. */
|
||||
|
||||
#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \
|
||||
{ rtx _symref = XEXP (DECL_RTL (DECL), 0); \
|
||||
if ((TREE_CODE (DECL) == VAR_DECL \
|
||||
|| TREE_CODE (DECL) == FUNCTION_DECL) \
|
||||
&& (NAME)[strlen (NAME) - 1] != ']') \
|
||||
{ \
|
||||
char *_name = (char *) permalloc (strlen (XSTR (_symref, 0)) + 5); \
|
||||
strcpy (_name, XSTR (_symref, 0)); \
|
||||
strcat (_name, TREE_CODE (DECL) == FUNCTION_DECL ? "[DS]" : "[RW]"); \
|
||||
XSTR (_symref, 0) = _name; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* This is how to output an internal numbered label where
|
||||
PREFIX is the class of label and NUM is the number within the class. */
|
||||
|
||||
#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
|
||||
fprintf (FILE, "%s..%d:\n", PREFIX, NUM)
|
||||
|
||||
/* This is how to output an internal label prefix. rs6000.c uses this
|
||||
when generating traceback tables. */
|
||||
|
||||
#define ASM_OUTPUT_INTERNAL_LABEL_PREFIX(FILE,PREFIX) \
|
||||
fprintf (FILE, "%s..", PREFIX)
|
||||
|
||||
/* This is how to output a label for a jump table. Arguments are the same as
|
||||
for ASM_OUTPUT_INTERNAL_LABEL, except the insn for the jump table is
|
||||
passed. */
|
||||
|
||||
#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLEINSN) \
|
||||
{ ASM_OUTPUT_ALIGN (FILE, 2); ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); }
|
||||
|
||||
/* This is how to store into the string LABEL
|
||||
the symbol_ref name of an internal numbered label where
|
||||
PREFIX is the class of label and NUM is the number within the class.
|
||||
This is suitable for output with `assemble_name'. */
|
||||
|
||||
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
|
||||
sprintf (LABEL, "*%s..%ld", (PREFIX), (long)(NUM))
|
||||
|
||||
/* This is how to output an assembler line to define N characters starting
|
||||
at P to FILE. */
|
||||
|
||||
#define ASM_OUTPUT_ASCII(FILE, P, N) output_ascii ((FILE), (P), (N))
|
||||
|
||||
/* This is how to advance the location counter by SIZE bytes. */
|
||||
|
||||
#define ASM_OUTPUT_SKIP(FILE,SIZE) \
|
||||
fprintf (FILE, "\t.space %d\n", (SIZE))
|
||||
|
||||
/* This says how to output an assembler line
|
||||
to define a global common symbol. */
|
||||
|
||||
#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGNMENT) \
|
||||
do { fputs (".comm ", (FILE)); \
|
||||
RS6000_OUTPUT_BASENAME ((FILE), (NAME)); \
|
||||
if ( (SIZE) > 4) \
|
||||
fprintf ((FILE), ",%d,3\n", (SIZE)); \
|
||||
else \
|
||||
fprintf ((FILE), ",%d\n", (SIZE)); \
|
||||
} while (0)
|
||||
|
||||
/* Used by definition of ASM_OUTPUT_DOUBLE_INT */
|
||||
#define DOUBLE_INT_ASM_OP ".llong"
|
||||
|
||||
/* This says how to output an assembler line
|
||||
to define a local common symbol.
|
||||
Alignment cannot be specified, but we can try to maintain
|
||||
alignment after preceding TOC section if it was aligned
|
||||
for 64-bit mode. */
|
||||
|
||||
#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
|
||||
do { fputs (".lcomm ", (FILE)); \
|
||||
RS6000_OUTPUT_BASENAME ((FILE), (NAME)); \
|
||||
fprintf ((FILE), ",%d,%s\n", (TARGET_32BIT ? (SIZE) : (ROUNDED)), \
|
||||
xcoff_bss_section_name); \
|
||||
} while (0)
|
||||
|
||||
/* This is how we tell the assembler that two symbols have the same value. */
|
||||
|
||||
#define SET_ASM_OP "\t.set\t"
|
||||
|
||||
/* These are various definitions for DWARF output. They could just
|
||||
use '.long' or '.word', but that aligns to a 4-byte boundary which
|
||||
is not what is required. So we define a million macros... */
|
||||
|
||||
#define UNALIGNED_SHORT_ASM_OP "\t.vbyte\t2,"
|
||||
#define UNALIGNED_INT_ASM_OP "\t.vbyte\t4,"
|
||||
#define UNALIGNED_DOUBLE_INT_ASM_OP "\t.vbyte\t8,"
|
||||
|
||||
/* Output before instructions. */
|
||||
#define TEXT_SECTION_ASM_OP "\t.csect .text[PR]"
|
||||
|
||||
/* Output before writable data.
|
||||
Align entire section to BIGGEST_ALIGNMENT. */
|
||||
#define DATA_SECTION_ASM_OP "\t.csect .data[RW],3"
|
||||
|
||||
/* Define unique section name -- functions only. */
|
||||
#define UNIQUE_SECTION(DECL,RELOC) \
|
||||
do { \
|
||||
int len; \
|
||||
const char *name; \
|
||||
char *string; \
|
||||
\
|
||||
if (TREE_CODE (DECL) == FUNCTION_DECL) { \
|
||||
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL)); \
|
||||
len = strlen (name) + 5; \
|
||||
string = alloca (len) + 1; \
|
||||
sprintf (string, ".%s[PR]", name); \
|
||||
DECL_SECTION_NAME (DECL) = build_string (len, string); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ASM_OUTPUT_SECTION_NAME(ASM_OUT_FILE,DECL,NAME,RELOC) \
|
||||
do { fputs ("\t.csect ", ASM_OUT_FILE); \
|
||||
fputs (TREE_STRING_POINTER (DECL_SECTION_NAME (DECL)), ASM_OUT_FILE); \
|
||||
putc ('\n', ASM_OUT_FILE); \
|
||||
} while (0)
|
||||
|
||||
/* Define the name of the section to use for the exception tables.
|
||||
TODO: test and see if we can use read_only_data_section, if so,
|
||||
remove this. */
|
||||
|
||||
#define EXCEPTION_SECTION data_section
|
Loading…
Add table
Reference in a new issue