}
#undef LINK_SPEC
-#ifndef CROSS_COMPILE
#define LINK_SPEC "-bpT:0x10000000 -bpD:0x20000000 %{!r:-btextro} -bnodelcsect\
- %{static:-bnso -bI:/lib/syscalls.exp} %{!shared: %{g*:-bexport:/usr/lib/libg.exp}}\
+ %{static:-bnso %(link_syscalls) } %{!shared: %{g*: %(link_libg) }}\
%{shared:-bM:SRE}"
-#else
-#define LINK_SPEC "-bpT:0x10000000 -bpD:0x20000000 %{!r:-btextro} -bnodelcsect\
- %{static:-bnso} \
- %{shared:-bM:SRE}"
-#endif
#define CPP_PREDEFINES \
"-DPPC -D__embedded__ -Asystem(embedded) -Acpu(powerpc) -Amachine(powerpc)"
+/* Clue the simulator in to use netbsd */
+#undef LINK_START_SPEC
+#define LINK_START_SPEC "%{msim: %{!Ttext*: -Ttext 0x10000000}}"
+
/* Use the simulator crt0 or mvme and libgloss/newlib libraries if desired */
#undef STARTFILE_SPEC
#define STARTFILE_SPEC "crti.o%s \
`MULTILIB_OPTIONS' are set by default. *Note Target Fragment::. */
#undef MULTILIB_DEFAULTS
-#define MULTILIB_DEFAULTS { "mbig", "mbig-endian", "mcall-aix" }
+#define MULTILIB_DEFAULTS { "mbig", "mbig-endian", "mcall-aix", "mno-sdata" }
`MULTILIB_OPTIONS' are set by default. *Note Target Fragment::. */
#undef MULTILIB_DEFAULTS
-#define MULTILIB_DEFAULTS { "mlittle", "mlittle-endian", "mcall-sysv" }
+#define MULTILIB_DEFAULTS { "mlittle", "mlittle-endian", "mcall-sysv", "mno-sdata" }
#define CPP_PREDEFINES \
"-DPPC -D__embedded__ -D__simulator__ -Asystem(embedded) -Asystem(simulator) -Acpu(powerpc) -Amachine(powerpc)"
+/* Clue the simulator in to use netbsd */
+#undef LINK_START_SPEC
+#define LINK_START_SPEC "%{!mmvme: %{!Ttext*: -Ttext 0x10000000}}"
+
/* Use the simulator crt0 or mvme and libgloss/newlib libraries if desired */
#undef STARTFILE_SPEC
#define STARTFILE_SPEC "crti.o%s \
#include "obstack.h"
#include "tree.h"
+#ifndef TARGET_NO_PROTOTYPE
+#define TARGET_NO_PROTOTYPE 0
+#endif
+
extern char *language_string;
extern int profile_block_flag;
for an add will be valid. */
return add_operand (op, mode);
}
+
+/* Return 1 for an operand in small memory on V.4/eabi */
+
+int
+small_data_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ rtx sym_ref, const_part;
+
+ if (DEFAULT_ABI != ABI_V4)
+ return 0;
+
+ if (GET_CODE (op) != SYMBOL_REF && GET_CODE (op) != CONST)
+ return 0;
+
+ sym_ref = eliminate_constant_term (op, &const_part);
+ if (!sym_ref || GET_CODE (sym_ref) != SYMBOL_REF || *XSTR (sym_ref, 0) != '@')
+ return 0;
+
+ return 1;
+}
+
\f
/* Initialize a variable CUM of type CUMULATIVE_ARGS
for a call to a function whose data type is FNTYPE.
int incoming;
{
static CUMULATIVE_ARGS zero_cumulative;
+ enum rs6000_abi abi = DEFAULT_ABI;
*cum = zero_cumulative;
cum->words = 0;
cum->fregno = FP_ARG_MIN_REG;
cum->prototype = (fntype && TYPE_ARG_TYPES (fntype));
+ cum->call_cookie = CALL_NORMAL;
if (incoming)
{
cum->nargs_prototype = 1000; /* don't return an EXPR_LIST */
-#ifdef TARGET_V4_CALLS
- if (TARGET_V4_CALLS)
+ if (abi == ABI_V4)
cum->varargs_offset = RS6000_VARARGS_OFFSET;
-#endif
}
else if (cum->prototype)
cum->nargs_prototype = 0;
cum->orig_nargs = cum->nargs_prototype;
+
+ /* Check for DLL import functions */
+ if (abi == ABI_NT
+ && fntype
+ && lookup_attribute ("dllimport", TYPE_ATTRIBUTES (fntype)))
+ cum->call_cookie = CALL_NT_DLLIMPORT;
+
if (TARGET_DEBUG_ARG)
{
fprintf (stderr, "\ninit_cumulative_args:");
tree_code_name[ (int)TREE_CODE (ret_type) ]);
}
-#ifdef TARGET_V4_CALLS
- if (TARGET_V4_CALLS && incoming)
+ if (abi == ABI_V4 && incoming)
fprintf (stderr, " varargs = %d, ", cum->varargs_offset);
-#endif
+
+ if (cum->call_cookie == CALL_NT_DLLIMPORT)
+ fprintf (stderr, " dllimport,");
fprintf (stderr, " proto = %d, nargs = %d\n",
cum->prototype, cum->nargs_prototype);
cum->words += align;
cum->nargs_prototype--;
-#ifdef TARGET_V4_CALLS
- if (TARGET_V4_CALLS)
+ if (DEFAULT_ABI == ABI_V4)
{
/* Long longs must not be split between registers and stack */
if ((GET_MODE_CLASS (mode) != MODE_FLOAT || TARGET_SOFT_FLOAT)
cum->words += RS6000_ARG_SIZE (mode, type, 1);
}
else
-#endif
if (named)
{
cum->words += RS6000_ARG_SIZE (mode, type, named);
marker for software floating point, or compiler generated library calls. */
if (mode == VOIDmode)
{
-#ifdef TARGET_V4_CALLS
- if (TARGET_V4_CALLS && TARGET_HARD_FLOAT && cum->nargs_prototype < 0
+ enum rs6000_abi abi = DEFAULT_ABI;
+
+ if (abi == ABI_V4
+ && TARGET_HARD_FLOAT
+ && cum->nargs_prototype < 0
&& type && (cum->prototype || TARGET_NO_PROTOTYPE))
- return GEN_INT ((cum->fregno == FP_ARG_MIN_REG) ? -1 : 1);
-#endif
+ {
+ if (cum->call_cookie != CALL_NORMAL)
+ abort ();
+
+ return GEN_INT ((cum->fregno == FP_ARG_MIN_REG)
+ ? CALL_V4_SET_FP_ARGS
+ : CALL_V4_CLEAR_FP_ARGS);
+ }
- return GEN_INT (0);
+ return GEN_INT (cum->call_cookie);
}
if (!named)
{
-#ifdef TARGET_V4_CALLS
- if (!TARGET_V4_CALLS)
-#endif
+ if (DEFAULT_ABI != ABI_V4)
return NULL_RTX;
}
if (USE_FP_FOR_ARG_P (*cum, mode, type))
{
if ((cum->nargs_prototype > 0)
-#ifdef TARGET_V4_CALLS
- || TARGET_V4_CALLS /* V.4 never passes FP values in GP registers */
-#endif
+ || (DEFAULT_ABI == ABI_V4) /* V.4 never passes FP values in GP registers */
|| !type)
return gen_rtx (REG, mode, cum->fregno);
gen_rtx (REG, mode, cum->fregno));
}
-#ifdef TARGET_V4_CALLS
/* Long longs won't be split between register and stack */
- else if (TARGET_V4_CALLS &&
+ else if (DEFAULT_ABI == ABI_V4 &&
align_words + RS6000_ARG_SIZE (mode, type, named) > GP_ARG_NUM_REG)
{
return NULL_RTX;
}
-#endif
else if (align_words < GP_ARG_NUM_REG)
return gen_rtx (REG, mode, GP_ARG_MIN_REG + align_words);
if (! named)
return 0;
-#ifdef TARGET_V4_CALLS
- if (TARGET_V4_CALLS)
+ if (DEFAULT_ABI == ABI_V4)
return 0;
-#endif
if (USE_FP_FOR_ARG_P (*cum, mode, type))
{
tree type;
int named;
{
-#ifdef TARGET_V4_CALLS
- if (TARGET_V4_CALLS && type && AGGREGATE_TYPE_P (type))
+ if (DEFAULT_ABI == ABI_V4 && type && AGGREGATE_TYPE_P (type))
{
if (TARGET_DEBUG_ARG)
fprintf (stderr, "function_arg_pass_by_reference: aggregate\n");
return 1;
}
-#endif
return 0;
}
"setup_vararg: words = %2d, fregno = %2d, nargs = %4d, proto = %d, mode = %4s, no_rtl= %d\n",
cum->words, cum->fregno, cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode), no_rtl);
-#ifdef TARGET_V4_CALLS
- if (TARGET_V4_CALLS && !no_rtl)
+ if (DEFAULT_ABI == ABI_V4 && !no_rtl)
{
rs6000_sysv_varargs_p = 1;
save_area = plus_constant (frame_pointer_rtx, RS6000_VARARGS_OFFSET);
}
-#endif
if (cum->words < 8)
{
*pretend_size = (GP_ARG_NUM_REG - first_reg_offset) * UNITS_PER_WORD;
}
-#ifdef TARGET_V4_CALLS
/* Save FP registers if needed. */
- if (TARGET_V4_CALLS && TARGET_HARD_FLOAT && !no_rtl)
+ if (DEFAULT_ABI == ABI_V4 && TARGET_HARD_FLOAT && !no_rtl)
{
int fregno = cum->fregno;
int num_fp_reg = FP_ARG_V4_MAX_REG + 1 - fregno;
emit_label (lab);
}
}
-#endif
}
\f
/* If defined, is a C expression that produces the machine-specific
else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == CONST)
{
output_addr_const (file, x);
- /* When TARGET_MINIMAL_TOC, use the indirected toc table pointer instead
- of the toc pointer. */
+ if (DEFAULT_ABI == ABI_V4 && small_data_operand (x, GET_MODE (x)))
+ fprintf (file, "@sda21(%s)", reg_names[0]);
+
#ifdef TARGET_NO_TOC
- if (TARGET_NO_TOC)
+ else if (TARGET_NO_TOC)
;
- else
#endif
+ else
fprintf (file, "(%s)", reg_names[ TARGET_MINIMAL_TOC ? 30 : 2 ]);
}
else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == REG)
return;
}
+
+\f
+/* If defined, a C expression whose value is nonzero if IDENTIFIER
+ with arguments ARGS is a valid machine specific attribute for DECL.
+ The attributes in ATTRIBUTES have previously been assigned to DECL. */
+
+int
+rs6000_valid_decl_attribute_p (decl, attributes, identifier, args)
+ tree decl;
+ tree attributes;
+ tree identifier;
+ tree args;
+{
+ return 0;
+}
+
+/* If defined, a C expression whose value is nonzero if IDENTIFIER
+ with arguments ARGS is a valid machine specific attribute for TYPE.
+ The attributes in ATTRIBUTES have previously been assigned to TYPE. */
+
+int
+rs6000_valid_type_attribute_p (type, attributes, identifier, args)
+ tree type;
+ tree attributes;
+ tree identifier;
+ tree args;
+{
+ if (TREE_CODE (type) != FUNCTION_TYPE
+ && TREE_CODE (type) != FIELD_DECL
+ && TREE_CODE (type) != TYPE_DECL)
+ return 0;
+
+ if (DEFAULT_ABI == ABI_NT)
+ {
+ /* Stdcall attribute says callee is responsible for popping arguments
+ if they are not variable. */
+ if (is_attribute_p ("stdcall", identifier))
+ return (args == NULL_TREE);
+
+ /* Cdecl attribute says the callee is a normal C declaration */
+ if (is_attribute_p ("cdecl", identifier))
+ return (args == NULL_TREE);
+
+ /* Dllimport attribute says says the caller is to call the function
+ indirectly through a __imp_<name> pointer. */
+ if (is_attribute_p ("dllimport", identifier))
+ return (args == NULL_TREE);
+
+ /* Dllexport attribute says says the callee is to create a __imp_<name>
+ pointer. */
+ if (is_attribute_p ("dllexport", identifier))
+ return (args == NULL_TREE);
+ }
+
+ return 0;
+}
+
+/* If defined, a C expression whose value is zero if the attributes on
+ TYPE1 and TYPE2 are incompatible, one if they are compatible, and
+ two if they are nearly compatible (which causes a warning to be
+ generated). */
+
+int
+rs6000_comp_type_attributes (type1, type2)
+ tree type1;
+ tree type2;
+{
+ return 1;
+}
+
+/* If defined, a C statement that assigns default attributes to newly
+ defined TYPE. */
+
+void
+rs6000_set_default_type_attributes (type)
+ tree type;
+{
+}
+
+/* Return a dll import reference corresponding to to a call's SYMBOL_REF */
+struct rtx_def *
+rs6000_dll_import_ref (call_ref)
+ rtx call_ref;
+{
+ char *call_name;
+ int len;
+ char *p;
+ rtx reg1, reg2;
+ tree node;
+
+ if (GET_CODE (call_ref) != SYMBOL_REF)
+ abort ();
+
+ call_name = XSTR (call_ref, 0);
+ len = sizeof ("__imp_") + strlen (call_name);
+ p = alloca (len);
+ reg2 = gen_reg_rtx (Pmode);
+
+ strcpy (p, "__imp_");
+ strcat (p, call_name);
+ node = get_identifier (p);
+
+ reg1 = force_reg (Pmode, gen_rtx (SYMBOL_REF, VOIDmode, IDENTIFIER_POINTER (node)));
+ emit_move_insn (reg2, gen_rtx (MEM, Pmode, reg1));
+
+ return reg2;
+}
+
+\f
+/* A C statement or statements to switch to the appropriate section
+ for output of RTX in mode MODE. You can assume that RTX is some
+ kind of constant in RTL. The argument MODE is redundant except in
+ the case of a `const_int' rtx. Select the section by calling
+ `text_section' or one of the alternatives for other sections.
+
+ Do not define this macro if you put all constants in the read-only
+ data section. */
+
+#ifdef USING_SVR4_H
+
+void
+rs6000_select_rtx_section (mode, x)
+ enum machine_mode mode;
+ rtx x;
+{
+ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (x))
+ toc_section ();
+ else if (TARGET_SDATA && GET_MODE_SIZE (mode) > 0 && GET_MODE_SIZE (mode) <= 8)
+ sdata2_section ();
+ else
+ const_section ();
+}
+
+/* A C statement or statements to switch to the appropriate
+ section for output of DECL. DECL is either a `VAR_DECL' node
+ or a constant of some sort. RELOC indicates whether forming
+ the initial value of DECL requires link-time relocations. */
+
+void
+rs6000_select_section (decl, reloc)
+ tree decl;
+ int reloc;
+{
+ int size = int_size_in_bytes (TREE_TYPE (decl));
+
+ if (TREE_CODE (decl) == STRING_CST)
+ {
+ if ((! flag_writable_strings) && TARGET_SDATA && (size <= 8))
+ sdata2_section ();
+ else if (! flag_writable_strings)
+ const_section ();
+ else if (TARGET_SDATA && (size <= 8))
+ sdata_section ();
+ else
+ data_section ();
+ }
+ else if (TREE_CODE (decl) == VAR_DECL)
+ {
+ if ((flag_pic && reloc)
+ || !TREE_READONLY (decl)
+ || TREE_SIDE_EFFECTS (decl)
+ || !DECL_INITIAL (decl)
+ || (DECL_INITIAL (decl) != error_mark_node
+ && !TREE_CONSTANT (DECL_INITIAL (decl))))
+ {
+ if (TARGET_SDATA && (size <= 8) && (size > 0))
+ sdata_section ();
+ else
+ data_section ();
+ }
+ else
+ {
+ if (TARGET_SDATA && (size <= 8) && (size > 0))
+ sdata2_section ();
+ else
+ const_section ();
+ }
+ }
+ else
+ const_section ();
+}
+#endif /* USING_SVR4_H */
Do not define this macro if it does not need to do anything. */
+#ifndef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS
+#endif
+
#define EXTRA_SPECS \
{ "cpp_cpu", CPP_CPU_SPEC }, \
{ "cpp_default", CPP_DEFAULT_SPEC }, \
{ "cpp_sysv_default", CPP_SYSV_DEFAULT_SPEC }, \
{ "cpp_endian", CPP_ENDIAN_SPEC }, \
{ "asm_cpu", ASM_CPU_SPEC }, \
- { "asm_default", ASM_DEFAULT_SPEC }
+ { "asm_default", ASM_DEFAULT_SPEC }, \
+ { "link_syscalls", LINK_SYSCALLS_SPEC }, \
+ { "link_libg", LINK_LIBG_SPEC }, \
+ { "link_path", LINK_PATH_SPEC }, \
+ { "link_start", LINK_START_SPEC }, \
+ SUBTARGET_EXTRA_SPECS
+
+/* Default paths to give linker under V.4 */
+#ifndef LINK_PATH_SPEC
+#define LINK_PATH_SPEC ""
+#endif
+
+/* Default location of syscalls.exp under AIX */
+#ifndef CROSS_COMPILE
+#define LINK_SYSCALLS_SPEC "-bI:/lib/syscalls.exp"
+#else
+#define LINK_SYSCALLS_SPEC ""
+#endif
+
+/* Default location of libg.exp under AIX */
+#ifndef CROSS_COMPILE
+#define LINK_LIBG_SPEC "-bexport:/usr/lib/libg.exp"
+#else
+#define LINK_LIBG_SPEC ""
+#endif
+
+/* Default starting address if specified */
+#ifndef LINK_START_SPEC
+#define LINK_START_SPEC ""
+#endif
/* Define the options for the binder: Start text at 512, align all segments
to 512 bytes, and warn if there is text relocation.
that to actually build a shared library you will also need to specify an
export list with the -Wl,-bE option. */
-#ifndef CROSS_COMPILE
-#define LINK_SPEC "-T512 -H512 %{!r:-btextro} -bhalt:4 -bnodelcsect\
- %{static:-bnso} \
- %{shared:-bM:SRE}"
-#else
#define LINK_SPEC "-T512 -H512 %{!r:-btextro} -bhalt:4 -bnodelcsect\
- %{static:-bnso -bI:/lib/syscalls.exp} \
- %{!shared:%{g*:-bexport:/usr/lib/libg.exp}} %{shared:-bM:SRE}"
-#endif
+ %{static:-bnso %(link_syscalls) } \
+ %{!shared:%{g*: %(link_libg) }} %{shared:-bM:SRE}"
/* Profiled library versions are used by linking with special directories. */
#define LIB_SPEC "%{pg:-L/lib/profiled -L/usr/lib/profiled}\
/* Minimum and maximum floating point registers used to hold arguments. */
#define FP_ARG_MIN_REG 33
-#define FP_ARG_MAX_REG 45
+#define FP_ARG_AIX_MAX_REG 45
+#define FP_ARG_V4_MAX_REG 40
+#define FP_ARG_MAX_REG FP_ARG_AIX_MAX_REG
#define FP_ARG_NUM_REG (FP_ARG_MAX_REG - FP_ARG_MIN_REG + 1)
/* Return registers */
#define GP_ARG_RETURN GP_ARG_MIN_REG
#define FP_ARG_RETURN FP_ARG_MIN_REG
+/* Flags for the call/call_value rtl operations set up by function_arg */
+enum rs6000_call_cookie
+{
+ CALL_V4_SET_FP_ARGS = -1, /* V4, FP args passed */
+ CALL_NORMAL = 0, /* no special processing */
+ CALL_V4_CLEAR_FP_ARGS = 1, /* V4, no FP args passed */
+ CALL_NT_DLLIMPORT = 2 /* NT, this is a DLL import call */
+};
+
/* Define cutoff for using external functions to save floating point */
#define FP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) == 62 || (FIRST_REG) == 63)
typedef struct rs6000_args
{
- int words; /* # words uses for passing GP registers */
- int fregno; /* next available FP register */
- int nargs_prototype; /* # args left in the current prototype */
- int orig_nargs; /* Original value of nargs_prototype */
- int varargs_offset; /* offset of the varargs save area */
- int prototype; /* Whether a prototype was defined */
+ int words; /* # words uses for passing GP registers */
+ int fregno; /* next available FP register */
+ int nargs_prototype; /* # args left in the current prototype */
+ int orig_nargs; /* Original value of nargs_prototype */
+ int varargs_offset; /* offset of the varargs save area */
+ int prototype; /* Whether a prototype was defined */
+ enum rs6000_call_cookie call_cookie; /* Do special things for this call */
} CUMULATIVE_ARGS;
/* Define intermediate macro to compute the size (in registers) of an argument
#define INITIALIZE_TRAMPOLINE(ADDR, FNADDR, CXT) \
rs6000_initialize_trampoline (ADDR, FNADDR, CXT)
\f
+/* If defined, a C expression whose value is nonzero if IDENTIFIER
+ with arguments ARGS is a valid machine specific attribute for DECL.
+ The attributes in ATTRIBUTES have previously been assigned to DECL. */
+
+#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, NAME, ARGS) \
+ (rs6000_valid_decl_attribute_p (DECL, ATTRIBUTES, NAME, ARGS))
+
+/* If defined, a C expression whose value is nonzero if IDENTIFIER
+ with arguments ARGS is a valid machine specific attribute for TYPE.
+ The attributes in ATTRIBUTES have previously been assigned to TYPE. */
+
+#define VALID_MACHINE_TYPE_ATTRIBUTE(TYPE, ATTRIBUTES, NAME, ARGS) \
+ (rs6000_valid_type_attribute_p (TYPE, ATTRIBUTES, NAME, ARGS))
+
+/* If defined, a C expression whose value is zero if the attributes on
+ TYPE1 and TYPE2 are incompatible, one if they are compatible, and
+ two if they are nearly compatible (which causes a warning to be
+ generated). */
+
+#define COMP_TYPE_ATTRIBUTES(TYPE1, TYPE2) \
+ (rs6000_comp_type_attributes (TYPE1, TYPE2))
+
+/* If defined, a C statement that assigns default attributes to newly
+ defined TYPE. */
+
+#define SET_DEFAULT_TYPE_ATTRIBUTES(TYPE) \
+ (rs6000_set_default_type_attributes (TYPE))
+
+\f
/* Definitions for __builtin_return_address and __builtin_frame_address.
__builtin_return_address (0) should give link register (65), enable
this. */
&& GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
&& LEGITIMATE_CONSTANT_POOL_BASE_P (XEXP (XEXP (X, 0), 0))))
+#define LEGITIMATE_SMALL_DATA_P(MODE, X) \
+ (DEFAULT_ABI == ABI_V4 && small_data_operand (X, MODE))
+
#define LEGITIMATE_ADDRESS_INTEGER_P(X,OFFSET) \
(GET_CODE (X) == CONST_INT \
&& (unsigned) (INTVAL (X) + (OFFSET) + 0x8000) < 0x10000)
if ((GET_CODE (X) == PRE_INC || GET_CODE (X) == PRE_DEC) \
&& LEGITIMATE_INDIRECT_ADDRESS_P (XEXP (X, 0))) \
goto ADDR; \
+ if (LEGITIMATE_SMALL_DATA_P (MODE, X)) \
+ goto ADDR; \
if (LEGITIMATE_CONSTANT_POOL_ADDRESS_P (X)) \
goto ADDR; \
if (LEGITIMATE_OFFSET_ADDRESS_P (MODE, X)) \
`assemble_name' uses this. */
#define ASM_OUTPUT_LABELREF(FILE,NAME) \
- fprintf (FILE, NAME)
+ fputs (NAME, FILE)
/* This is how to output an internal numbered label where
PREFIX is the class of label and NUM is the number within the class. */
extern int call_operand ();
extern int current_file_function_operand ();
extern int input_operand ();
+extern int small_data_operand ();
extern void init_cumulative_args ();
extern void function_arg_advance ();
extern int function_arg_boundary ();
extern void rs6000_trampoline_template ();
extern int rs6000_trampoline_size ();
extern void rs6000_initialize_trampoline ();
+extern int rs6000_comp_type_attributes ();
+extern int rs6000_valid_decl_attribute_p ();
+extern int rs6000_valid_type_attribute_p ();
+extern void rs6000_set_default_type_attributes ();
+extern struct rtx_def *rs6000_dll_import_ref ();
abort ();
operands[0] = XEXP (operands[0], 0);
+
+ /* Convert NT DLL imports into an indirect call. */
+ if (GET_CODE (operands[0]) == SYMBOL_REF
+ && INTVAL (operands[2]) == (int)CALL_NT_DLLIMPORT)
+ {
+ operands[0] = rs6000_dll_import_ref (operands[0]);
+ operands[2] = GEN_INT ((int)CALL_NORMAL);
+ }
+
if (GET_CODE (operands[0]) != SYMBOL_REF)
{
if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_AIX_NODESC)
else if (DEFAULT_ABI == ABI_NT)
{
/* NT function pointers are really pointers to a two word area */
+ rs6000_save_toc_p = 1;
emit_call_insn (gen_call_indirect_nt (force_reg (Pmode, operands[0]),
operands[1], operands[2],
toc_addr, toc_reg));
abort ();
operands[1] = XEXP (operands[1], 0);
+
+ /* Convert NT DLL imports into an indirect call. */
+ if (GET_CODE (operands[1]) == SYMBOL_REF
+ && INTVAL (operands[3]) == (int)CALL_NT_DLLIMPORT)
+ {
+ operands[1] = rs6000_dll_import_ref (operands[1]);
+ operands[3] = GEN_INT ((int)CALL_NORMAL);
+ }
+
if (GET_CODE (operands[1]) != SYMBOL_REF)
{
if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_AIX_NODESC)
else if (DEFAULT_ABI == ABI_NT)
{
/* NT function pointers are really pointers to a two word area */
+ rs6000_save_toc_p = 1;
emit_call_insn (gen_call_value_indirect_nt (operands[0],
force_reg (Pmode, operands[1]),
operands[2], operands[3],
""
"*
{
- if (INTVAL (operands[2]) > 0)
- return \"creqv 6,6,6\;bl %z0\";
-
- else if (INTVAL (operands[2]) < 0)
- return \"crxor 6,6,6\;bl %z0\";
+ switch ((enum rs6000_call_cookie)INTVAL (operands[2]))
+ {
+ case CALL_V4_SET_FP_ARGS: output_asm_insn (\"crxor 6,6,6\", operands); break;
+ case CALL_V4_CLEAR_FP_ARGS: output_asm_insn (\"creqv 6,6,6\", operands); break;
+ }
return \"bl %z0\";
}"
"DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT"
"*
{
- if (INTVAL (operands[2]) > 0)
- output_asm_insn (\"creqv 6,6,6\", operands);
-
- else if (INTVAL (operands[2]) < 0)
- output_asm_insn (\"crxor 6,6,6\", operands);
-
/* Indirect calls should go through call_indirect */
if (GET_CODE (operands[0]) == REG)
abort ();
+ switch ((enum rs6000_call_cookie)INTVAL (operands[2]))
+ {
+ case CALL_V4_SET_FP_ARGS: output_asm_insn (\"crxor 6,6,6\", operands); break;
+ case CALL_V4_CLEAR_FP_ARGS: output_asm_insn (\"creqv 6,6,6\", operands); break;
+ }
+
return (TARGET_WINDOWS_NT) ? \"bl %z0\;.znop %z0\" : \"bl %z0\;%.\";
}"
[(set_attr "length" "8,12")])
"DEFAULT_ABI == ABI_AIX_NODESC || DEFAULT_ABI == ABI_V4"
"*
{
- if (INTVAL (operands[2]) > 0)
- output_asm_insn (\"creqv 6,6,6\", operands);
-
- else if (INTVAL (operands[2]) < 0)
- output_asm_insn (\"crxor 6,6,6\", operands);
-
/* Indirect calls should go through call_indirect */
if (GET_CODE (operands[0]) == REG)
abort ();
+ switch ((enum rs6000_call_cookie)INTVAL (operands[2]))
+ {
+ case CALL_V4_SET_FP_ARGS: output_asm_insn (\"crxor 6,6,6\", operands); break;
+ case CALL_V4_CLEAR_FP_ARGS: output_asm_insn (\"creqv 6,6,6\", operands); break;
+ }
+
return \"bl %z0\";
}"
[(set_attr "length" "4,8")])
""
"*
{
- if (INTVAL (operands[3]) > 0)
- return \"creqv 6,6,6\;bl %z1\";
-
- else if (INTVAL (operands[3]) < 0)
- return \"crxor 6,6,6\;bl %z1\";
+ switch ((enum rs6000_call_cookie)INTVAL (operands[3]))
+ {
+ case CALL_V4_SET_FP_ARGS: output_asm_insn (\"crxor 6,6,6\", operands); break;
+ case CALL_V4_CLEAR_FP_ARGS: output_asm_insn (\"creqv 6,6,6\", operands); break;
+ }
return \"bl %z1\";
}"
"DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT"
"*
{
- if (INTVAL (operands[3]) > 0)
- output_asm_insn (\"creqv 6,6,6\", operands);
-
- else if (INTVAL (operands[3]) < 0)
- output_asm_insn (\"crxor 6,6,6\", operands);
-
/* This should be handled by call_value_indirect */
if (GET_CODE (operands[1]) == REG)
abort ();
+ switch ((enum rs6000_call_cookie)INTVAL (operands[3]))
+ {
+ case CALL_V4_SET_FP_ARGS: output_asm_insn (\"crxor 6,6,6\", operands); break;
+ case CALL_V4_CLEAR_FP_ARGS: output_asm_insn (\"creqv 6,6,6\", operands); break;
+ }
+
return (TARGET_WINDOWS_NT) ? \"bl %z1\;.znop %z1\" : \"bl %z1\;%.\";
}"
[(set_attr "length" "8,12")])
"DEFAULT_ABI == ABI_AIX_NODESC || DEFAULT_ABI == ABI_V4"
"*
{
- if (INTVAL (operands[3]) > 0)
- output_asm_insn (\"creqv 6,6,6\", operands);
-
- else if (INTVAL (operands[3]) < 0)
- output_asm_insn (\"crxor 6,6,6\", operands);
-
/* This should be handled by call_value_indirect */
if (GET_CODE (operands[1]) == REG)
abort ();
+ switch ((enum rs6000_call_cookie)INTVAL (operands[3]))
+ {
+ case CALL_V4_SET_FP_ARGS: output_asm_insn (\"crxor 6,6,6\", operands); break;
+ case CALL_V4_CLEAR_FP_ARGS: output_asm_insn (\"creqv 6,6,6\", operands); break;
+ }
+
return \"bl %z1\";
}"
[(set_attr "length" "4,8")])
#define MASK_NO_BITFIELD_TYPE 0x40000000 /* Set PCC_BITFIELD_TYPE_MATTERS to 0 */
#define MASK_STRICT_ALIGN 0x20000000 /* Set STRICT_ALIGNMENT to 1. */
#define MASK_RELOCATABLE 0x10000000 /* GOT pointers are PC relative */
-#define MASK_UNUSED 0x08000000 /* UNUSED, was no-traceback */
+#define MASK_SDATA 0x08000000 /* use eabi .sdata/.sdata2/.sbss relocations */
#define MASK_LITTLE_ENDIAN 0x04000000 /* target is little endian */
#define MASK_CALLS_1 0x02000000 /* First ABI bit (AIX, AIXDESC) */
#define MASK_PROTOTYPE 0x01000000 /* Only prototyped fcns pass variable args */
#define TARGET_NO_BITFIELD_TYPE (target_flags & MASK_NO_BITFIELD_TYPE)
#define TARGET_STRICT_ALIGN (target_flags & MASK_STRICT_ALIGN)
#define TARGET_RELOCATABLE (target_flags & MASK_RELOCATABLE)
+#define TARGET_SDATA (target_flags & MASK_SDATA)
#define TARGET_LITTLE_ENDIAN (target_flags & MASK_LITTLE_ENDIAN)
#define TARGET_PROTOTYPE (target_flags & MASK_PROTOTYPE)
#define TARGET_TOC ((target_flags & (MASK_64BIT \
{ "strict-align", MASK_STRICT_ALIGN }, \
{ "no-strict-align", -MASK_STRICT_ALIGN }, \
{ "relocatable", MASK_RELOCATABLE | MASK_MINIMAL_TOC | MASK_NO_FP_IN_TOC }, \
+ { "relocatable", -MASK_SDATA }, \
{ "no-relocatable", -MASK_RELOCATABLE }, \
{ "relocatable-lib", MASK_RELOCATABLE | MASK_MINIMAL_TOC | MASK_NO_FP_IN_TOC }, \
{ "no-relocatable-lib", -MASK_RELOCATABLE }, \
+ { "sdata", MASK_SDATA }, \
+ { "no-sdata", -MASK_SDATA }, \
{ "little-endian", MASK_LITTLE_ENDIAN }, \
{ "little", MASK_LITTLE_ENDIAN }, \
{ "big-endian", -MASK_LITTLE_ENDIAN }, \
#define SUBTARGET_OVERRIDE_OPTIONS \
do { \
+ rs6000_current_abi = ((TARGET_AIXDESC_CALLS) ? ABI_AIX : \
+ (TARGET_NT_CALLS) ? ABI_NT : \
+ (TARGET_AIX_CALLS) ? ABI_AIX_NODESC : \
+ ABI_V4); \
+ \
+ if (TARGET_RELOCATABLE && TARGET_SDATA) \
+ { \
+ target_flags &= ~MASK_SDATA; \
+ error ("-mrelocatable and -msdata are incompatible."); \
+ } \
+ \
+ if (TARGET_SDATA && DEFAULT_ABI != ABI_V4) \
+ { \
+ target_flags &= ~MASK_SDATA; \
+ error ("-msdata and -mcall-aix are incompatible."); \
+ } \
+ \
if (TARGET_RELOCATABLE && !TARGET_MINIMAL_TOC) \
{ \
target_flags |= MASK_MINIMAL_TOC; \
target_flags |= MASK_LITTLE_ENDIAN; \
error ("-mcall-nt must be little endian"); \
} \
- \
- rs6000_current_abi = ((TARGET_AIXDESC_CALLS) ? ABI_AIX : \
- (TARGET_NT_CALLS) ? ABI_NT : \
- (TARGET_AIX_CALLS) ? ABI_AIX_NODESC : \
- ABI_V4); \
} while (0)
/* Default ABI to compile code for */
/* System V.4 passes the first 8 floating arguments in registers,
instead of the first 13 like AIX does. */
#undef FP_ARG_MAX_REG
-#define FP_ARG_AIX_MAX_REG 45
-#define FP_ARG_V4_MAX_REG 40
#define FP_ARG_MAX_REG ((TARGET_AIX_CALLS) ? FP_ARG_AIX_MAX_REG : FP_ARG_V4_MAX_REG)
/* Size of the V.4 varargs area if needed */
/* Besides the usual ELF sections, we need a toc section. */
#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_const, in_ctors, in_dtors, in_toc
+#define EXTRA_SECTIONS in_const, in_ctors, in_dtors, in_toc, in_sdata, in_sdata2, in_sbss
#undef EXTRA_SECTION_FUNCTIONS
#define EXTRA_SECTION_FUNCTIONS \
CONST_SECTION_FUNCTION \
CTORS_SECTION_FUNCTION \
DTORS_SECTION_FUNCTION \
- TOC_SECTION_FUNCTION
+ TOC_SECTION_FUNCTION \
+ SDATA_SECTION_FUNCTION \
+ SDATA2_SECTION_FUNCTION \
+ SBSS_SECTION_FUNCTION
+
+extern void toc_section (), sdata_section (), sdata2_section ();
+extern void sbss_section ();
#define TOC_SECTION_FUNCTION \
void \
#define TOC_SECTION_ASM_OP "\t.section\t\".got\",\"aw\""
#define MINIMAL_TOC_SECTION_ASM_OP "\t.section\t\".got1\",\"aw\""
-/* Use the TOC section for TOC entries. */
+#define SDATA_SECTION_ASM_OP "\t.section\t\".sdata\",\"aw\""
+#define SDATA2_SECTION_ASM_OP "\t.section\t\".sdata2\",\"a\""
+#define SBSS_SECTION_ASM_OP "\t.section\t\".sbss\",\"aw\",@nobits"
-#undef SELECT_RTX_SECTION
-#define SELECT_RTX_SECTION(MODE, X) \
-{ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (X)) \
- toc_section (); \
- else \
- const_section (); \
+#define SDATA_SECTION_FUNCTION \
+void \
+sdata_section () \
+{ \
+ if (in_section != in_sdata) \
+ { \
+ in_section = in_sdata; \
+ fprintf (asm_out_file, "%s\n", SDATA_SECTION_ASM_OP); \
+ } \
+}
+
+#define SDATA2_SECTION_FUNCTION \
+void \
+sdata2_section () \
+{ \
+ if (in_section != in_sdata2) \
+ { \
+ in_section = in_sdata2; \
+ fprintf (asm_out_file, "%s\n", SDATA2_SECTION_ASM_OP); \
+ } \
+}
+
+#define SBSS_SECTION_FUNCTION \
+void \
+sbss_section () \
+{ \
+ if (in_section != in_sbss) \
+ { \
+ in_section = in_sbss; \
+ fprintf (asm_out_file, "%s\n", SBSS_SECTION_ASM_OP); \
+ } \
}
+/* A C statement or statements to switch to the appropriate section
+ for output of RTX in mode MODE. You can assume that RTX is some
+ kind of constant in RTL. The argument MODE is redundant except in
+ the case of a `const_int' rtx. Select the section by calling
+ `text_section' or one of the alternatives for other sections.
+
+ Do not define this macro if you put all constants in the read-only
+ data section. */
+
+extern void rs6000_select_rtx_section (), rs6000_select_section ();
+
+#undef SELECT_RTX_SECTION
+#define SELECT_RTX_SECTION(MODE, X) rs6000_select_rtx_section (MODE, X)
+
+/* A C statement or statements to switch to the appropriate
+ section for output of DECL. DECL is either a `VAR_DECL' node
+ or a constant of some sort. RELOC indicates whether forming
+ the initial value of DECL requires link-time relocations. */
+
+#undef SELECT_SECTION
+#define SELECT_SECTION(DECL,RELOC) rs6000_select_section (DECL, RELOC)
+
/* 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
#define ASM_OUTPUT_INTERNAL_LABEL_PREFIX(FILE,PREFIX) \
fprintf (FILE, ".%s", PREFIX)
-/* Pass -mppc to the assembler, since that is what powerpc.h currently
- implies. */
+/* Pass various options to the assembler */
#undef ASM_SPEC
#define ASM_SPEC "-u %(asm_cpu) \
%{V} %{v:%{!V:-V}} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \
-%{mrelocatable} %{mrelocatable-lib} %{memb} \
+%{mrelocatable} %{mrelocatable-lib} %{memb} %{msdata: -memb} \
%{mlittle} %{mlittle-endian} %{mbig} %{mbig-endian}"
/* Output .file and comments listing what options there are */
XSTR (sym_ref, 0) = str; \
} \
} \
+ else if (TARGET_SDATA && DEFAULT_ABI == ABI_V4 \
+ && TREE_CODE (DECL) == VAR_DECL) \
+ { \
+ int size = int_size_in_bytes (TREE_TYPE (DECL)); \
+ tree section_name = DECL_SECTION_NAME (DECL); \
+ char *name = ((section_name) \
+ ? IDENTIFIER_POINTER (section_name) \
+ : (char *)0); \
+ \
+ if ((size > 0 && size <= 8) \
+ || (name \
+ && (strcmp (name, ".sdata") == 0 \
+ || strcmp (name, ".sdata2") == 0 \
+ || strcmp (name, ".sbss") == 0 \
+ || strcmp (name, ".sbss2") == 0 \
+ || strcmp (name, ".PPC.EMB.sdata0") == 0 \
+ || strcmp (name, ".PPC.EMB.sbss0") == 0))) \
+ { \
+ rtx sym_ref = XEXP (DECL_RTL (DECL), 0); \
+ char *str = permalloc (2 + strlen (XSTR (sym_ref, 0))); \
+ strcpy (str, "@"); \
+ strcat (str, XSTR (sym_ref, 0)); \
+ XSTR (sym_ref, 0) = str; \
+ } \
+ } \
} while (0)
/* This macro gets just the user-specified name
out of the string in a SYMBOL_REF. Discard
- a leading * */
+ a leading * or @. */
#undef STRIP_NAME_ENCODING
#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \
- (VAR) = ((SYMBOL_NAME) + ((SYMBOL_NAME)[0] == '*'))
+ (VAR) = ((SYMBOL_NAME) + (((SYMBOL_NAME)[0] == '*') || ((SYMBOL_NAME)[0] == '@')))
+
+/* This is how to output a reference to a user-level label named NAME.
+ `assemble_name' uses this. */
+
+#undef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ fputs ((NAME) + (NAME[0] == '@'), FILE)
/* But, to make this work, we have to output the stabs for the function
name *first*... */
"-DPPC -Dunix -D__svr4__ -Asystem(unix) -Asystem(svr4) -Acpu(powerpc) -Amachine(powerpc)"
/* Don't put -Y P,<path> for cross compilers */
-#undef LINK_SPEC
-#ifdef CROSS_COMPILE
-#define LINK_SPEC "\
-%{h*} %{V} %{v:%{!V:-V}} \
-%{b} %{Wl,*:%*} \
-%{static:-dn -Bstatic} \
-%{shared:-G -dy -z text %{!h*:%{o*:-h %*}}} \
-%{symbolic:-Bsymbolic -G -dy -z text %{!h*:%{o*:-h %*}}} \
-%{G:-G} \
-%{YP,*} \
-%{Qy:} %{!Qn:-Qy} \
-%{mlittle: -oformat elf32-powerpcle } %{mlittle-endian: -oformat elf32-powerpcle } \
-%{mbig: -oformat elf32-powerpc } %{mbig-endian: -oformat elf32-powerpc }"
+#undef LINK_PATH_SPEC
+#ifndef CROSS_COMPILE
+#define LINK_PATH_SPEC "\
+%{!nostdlib: %{!YP,*:%{p:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
+%{!p:-Y P,/usr/ccs/lib:/usr/lib}}}"
+
#else
+#define LINK_PATH_SPEC ""
+#endif
+#undef LINK_SPEC
#define LINK_SPEC "\
%{h*} %{V} %{v:%{!V:-V}} \
%{b} %{Wl,*:%*} \
%{symbolic:-Bsymbolic -G -dy -z text %{!h*:%{o*:-h %*}}} \
%{G:-G} \
%{YP,*} \
-%{!nostdlib: %{!YP,*:%{p:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
- %{!p:-Y P,/usr/ccs/lib:/usr/lib}}} \
+%(link_path) %(link_start) \
%{Qy:} %{!Qn:-Qy} \
%{mlittle: -oformat elf32-powerpcle } %{mlittle-endian: -oformat elf32-powerpcle } \
%{mbig: -oformat elf32-powerpc } %{mbig-endian: -oformat elf32-powerpc }"
-#endif /* CROSS_COMPILE */
#undef CPP_SYSV_SPEC
#define CPP_SYSV_SPEC \
`MULTILIB_OPTIONS' are set by default. *Note Target Fragment::. */
#undef MULTILIB_DEFAULTS
-#define MULTILIB_DEFAULTS { "mbig", "mbig-endian", "mcall-sysv" }
+#define MULTILIB_DEFAULTS { "mbig", "mbig-endian", "mcall-sysv", "mno-sdata" }
`MULTILIB_OPTIONS' are set by default. *Note Target Fragment::. */
#undef MULTILIB_DEFAULTS
-#define MULTILIB_DEFAULTS { "mlittle", "mlittle-endian", "mcall-sysv" }
+#define MULTILIB_DEFAULTS { "mlittle", "mlittle-endian", "mcall-sysv", "mno-sdata" }
MULTILIB_OPTIONS = msoft-float \
mlittle/mbig \
- mcall-sysv/mcall-aix/mcall-aixdesc
+ mcall-sysv/mcall-aix # /mcall-aixdesc
MULTILIB_DIRNAMES = soft-float \
little big \
- sysv aix aixdesc
+ sysv aix # aixdesc
MULTILIB_MATCHES = mlittle=mlittle-endian \
mbig=mbig-endian \
msoft-float=mcpu?821 \
msoft-float=mcpu?860
-MULTILIB_EXCEPTIONS = *mlittle/*mcall-aixdesc*
+#MULTILIB_EXCEPTIONS = *mlittle/*mcall-aixdesc*
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
#undef LIB_SPEC
#define LIB_SPEC "%{mwindows:-subsystem:windows -entry:WinMainCRTStartup \
USER32.LIB GDI32.LIB COMDLG32.LIB WINSPOOL.LIB} \
- %{!mwindows:-subsystem:console -entry:mainCRTStartup} \
- %{mcrtmt:LIBCMT.LIB KERNEL32.LIB} %{!mcrtmt:LIBC.LIB KERNEL32.LIB} \
+ %{!mwindows:-subsystem console -e mainCRTStartup} \
+ %{mcrtmt:LIBCMT.LIB KERNEL32.LIB} %{!mcrtmt:-lkernel32 -lcygwin} \
%{v}"
#undef LINK_SPEC
fprintf (FILE, "\t.ualong .."); \
assemble_name (FILE, NAME); \
fprintf (FILE, ",.toc\n"); \
+ \
+ if (lookup_attribute ("dllexport", \
+ TYPE_ATTRIBUTES (TREE_TYPE (DECL)))) \
+ { \
+ fprintf (FILE, "\t.globl __imp_"); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n__imp_"); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, ":\n\t.ulong "); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n"); \
+ } \
+ \
fprintf (FILE, "\t.section .text\n\t.align 2\n.."); \
assemble_name (FILE, NAME); \
fprintf (FILE, ":\n"); \