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:
Daniel Berlin 2001-07-31 17:20:20 +00:00 committed by Daniel Berlin
parent befe7c6146
commit 2bfcf29777
12 changed files with 1432 additions and 871 deletions

View file

@ -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.

View file

@ -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
;;

View file

@ -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

View file

@ -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)))

View file

@ -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
View 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"

View file

@ -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));

View file

@ -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);

View file

@ -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}}, \

View file

@ -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"))

View file

@ -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
View 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