aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMichael Meissner <meissner@gcc.gnu.org>1997-06-29 16:13:13 +0000
committerMichael Meissner <meissner@gcc.gnu.org>1997-06-29 16:13:13 +0000
commit38c1f2d7e6de970a7345b7d7fabe3952f2f7af89 (patch)
treeba58f6722502142779630876cdbc8b23a4251d91 /gcc
parent8b0c969eb1027fdd6f0290e1c59bde46e1fd4fb1 (diff)
downloadgcc-38c1f2d7e6de970a7345b7d7fabe3952f2f7af89.zip
gcc-38c1f2d7e6de970a7345b7d7fabe3952f2f7af89.tar.gz
gcc-38c1f2d7e6de970a7345b7d7fabe3952f2f7af89.tar.bz2
Fix various problems; Add -m{,no-}fused-madd, -m{,no-}no-update switches; Allow add/and/ior/xor of 32 bit constants
From-SVN: r14361
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/rs6000/rs6000.c342
-rw-r--r--gcc/config/rs6000/rs6000.h195
-rw-r--r--gcc/config/rs6000/rs6000.md251
-rw-r--r--gcc/config/rs6000/sysv4.h60
4 files changed, 532 insertions, 316 deletions
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 8146ce9..60262a9 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -104,6 +104,14 @@ enum rs6000_abi rs6000_current_abi;
int rs6000_fpmem_offset;
int rs6000_fpmem_size;
+/* Debug flags */
+char *rs6000_debug_name;
+int rs6000_debug_stack; /* debug stack applications */
+int rs6000_debug_arg; /* debug argument handling */
+
+/* Flag to say the TOC is initialized */
+int toc_initialized;
+
/* Default register names. */
char rs6000_reg_names[][8] =
@@ -297,6 +305,19 @@ rs6000_override_options (default_cpu)
}
}
+ /* Set debug flags */
+ if (rs6000_debug_name)
+ {
+ if (!strcmp (rs6000_debug_name, "all"))
+ rs6000_debug_stack = rs6000_debug_arg = 1;
+ else if (!strcmp (rs6000_debug_name, "stack"))
+ rs6000_debug_stack = 1;
+ else if (!strcmp (rs6000_debug_name, "arg"))
+ rs6000_debug_arg = 1;
+ else
+ error ("Unknown -mdebug-%s switch", rs6000_debug_name);
+ }
+
#ifdef TARGET_REGNAMES
/* If the user desires alternate register names, copy in the alternate names
now. */
@@ -416,7 +437,8 @@ any_operand (op, mode)
}
/* Returns 1 if op is the count register */
-int count_register_operand(op, mode)
+int
+count_register_operand(op, mode)
register rtx op;
enum machine_mode mode;
{
@@ -434,7 +456,8 @@ int count_register_operand(op, mode)
/* Returns 1 if op is memory location for float/int conversions that masquerades
as a register. */
-int fpmem_operand(op, mode)
+int
+fpmem_operand(op, mode)
register rtx op;
enum machine_mode mode;
{
@@ -576,6 +599,17 @@ got_operand (op, mode)
|| GET_CODE (op) == LABEL_REF);
}
+/* Return 1 if the operand is a simple references that can be loaded via
+ the GOT (labels involving addition aren't allowed). */
+
+int
+got_no_const_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF);
+}
+
/* Return the number of instructions it takes to form a constant in an
integer register. */
@@ -869,8 +903,7 @@ and_operand (op, mode)
register rtx op;
enum machine_mode mode;
{
- return (reg_or_short_operand (op, mode)
- || logical_operand (op, mode)
+ return (logical_operand (op, mode)
|| mask_operand (op, mode));
}
@@ -1009,7 +1042,7 @@ small_data_operand (op, mode)
rtx op;
enum machine_mode mode;
{
-#ifdef TARGET_SDATA
+#if TARGET_ELF
rtx sym_ref, const_part;
if (rs6000_sdata == SDATA_NONE || rs6000_sdata == SDATA_DATA)
@@ -2168,6 +2201,7 @@ rs6000_finalize_pic ()
rtx insn = get_insns ();
rtx reg = NULL_RTX;
rtx first_insn;
+ rtx last_insn = NULL_RTX;
if (GET_CODE (insn) == NOTE)
insn = next_nonnote_insn (insn);
@@ -2186,12 +2220,17 @@ rs6000_finalize_pic ()
GOT_TOC_REGNUM,
&reg);
}
+
+ if (GET_CODE (insn) != NOTE)
+ last_insn = insn;
}
if (reg)
{
rtx init = gen_init_v4_pic (reg);
emit_insn_before (init, first_insn);
+ if (!optimize && last_insn)
+ emit_insn_after (gen_rtx (USE, VOIDmode, reg), last_insn);
}
}
}
@@ -2274,7 +2313,7 @@ rs6000_init_expanders ()
/* Print an operand. Recognize special options, documented below. */
-#ifdef TARGET_SDATA
+#if TARGET_ELF
#define SMALL_DATA_RELOC ((rs6000_sdata == SDATA_EABI) ? "sda21" : "sdarel")
#else
#define SMALL_DATA_RELOC "sda21"
@@ -2875,8 +2914,10 @@ rs6000_makes_calls ()
{
rtx insn;
- /* If we are profiling, we will be making a call to __mcount. */
- if (profile_flag)
+ /* If we are profiling, we will be making a call to __mcount.
+ Under the System V ABI's, we store the LR directly, so
+ we don't need to do it here. */
+ if (DEFAULT_ABI == ABI_AIX && profile_flag)
return 1;
for (insn = get_insns (); insn; insn = next_insn (insn))
@@ -3066,7 +3107,8 @@ rs6000_stack_info ()
/* Determine if we need to save the link register */
- if (regs_ever_live[65] || profile_flag
+ if (regs_ever_live[65]
+ || (DEFAULT_ABI == ABI_AIX && profile_flag)
#ifdef TARGET_RELOCATABLE
|| (TARGET_RELOCATABLE && (get_pool_size () != 0))
#endif
@@ -3336,8 +3378,9 @@ debug_stack_info (info)
a constant pool. */
void
-rs6000_output_load_toc_table (file)
+rs6000_output_load_toc_table (file, reg)
FILE *file;
+ int reg;
{
char buf[256];
@@ -3349,8 +3392,45 @@ rs6000_output_load_toc_table (file)
assemble_name (file, buf);
fprintf (file, "\n");
+ /* possibly create the toc section */
+ if (!toc_initialized)
+ {
+ toc_section ();
+ function_section (current_function_decl);
+ }
+
+ /* If not first call in this function, we need to put the
+ different between .LCTOC1 and the address we get to right
+ after the bl. It will mess up disassembling the instructions
+ but that can't be helped. We will later need to bias the
+ address before loading. */
+ if (rs6000_pic_func_labelno != rs6000_pic_labelno)
+ {
+ char *init_ptr = (TARGET_64BIT) ? ".quad" : ".long";
+ char *buf_ptr;
+
+ ASM_OUTPUT_INTERNAL_LABEL (file, "LCL", rs6000_pic_labelno);
+
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 1);
+ STRIP_NAME_ENCODING (buf_ptr, buf);
+ fprintf (file, "\t%s %s-", init_ptr, buf_ptr);
+
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
+ fprintf (file, "%s\n", buf_ptr);
+ }
+
ASM_OUTPUT_INTERNAL_LABEL (file, "LCF", rs6000_pic_labelno);
- fprintf (file, "\tmflr %s\n", reg_names[30]);
+ fprintf (file, "\tmflr %s\n", reg_names[reg]);
+
+ if (rs6000_pic_func_labelno != rs6000_pic_labelno)
+ {
+ if (TARGET_POWERPC64)
+ fprintf (file, "\taddi %s,%s,8\n", reg_names[reg], reg_names[reg]);
+ else if (TARGET_NEW_MNEMONICS)
+ fprintf (file, "\taddi %s,%s,4\n", reg_names[reg], reg_names[reg]);
+ else
+ fprintf (file, "\tcal %s,4(%s)\n", reg_names[reg], reg_names[reg]);
+ }
if (TARGET_POWERPC64)
fprintf (file, "\tld");
@@ -3360,33 +3440,33 @@ rs6000_output_load_toc_table (file)
fprintf (file, "\tl");
fprintf (file, " %s,(", reg_names[0]);
- ASM_GENERATE_INTERNAL_LABEL (buf, "LCL", rs6000_pic_func_labelno);
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LCL", rs6000_pic_labelno);
assemble_name (file, buf);
fprintf (file, "-");
ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
assemble_name (file, buf);
- fprintf (file, ")(%s)\n", reg_names[30]);
+ fprintf (file, ")(%s)\n", reg_names[reg]);
asm_fprintf (file, "\t{cax|add} %s,%s,%s\n",
- reg_names[30], reg_names[0], reg_names[30]);
+ reg_names[reg], reg_names[0], reg_names[reg]);
rs6000_pic_labelno++;
}
else if (!TARGET_64BIT)
{
ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 1);
- asm_fprintf (file, "\t{cau|addis} %s,%s,", reg_names[30], reg_names[0]);
+ asm_fprintf (file, "\t{cau|addis} %s,%s,", reg_names[reg], reg_names[0]);
assemble_name (file, buf);
asm_fprintf (file, "@ha\n");
if (TARGET_NEW_MNEMONICS)
{
- asm_fprintf (file, "\taddi %s,%s,", reg_names[30], reg_names[30]);
+ asm_fprintf (file, "\taddi %s,%s,", reg_names[reg], reg_names[reg]);
assemble_name (file, buf);
asm_fprintf (file, "@l\n");
}
else
{
- asm_fprintf (file, "\tcal %s,", reg_names[30]);
+ asm_fprintf (file, "\tcal %s,", reg_names[reg]);
assemble_name (file, buf);
- asm_fprintf (file, "@l(%s)\n", reg_names[30]);
+ asm_fprintf (file, "@l(%s)\n", reg_names[reg]);
}
}
else
@@ -3394,12 +3474,68 @@ rs6000_output_load_toc_table (file)
#else /* !USING_SVR4_H */
ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 0);
- asm_fprintf (file, "\t{l|lwz} %s,", reg_names[30]);
+ asm_fprintf (file, "\t{l|lwz} %s,", reg_names[reg]);
assemble_name (file, buf);
asm_fprintf (file, "(%s)\n", reg_names[2]);
#endif /* USING_SVR4_H */
}
+
+/* Emit the correct code for allocating stack space. If COPY_R12, make sure a copy
+ of the old frame is left in r12. */
+
+void
+rs6000_allocate_stack_space (file, size, copy_r12)
+ FILE *file;
+ int size;
+ int copy_r12;
+{
+ int neg_size = -size;
+ if (TARGET_UPDATE)
+ {
+ if (size < 32767)
+ asm_fprintf (file,
+ (TARGET_32BIT) ? "\t{stu|stwu} %s,%d(%s)\n" : "\tstdu %s,%d(%s)\n",
+ reg_names[1], neg_size, reg_names[1]);
+ else
+ {
+ if (copy_r12)
+ fprintf (file, "\tmr %s,%s\n", reg_names[12], reg_names[1]);
+
+ asm_fprintf (file, "\t{liu|lis} %s,%d\n\t{oril|ori} %s,%s,%d\n",
+ reg_names[0], (neg_size >> 16) & 0xffff,
+ reg_names[0], reg_names[0], neg_size & 0xffff);
+ asm_fprintf (file,
+ (TARGET_32BIT) ? "\t{stux|stwux} %s,%s,%s\n" : "\tstdux %s,%s,%s\n",
+ reg_names[1], reg_names[1], reg_names[0]);
+ }
+ }
+ else
+ {
+ fprintf (file, "\tmr %s,%s\n", reg_names[12], reg_names[1]);
+ if (size < 32767)
+ {
+ if (TARGET_NEW_MNEMONICS)
+ fprintf (file, "\taddi %s,%s,%d\n", reg_names[1], reg_names[1], neg_size);
+ else
+ fprintf (file, "\tcal %s,%d(%s)\n", reg_names[1], neg_size, reg_names[1]);
+ }
+ else
+ {
+ asm_fprintf (file, "\t{liu|lis} %s,%d\n\t{oril|ori} %s,%s,%d\n",
+ reg_names[0], (neg_size >> 16) & 0xffff,
+ reg_names[0], reg_names[0], neg_size & 0xffff);
+ asm_fprintf (file, "\t{cax|add} %s,%s,%s\n", reg_names[1],
+ reg_names[0], reg_names[1]);
+ }
+
+ asm_fprintf (file,
+ (TARGET_32BIT) ? "\t{st|stw} %s,0(%s)\n" : "\tstd %s,0(%s)\n",
+ reg_names[12], reg_names[1]);
+ }
+}
+
+
/* Write function prologue. */
void
output_prolog (file, size)
@@ -3458,24 +3594,10 @@ output_prolog (file, size)
if (info->push_p && (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS))
{
if (info->total_size < 32767)
- {
- asm_fprintf (file,
- (TARGET_32BIT) ? "\t{stu|stwu} %s,%d(%s)\n" : "\tstdu %s,%d(%s)\n",
- reg_names[1], - info->total_size, reg_names[1]);
- sp_offset = info->total_size;
- }
+ sp_offset = info->total_size;
else
- {
- int neg_size = - info->total_size;
- sp_reg = 12;
- asm_fprintf (file, "\tmr %s,%s\n", reg_names[12], reg_names[1]);
- asm_fprintf (file, "\t{liu|lis} %s,%d\n\t{oril|ori} %s,%s,%d\n",
- reg_names[0], (neg_size >> 16) & 0xffff,
- reg_names[0], reg_names[0], neg_size & 0xffff);
- asm_fprintf (file,
- (TARGET_32BIT) ? "\t{stux|stwux} %s,%s,%s\n" : "\tstdux %s,%s,%s\n",
- reg_names[1], reg_names[1], reg_names[0]);
- }
+ sp_reg = 12;
+ rs6000_allocate_stack_space (file, info->total_size, sp_reg == 12);
}
/* If we use the link register, get it into r0. */
@@ -3589,24 +3711,9 @@ output_prolog (file, size)
}
}
- /* Update stack and set back pointer and we have already done so for V.4. */
+ /* Update stack and set back pointer unless this is V.4, which was done previously */
if (info->push_p && DEFAULT_ABI != ABI_V4 && DEFAULT_ABI != ABI_SOLARIS)
- {
- if (info->total_size < 32767)
- asm_fprintf (file,
- (TARGET_32BIT) ? "\t{stu|stwu} %s,%d(%s)\n" : "\tstdu %s,%d(%s)\n",
- reg_names[1], - info->total_size, reg_names[1]);
- else
- {
- int neg_size = - info->total_size;
- asm_fprintf (file, "\t{liu|lis} %s,%d\n\t{oril|ori} %s,%s,%d\n",
- reg_names[0], (neg_size >> 16) & 0xffff,
- reg_names[0], reg_names[0], neg_size & 0xffff);
- asm_fprintf (file,
- (TARGET_32BIT) ? "\t{stux|stwux} %s,%s,%s\n" : "\tstdux %s,%s,%s\n",
- reg_names[1], reg_names[1], reg_names[0]);
- }
- }
+ rs6000_allocate_stack_space (file, info->total_size, FALSE);
/* Set frame pointer, if needed. */
if (frame_pointer_needed)
@@ -3671,9 +3778,10 @@ output_prolog (file, size)
if (TARGET_TOC && TARGET_MINIMAL_TOC && get_pool_size () != 0)
{
#ifdef USING_SVR4_H
- rs6000_pic_func_labelno = rs6000_pic_labelno;
+ if (!profile_flag)
+ rs6000_pic_func_labelno = rs6000_pic_labelno;
#endif
- rs6000_output_load_toc_table (file);
+ rs6000_output_load_toc_table (file, 30);
}
if (DEFAULT_ABI == ABI_NT)
@@ -4287,55 +4395,115 @@ output_function_profiler (file, labelno)
int i, j;
char buf[100];
- if (DEFAULT_ABI != ABI_AIX)
- abort ();
-
- /* Set up a TOC entry for the profiler label. */
- toc_section ();
- ASM_OUTPUT_INTERNAL_LABEL (file, "LPC", labelno);
ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
- if (TARGET_MINIMAL_TOC)
- {
- fputs ("\t.long ", file);
- assemble_name (file, buf);
- putc ('\n', file);
- }
- else
+ switch (DEFAULT_ABI)
{
- fputs ("\t.tc\t", file);
- assemble_name (file, buf);
- fputs ("[TC],", file);
- assemble_name (file, buf);
- putc ('\n', file);
- }
- text_section ();
+ default:
+ abort ();
+
+ case ABI_V4:
+ case ABI_SOLARIS:
+ case ABI_AIX_NODESC:
+ fprintf (file, "\tmflr %s\n", reg_names[0]);
+ if (flag_pic == 1)
+ {
+ fprintf (file, "\tbl _GLOBAL_OFFSET_TABLE_@local-4\n");
+ fprintf (file, "\tmflr %s\n", reg_names[11]);
+ fprintf (file, "\t%s %s,", (TARGET_NEW_MNEMONICS) ? "lwz" : "l",
+ reg_names[11]);
+ assemble_name (file, buf);
+ fprintf (file, "@got(%s)\n", reg_names[11]);
+ }
+#if TARGET_ELF
+ else if (flag_pic > 1 || TARGET_RELOCATABLE)
+ {
+ fprintf (file, "\tstw %s,4(%s)\n", reg_names[0], reg_names[1]);
+ fprintf (file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP);
+ assemble_name (file, buf);
+ fprintf (file, "X = .-.LCTOC1\n");
+ fprintf (file, "\t.long ");
+ assemble_name (file, buf);
+ fputs ("\n\t.previous\n", file);
+ rs6000_pic_func_labelno = rs6000_pic_labelno;
+ rs6000_output_load_toc_table (file, 11);
+ fprintf (file, "\t%s %s,", (TARGET_NEW_MNEMONICS) ? "lwz" : "l",
+ reg_names[11]);
+ assemble_name (file, buf);
+ fprintf (file, "X(%s)\n", reg_names[11]);
+ }
+#endif
+ else if (TARGET_NEW_MNEMONICS)
+ {
+ fprintf (file, "\taddis %s,%s,", reg_names[11], reg_names[11]);
+ assemble_name (file, buf);
+ fprintf (file, "@ha\n");
+ fprintf (file, "\tstw %s,4(%s)\n", reg_names[0], reg_names[1]);
+ fprintf (file, "\taddi %s,%s,", reg_names[11], reg_names[11]);
+ assemble_name (file, buf);
+ fputs ("@l\n", file);
+ }
+ else
+ {
+ fprintf (file, "\tcau %s,%s,", reg_names[11], reg_names[11]);
+ assemble_name (file, buf);
+ fprintf (file, "@ha\n");
+ fprintf (file, "\tst %s,4(%s)\n", reg_names[0], reg_names[1]);
+ fprintf (file, "\tcal %s,", reg_names[11]);
+ assemble_name (file, buf);
+ fprintf (file, "@l(%s)\n", reg_names[11]);
+ }
+
+ fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
+ break;
+
+ case ABI_AIX:
+ /* Set up a TOC entry for the profiler label. */
+ toc_section ();
+ ASM_OUTPUT_INTERNAL_LABEL (file, "LPC", labelno);
+ if (TARGET_MINIMAL_TOC)
+ {
+ fputs ("\t.long ", file);
+ assemble_name (file, buf);
+ putc ('\n', file);
+ }
+ else
+ {
+ fputs ("\t.tc\t", file);
+ assemble_name (file, buf);
+ fputs ("[TC],", file);
+ assemble_name (file, buf);
+ putc ('\n', file);
+ }
+ text_section ();
/* Figure out last used parameter register. The proper thing to do is
to walk incoming args of the function. A function might have live
parameter registers even if it has no incoming args. */
- for (last_parm_reg = 10;
- last_parm_reg > 2 && ! regs_ever_live [last_parm_reg];
- last_parm_reg--)
- ;
+ for (last_parm_reg = 10;
+ last_parm_reg > 2 && ! regs_ever_live [last_parm_reg];
+ last_parm_reg--)
+ ;
/* Save parameter registers in regs 23-30. Don't overwrite reg 31, since
it might be set up as the frame pointer. */
- for (i = 3, j = 30; i <= last_parm_reg; i++, j--)
- asm_fprintf (file, "\tmr %d,%d\n", j, i);
+ for (i = 3, j = 30; i <= last_parm_reg; i++, j--)
+ asm_fprintf (file, "\tmr %d,%d\n", j, i);
/* Load location address into r3, and call mcount. */
- ASM_GENERATE_INTERNAL_LABEL (buf, "LPC", labelno);
- asm_fprintf (file, "\t{l|lwz} %s,", reg_names[3]);
- assemble_name (file, buf);
- asm_fprintf (file, "(%s)\n\tbl %s\n", reg_names[2], RS6000_MCOUNT);
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LPC", labelno);
+ asm_fprintf (file, "\t{l|lwz} %s,", reg_names[3]);
+ assemble_name (file, buf);
+ asm_fprintf (file, "(%s)\n\tbl %s\n", reg_names[2], RS6000_MCOUNT);
/* Restore parameter registers. */
- for (i = 3, j = 30; i <= last_parm_reg; i++, j--)
- asm_fprintf (file, "\tmr %d,%d\n", i, j);
+ for (i = 3, j = 30; i <= last_parm_reg; i++, j--)
+ asm_fprintf (file, "\tmr %d,%d\n", i, j);
+ break;
+ }
}
/* Adjust the cost of a scheduling dependency. Return the new cost of
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index f469061..60b4c52 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -208,33 +208,33 @@ Boston, MA 02111-1307, USA. */
extern int target_flags;
/* Use POWER architecture instructions and MQ register. */
-#define MASK_POWER 0x01
+#define MASK_POWER 0x00000001
/* Use POWER2 extensions to POWER architecture. */
-#define MASK_POWER2 0x02
+#define MASK_POWER2 0x00000002
/* Use PowerPC architecture instructions. */
-#define MASK_POWERPC 0x04
+#define MASK_POWERPC 0x00000004
/* Use PowerPC General Purpose group optional instructions, e.g. fsqrt. */
-#define MASK_PPC_GPOPT 0x08
+#define MASK_PPC_GPOPT 0x00000008
/* Use PowerPC Graphics group optional instructions, e.g. fsel. */
-#define MASK_PPC_GFXOPT 0x10
+#define MASK_PPC_GFXOPT 0x00000010
/* Use PowerPC-64 architecture instructions. */
-#define MASK_POWERPC64 0x20
+#define MASK_POWERPC64 0x00000020
/* Use revised mnemonic names defined for PowerPC architecture. */
-#define MASK_NEW_MNEMONICS 0x40
+#define MASK_NEW_MNEMONICS 0x00000040
/* Disable placing fp constants in the TOC; can be turned on when the
TOC overflows. */
-#define MASK_NO_FP_IN_TOC 0x80
+#define MASK_NO_FP_IN_TOC 0x00000080
/* Disable placing symbol+offset constants in the TOC; can be turned on when
the TOC overflows. */
-#define MASK_NO_SUM_IN_TOC 0x100
+#define MASK_NO_SUM_IN_TOC 0x00000100
/* Output only one TOC entry per module. Normally linking fails if
there are more than 16K unique variables/constants in an executable. With
@@ -243,25 +243,27 @@ extern int target_flags;
This is at the cost of having 2 extra loads and one extra store per
function, and one less allocatable register. */
-#define MASK_MINIMAL_TOC 0x200
+#define MASK_MINIMAL_TOC 0x00000200
/* Nonzero for the 64bit model: ints, longs, and pointers are 64 bits. */
-#define MASK_64BIT 0x400
+#define MASK_64BIT 0x00000400
/* Disable use of FPRs. */
-#define MASK_SOFT_FLOAT 0x800
+#define MASK_SOFT_FLOAT 0x00000800
/* Enable load/store multiple, even on powerpc */
-#define MASK_MULTIPLE 0x1000
-#define MASK_MULTIPLE_SET 0x2000
+#define MASK_MULTIPLE 0x00001000
+#define MASK_MULTIPLE_SET 0x00002000
/* Use string instructions for block moves */
-#define MASK_STRING 0x4000
-#define MASK_STRING_SET 0x8000
+#define MASK_STRING 0x00004000
+#define MASK_STRING_SET 0x00008000
-/* Temporary debug switches */
-#define MASK_DEBUG_STACK 0x10000
-#define MASK_DEBUG_ARG 0x20000
+/* Disable update form of load/store */
+#define MASK_NO_UPDATE 0x00010000
+
+/* Disable fused multiply/add operations */
+#define MASK_NO_FUSED_MADD 0x00020000
#define TARGET_POWER (target_flags & MASK_POWER)
#define TARGET_POWER2 (target_flags & MASK_POWER2)
@@ -279,11 +281,13 @@ extern int target_flags;
#define TARGET_MULTIPLE_SET (target_flags & MASK_MULTIPLE_SET)
#define TARGET_STRING (target_flags & MASK_STRING)
#define TARGET_STRING_SET (target_flags & MASK_STRING_SET)
-#define TARGET_DEBUG_STACK (target_flags & MASK_DEBUG_STACK)
-#define TARGET_DEBUG_ARG (target_flags & MASK_DEBUG_ARG)
+#define TARGET_NO_UPDATE (target_flags & MASK_NO_UPDATE)
+#define TARGET_NO_FUSED_MADD (target_flags & MASK_NO_FUSED_MADD)
#define TARGET_32BIT (! TARGET_64BIT)
#define TARGET_HARD_FLOAT (! TARGET_SOFT_FLOAT)
+#define TARGET_UPDATE (! TARGET_NO_UPDATE)
+#define TARGET_FUSED_MADD (! TARGET_NO_FUSED_MADD)
/* Pseudo target to indicate whether the object format is ELF
(to get around not having conditional compilation in the md file) */
@@ -366,8 +370,10 @@ extern int target_flags;
{"string", MASK_STRING | MASK_STRING_SET}, \
{"no-string", - MASK_STRING}, \
{"no-string", MASK_STRING_SET}, \
- {"debug-stack", MASK_DEBUG_STACK}, \
- {"debug-arg", MASK_DEBUG_ARG}, \
+ {"update", - MASK_NO_UPDATE}, \
+ {"no-update", MASK_NO_UPDATE}, \
+ {"fused-madd", - MASK_NO_FUSED_MADD}, \
+ {"no-fused-madd", MASK_NO_FUSED_MADD}, \
SUBTARGET_SWITCHES \
{"", TARGET_DEFAULT}}
@@ -427,6 +433,8 @@ extern enum processor_type rs6000_cpu;
{ \
{"cpu=", &rs6000_select[1].string}, \
{"tune=", &rs6000_select[2].string}, \
+ {"debug-", &rs6000_debug_name}, \
+ {"debug=", &rs6000_debug_name}, \
SUBTARGET_OPTIONS \
}
@@ -441,6 +449,14 @@ struct rs6000_cpu_select
extern struct rs6000_cpu_select rs6000_select[];
+/* Debug support */
+extern char *rs6000_debug_name; /* Name for -mdebug-xxxx option */
+extern int rs6000_debug_stack; /* debug stack applications */
+extern int rs6000_debug_arg; /* debug argument handling */
+
+#define TARGET_DEBUG_STACK rs6000_debug_stack
+#define TARGET_DEBUG_ARG rs6000_debug_arg
+
/* Sometimes certain combinations of command options do not make sense
on a particular target machine. You can define a macro
`OVERRIDE_OPTIONS' to take account of this. This macro, if
@@ -1811,6 +1827,7 @@ typedef struct rs6000_args
{ if (LEGITIMATE_INDIRECT_ADDRESS_P (X)) \
goto ADDR; \
if ((GET_CODE (X) == PRE_INC || GET_CODE (X) == PRE_DEC) \
+ && TARGET_UPDATE \
&& LEGITIMATE_INDIRECT_ADDRESS_P (XEXP (X, 0))) \
goto ADDR; \
if (LEGITIMATE_SMALL_DATA_P (MODE, X)) \
@@ -1904,9 +1921,9 @@ typedef struct rs6000_args
&& ! LEGITIMATE_ADDRESS_INTEGER_P (XEXP (ADDR, 1), \
(TARGET_32BIT ? 4 : 8))) \
goto LABEL; \
- if (GET_CODE (ADDR) == PRE_INC) \
+ if (TARGET_UPDATE && GET_CODE (ADDR) == PRE_INC) \
goto LABEL; \
- if (GET_CODE (ADDR) == PRE_DEC) \
+ if (TARGET_UPDATE && GET_CODE (ADDR) == PRE_DEC) \
goto LABEL; \
if (GET_CODE (ADDR) == LO_SUM) \
goto LABEL; \
@@ -2096,59 +2113,74 @@ typedef struct rs6000_args
/* Provide the costs of a rtl expression. This is in the body of a
switch on CODE. */
-#define RTX_COSTS(X,CODE,OUTER_CODE) \
- case MULT: \
- switch (rs6000_cpu) \
- { \
- case PROCESSOR_RIOS1: \
- return (GET_CODE (XEXP (X, 1)) != CONST_INT \
- ? COSTS_N_INSNS (5) \
- : INTVAL (XEXP (X, 1)) >= -256 && INTVAL (XEXP (X, 1)) <= 255 \
- ? COSTS_N_INSNS (3) : COSTS_N_INSNS (4)); \
- case PROCESSOR_RIOS2: \
- case PROCESSOR_MPCCORE: \
- return COSTS_N_INSNS (2); \
- case PROCESSOR_PPC601: \
- return COSTS_N_INSNS (5); \
- case PROCESSOR_PPC603: \
- return (GET_CODE (XEXP (X, 1)) != CONST_INT \
- ? COSTS_N_INSNS (5) \
- : INTVAL (XEXP (X, 1)) >= -256 && INTVAL (XEXP (X, 1)) <= 255 \
- ? COSTS_N_INSNS (2) : COSTS_N_INSNS (3)); \
- case PROCESSOR_PPC403: \
- case PROCESSOR_PPC604: \
- case PROCESSOR_PPC620: \
- return COSTS_N_INSNS (4); \
- } \
- case DIV: \
- case MOD: \
- if (GET_CODE (XEXP (X, 1)) == CONST_INT \
- && exact_log2 (INTVAL (XEXP (X, 1))) >= 0) \
- return COSTS_N_INSNS (2); \
- /* otherwise fall through to normal divide. */ \
- case UDIV: \
- case UMOD: \
- switch (rs6000_cpu) \
- { \
- case PROCESSOR_RIOS1: \
- return COSTS_N_INSNS (19); \
- case PROCESSOR_RIOS2: \
- return COSTS_N_INSNS (13); \
- case PROCESSOR_MPCCORE: \
- return COSTS_N_INSNS (6); \
- case PROCESSOR_PPC403: \
- return COSTS_N_INSNS (33); \
- case PROCESSOR_PPC601: \
- return COSTS_N_INSNS (36); \
- case PROCESSOR_PPC603: \
- return COSTS_N_INSNS (37); \
- case PROCESSOR_PPC604: \
- case PROCESSOR_PPC620: \
- return COSTS_N_INSNS (20); \
- } \
- case FFS: \
- return COSTS_N_INSNS (4); \
- case MEM: \
+#define RTX_COSTS(X,CODE,OUTER_CODE) \
+ case PLUS: \
+ return ((GET_CODE (XEXP (X, 1)) == CONST_INT \
+ && (unsigned HOST_WIDE_INT) ((INTVAL (XEXP (X, 1)) \
+ + 0x8000) >= 0x10000)) \
+ ? COSTS_N_INSNS (2) \
+ : COSTS_N_INSNS (1)); \
+ case AND: \
+ return ((non_and_cint_operand (XEXP (X, 1), SImode)) \
+ ? COSTS_N_INSNS (2) \
+ : COSTS_N_INSNS (1)); \
+ case IOR: \
+ case XOR: \
+ return ((non_logical_cint_operand (XEXP (X, 1), SImode)) \
+ ? COSTS_N_INSNS (2) \
+ : COSTS_N_INSNS (1)); \
+ case MULT: \
+ switch (rs6000_cpu) \
+ { \
+ case PROCESSOR_RIOS1: \
+ return (GET_CODE (XEXP (X, 1)) != CONST_INT \
+ ? COSTS_N_INSNS (5) \
+ : INTVAL (XEXP (X, 1)) >= -256 && INTVAL (XEXP (X, 1)) <= 255 \
+ ? COSTS_N_INSNS (3) : COSTS_N_INSNS (4)); \
+ case PROCESSOR_RIOS2: \
+ case PROCESSOR_MPCCORE: \
+ return COSTS_N_INSNS (2); \
+ case PROCESSOR_PPC601: \
+ return COSTS_N_INSNS (5); \
+ case PROCESSOR_PPC603: \
+ return (GET_CODE (XEXP (X, 1)) != CONST_INT \
+ ? COSTS_N_INSNS (5) \
+ : INTVAL (XEXP (X, 1)) >= -256 && INTVAL (XEXP (X, 1)) <= 255 \
+ ? COSTS_N_INSNS (2) : COSTS_N_INSNS (3)); \
+ case PROCESSOR_PPC403: \
+ case PROCESSOR_PPC604: \
+ case PROCESSOR_PPC620: \
+ return COSTS_N_INSNS (4); \
+ } \
+ case DIV: \
+ case MOD: \
+ if (GET_CODE (XEXP (X, 1)) == CONST_INT \
+ && exact_log2 (INTVAL (XEXP (X, 1))) >= 0) \
+ return COSTS_N_INSNS (2); \
+ /* otherwise fall through to normal divide. */ \
+ case UDIV: \
+ case UMOD: \
+ switch (rs6000_cpu) \
+ { \
+ case PROCESSOR_RIOS1: \
+ return COSTS_N_INSNS (19); \
+ case PROCESSOR_RIOS2: \
+ return COSTS_N_INSNS (13); \
+ case PROCESSOR_MPCCORE: \
+ return COSTS_N_INSNS (6); \
+ case PROCESSOR_PPC403: \
+ return COSTS_N_INSNS (33); \
+ case PROCESSOR_PPC601: \
+ return COSTS_N_INSNS (36); \
+ case PROCESSOR_PPC603: \
+ return COSTS_N_INSNS (37); \
+ case PROCESSOR_PPC604: \
+ case PROCESSOR_PPC620: \
+ return COSTS_N_INSNS (20); \
+ } \
+ case FFS: \
+ return COSTS_N_INSNS (4); \
+ case MEM: \
/* MEM should be slightly more expensive than (plus (reg) (const)) */ \
return 5;
@@ -2373,8 +2405,6 @@ toc_section () \
{ \
if (TARGET_MINIMAL_TOC) \
{ \
- static int toc_initialized = 0; \
- \
/* 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. */ \
@@ -2396,6 +2426,9 @@ toc_section () \
in_section = toc; \
}
+/* Flag to say the TOC is initialized */
+extern int toc_initialized;
+
/* 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.
@@ -2998,6 +3031,7 @@ do { \
{"reg_or_u_short_operand", {SUBREG, REG, CONST_INT}}, \
{"reg_or_cint_operand", {SUBREG, REG, CONST_INT}}, \
{"got_operand", {SYMBOL_REF, CONST, LABEL_REF}}, \
+ {"got_no_const_operand", {SYMBOL_REF, LABEL_REF}}, \
{"easy_fp_constant", {CONST_DOUBLE}}, \
{"reg_or_mem_operand", {SUBREG, MEM, REG}}, \
{"lwa_operand", {SUBREG, MEM, REG}}, \
@@ -3058,6 +3092,7 @@ extern int reg_or_neg_short_operand ();
extern int reg_or_u_short_operand ();
extern int reg_or_cint_operand ();
extern int got_operand ();
+extern int got_no_const_operand ();
extern int num_insns_constant ();
extern int easy_fp_constant ();
extern int volatile_mem_operand ();
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index fc1323a..0e6e259 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -859,15 +859,17 @@
;; Discourage ai/addic because of carry but provide it in an alternative
;; allowing register zero as source.
(define_insn "addsi3"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,?r,r")
- (plus:SI (match_operand:SI 1 "gpc_reg_operand" "%r,b,r,b")
- (match_operand:SI 2 "add_operand" "r,I,I,J")))]
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,?r,r,r")
+ (plus:SI (match_operand:SI 1 "gpc_reg_operand" "%r,b,r,b,b")
+ (match_operand:SI 2 "reg_or_cint_operand" "r,I,I,J,n")))]
""
"@
{cax|add} %0,%1,%2
{cal %0,%2(%1)|addi %0,%1,%2}
{ai|addic} %0,%1,%2
- {cau|addis} %0,%1,%v2")
+ {cau|addis} %0,%1,%v2
+ #"
+ [(set_attr "length" "4,4,4,4,8")])
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x")
@@ -1646,16 +1648,18 @@
[(set_attr "type" "idiv")])
(define_insn "andsi3"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
- (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r")
- (match_operand:SI 2 "and_operand" "?r,L,K,J")))
- (clobber (match_scratch:CC 3 "=X,X,x,x"))]
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r,r")
+ (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r")
+ (match_operand:SI 2 "reg_or_cint_operand" "?r,L,K,J,n")))
+ (clobber (match_scratch:CC 3 "=X,X,x,x,x"))]
""
"@
and %0,%1,%2
{rlinm|rlwinm} %0,%1,0,%m2,%M2
{andil.|andi.} %0,%1,%b2
- {andiu.|andis.} %0,%1,%u2")
+ {andiu.|andis.} %0,%1,%u2
+ #"
+ [(set_attr "length" "4,4,4,4,8")])
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x")
@@ -1687,54 +1691,37 @@
[(set_attr "type" "compare,compare,compare,delayed_compare")])
;; Take a AND with a constant that cannot be done in a single insn and try to
-;; split it into two insns. This does not verify that the insns are valid
-;; since this need not be done as combine will do it.
+;; split it into two insns.
(define_split
[(set (match_operand:SI 0 "gpc_reg_operand" "")
(and:SI (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "non_and_cint_operand" "")))]
- ""
- [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 3)))
- (set (match_dup 0) (and:SI (match_dup 0) (match_dup 4)))]
+ (match_operand:SI 2 "non_and_cint_operand" "")))
+ (clobber (match_scratch:CC 3 ""))]
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 4))) (clobber (match_dup 6))])
+ (parallel [(set (match_dup 0) (and:SI (match_dup 0) (match_dup 5))) (clobber (match_dup 7))])]
"
{
- int maskval = INTVAL (operands[2]);
- int i, transitions, last_bit_value;
- int orig = maskval, first_c = maskval, second_c;
-
- /* We know that MASKVAL must have more than 2 bit-transitions. Start at
- the low-order bit and count for the third transition. When we get there,
- make a first mask that has everything to the left of that position
- a one. Then make the second mask to turn off whatever else is needed. */
-
- for (i = 1, transitions = 0, last_bit_value = maskval & 1; i < 32; i++)
- {
- if (((maskval >>= 1) & 1) != last_bit_value)
- last_bit_value ^= 1, transitions++;
-
- if (transitions > 2)
- {
- first_c |= (~0) << i;
- break;
- }
- }
-
- second_c = orig | ~ first_c;
-
- operands[3] = gen_rtx (CONST_INT, VOIDmode, first_c);
- operands[4] = gen_rtx (CONST_INT, VOIDmode, second_c);
+ operands[4] = GEN_INT (INTVAL (operands[2]) & 0xffff0000);
+ operands[5] = GEN_INT (INTVAL (operands[2]) & 0x0000ffff);
+ operands[6] = ((mask_constant (INTVAL (operands[4])))
+ ? gen_rtx (SCRATCH, CCmode)
+ : operands[3]);
+ operands[7] = operands[3];
}")
(define_insn "iorsi3"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r")
- (ior:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r")
- (match_operand:SI 2 "logical_operand" "r,K,J")))]
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
+ (ior:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r")
+ (match_operand:SI 2 "reg_or_cint_operand" "r,K,J,n")))]
""
"@
or %0,%1,%2
{oril|ori} %0,%1,%b2
- {oriu|oris} %0,%1,%u2")
+ {oriu|oris} %0,%1,%u2
+ #"
+ [(set_attr "length" "4,4,4,8")])
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x")
@@ -1758,7 +1745,7 @@
[(set_attr "type" "compare")])
;; Split an IOR that we can't do in one insn into two insns, each of which
-;; does one 16-bit part. This is used by combine.
+;; does one 16-bit part.
(define_split
[(set (match_operand:SI 0 "gpc_reg_operand" "")
@@ -1769,20 +1756,21 @@
(set (match_dup 0) (ior:SI (match_dup 0) (match_dup 4)))]
"
{
- operands[3] = gen_rtx (CONST_INT, VOIDmode,
- INTVAL (operands[2]) & 0xffff0000);
- operands[4] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff);
+ operands[3] = GEN_INT (INTVAL (operands[2]) & 0xffff0000);
+ operands[4] = GEN_INT (INTVAL (operands[2]) & 0x0000ffff);
}")
(define_insn "xorsi3"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r")
- (xor:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r")
- (match_operand:SI 2 "logical_operand" "r,K,J")))]
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
+ (xor:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r")
+ (match_operand:SI 2 "reg_or_cint_operand" "r,K,J,n")))]
""
"@
xor %0,%1,%2
{xoril|xori} %0,%1,%b2
- {xoriu|xoris} %0,%1,%u2")
+ {xoriu|xoris} %0,%1,%u2
+ #"
+ [(set_attr "length" "4,4,4,8")])
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x")
@@ -1806,7 +1794,7 @@
[(set_attr "type" "compare")])
;; Split an XOR that we can't do in one insn into two insns, each of which
-;; does one 16-bit part. This is used by combine.
+;; does one 16-bit part.
(define_split
[(set (match_operand:SI 0 "gpc_reg_operand" "")
@@ -1817,9 +1805,8 @@
(set (match_dup 0) (xor:SI (match_dup 0) (match_dup 4)))]
"
{
- operands[3] = gen_rtx (CONST_INT, VOIDmode,
- INTVAL (operands[2]) & 0xffff0000);
- operands[4] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff);
+ operands[3] = GEN_INT (INTVAL (operands[2]) & 0xffff0000);
+ operands[4] = GEN_INT (INTVAL (operands[2]) & 0x0000ffff);
}")
(define_insn ""
@@ -3058,7 +3045,7 @@
(plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
(match_operand:SF 3 "gpc_reg_operand" "f")))]
- "TARGET_POWERPC && TARGET_HARD_FLOAT"
+ "TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
"fmadds %0,%1,%2,%3"
[(set_attr "type" "fp")])
@@ -3067,7 +3054,7 @@
(plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
(match_operand:SF 3 "gpc_reg_operand" "f")))]
- "! TARGET_POWERPC && TARGET_HARD_FLOAT"
+ "! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
"{fma|fmadd} %0,%1,%2,%3"
[(set_attr "type" "dmul")])
@@ -3076,7 +3063,7 @@
(minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
(match_operand:SF 3 "gpc_reg_operand" "f")))]
- "TARGET_POWERPC && TARGET_HARD_FLOAT"
+ "TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
"fmsubs %0,%1,%2,%3"
[(set_attr "type" "fp")])
@@ -3085,7 +3072,7 @@
(minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
(match_operand:SF 3 "gpc_reg_operand" "f")))]
- "! TARGET_POWERPC && TARGET_HARD_FLOAT"
+ "! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
"{fms|fmsub} %0,%1,%2,%3"
[(set_attr "type" "dmul")])
@@ -3094,7 +3081,7 @@
(neg:SF (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
(match_operand:SF 3 "gpc_reg_operand" "f"))))]
- "TARGET_POWERPC && TARGET_HARD_FLOAT"
+ "TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
"fnmadds %0,%1,%2,%3"
[(set_attr "type" "fp")])
@@ -3103,7 +3090,7 @@
(neg:SF (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
(match_operand:SF 3 "gpc_reg_operand" "f"))))]
- "! TARGET_POWERPC && TARGET_HARD_FLOAT"
+ "! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
"{fnma|fnmadd} %0,%1,%2,%3"
[(set_attr "type" "dmul")])
@@ -3112,7 +3099,7 @@
(neg:SF (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
(match_operand:SF 3 "gpc_reg_operand" "f"))))]
- "TARGET_POWERPC && TARGET_HARD_FLOAT"
+ "TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
"fnmsubs %0,%1,%2,%3"
[(set_attr "type" "fp")])
@@ -3121,7 +3108,7 @@
(neg:SF (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
(match_operand:SF 3 "gpc_reg_operand" "f"))))]
- "! TARGET_POWERPC && TARGET_HARD_FLOAT"
+ "! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
"{fnms|fnmsub} %0,%1,%2,%3"
[(set_attr "type" "dmul")])
@@ -5039,12 +5026,30 @@
"(DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS) && flag_pic == 1"
"
{
+ if (GET_CODE (operands[1]) == CONST)
+ {
+ rtx offset = const0_rtx;
+ HOST_WIDE_INT value;
+
+ operands[1] = eliminate_constant_term (XEXP (operands[1], 0), &offset);
+ value = INTVAL (offset);
+ if (value != 0)
+ {
+ rtx tmp = ((reload_in_progress || reload_completed)
+ ? operands[0]
+ : gen_reg_rtx (Pmode));
+ emit_insn (gen_movsi_got (tmp, operands[1]));
+ emit_insn (gen_addsi3 (operands[0], tmp, offset));
+ DONE;
+ }
+ }
+
operands[2] = rs6000_got_register (operands[1]);
}")
(define_insn "*movsi_got_internal"
[(set (match_operand:SI 0 "register_operand" "=r")
- (unspec [(match_operand:SI 1 "got_operand" "")
+ (unspec [(match_operand:SI 1 "got_no_const_operand" "")
(match_operand:SI 2 "register_operand" "b")] 8))]
"(DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS) && flag_pic == 1"
"{l|lwz} %0,%a1@got(%2)"
@@ -5132,24 +5137,7 @@
emit_insn (gen_movsi (tmp1, sym));
if (INTVAL (const_term) != 0)
- {
- if (value + 0x8000 < 0x10000)
- emit_insn (gen_addsi3 (operands[0], tmp1, GEN_INT (value)));
-
- else
- {
- HOST_WIDE_INT high_int = value & (~ (HOST_WIDE_INT) 0xffff);
- HOST_WIDE_INT low_int = value & 0xffff;
- rtx tmp2 = (!new_reg_p || !low_int) ? operands[0] : gen_reg_rtx (Pmode);
-
- if (low_int & 0x8000)
- high_int += 0x10000, low_int |= ((HOST_WIDE_INT) -1) << 16;
-
- emit_insn (gen_addsi3 (tmp2, tmp1, GEN_INT (high_int)));
- if (low_int)
- emit_insn (gen_addsi3 (operands[0], tmp2, GEN_INT (low_int)));
- }
- }
+ emit_insn (gen_addsi3 (operands[0], tmp1, GEN_INT (value)));
DONE;
}
else
@@ -6745,19 +6733,19 @@
;; tie and these are the pair most likely to be tieable (and the ones
;; that will benefit the most).
-(define_insn ""
+(define_insn "*movdi_update1"
[(set (match_operand:DI 3 "gpc_reg_operand" "=r,r")
(mem:DI (plus:DI (match_operand:DI 1 "gpc_reg_operand" "0,0")
(match_operand:DI 2 "reg_or_short_operand" "r,I"))))
(set (match_operand:DI 0 "gpc_reg_operand" "=b,b")
(plus:DI (match_dup 1) (match_dup 2)))]
- "TARGET_POWERPC64"
+ "TARGET_POWERPC64 && TARGET_UPDATE"
"@
ldux %3,%0,%2
ldu %3,%2(%0)"
[(set_attr "type" "load")])
-(define_insn ""
+(define_insn "*movdi_update2"
[(set (match_operand:DI 3 "gpc_reg_operand" "=r")
(sign_extend:DI
(mem:SI (plus:DI (match_operand:DI 1 "gpc_reg_operand" "0")
@@ -6774,13 +6762,13 @@
(match_operand:DI 3 "gpc_reg_operand" "r,r"))
(set (match_operand:DI 0 "gpc_reg_operand" "=b,b")
(plus:DI (match_dup 1) (match_dup 2)))]
- "TARGET_POWERPC64"
+ "TARGET_POWERPC64 && TARGET_UPDATE"
"@
stdux %3,%0,%2
stdu %3,%2(%0)"
[(set_attr "type" "store")])
-(define_insn ""
+(define_insn "*movsi_update1"
[(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
(mem:SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
(match_operand:SI 2 "reg_or_short_operand" "r,I"))))
@@ -6798,142 +6786,166 @@
(match_operand:SI 3 "gpc_reg_operand" "r,r"))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- ""
+ "TARGET_UPDATE"
"@
{stux|stwux} %3,%0,%2
{stu|stwu} %3,%2(%0)"
[(set_attr "type" "store")])
-(define_insn ""
+(define_insn "*movhi_update"
[(set (match_operand:HI 3 "gpc_reg_operand" "=r,r")
(mem:HI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
(match_operand:SI 2 "reg_or_short_operand" "r,I"))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- ""
+ "TARGET_UPDATE"
"@
lhzux %3,%0,%2
lhzu %3,%2(%0)"
[(set_attr "type" "load")])
-(define_insn ""
+(define_insn "*movhi_update2"
[(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
(zero_extend:SI
(mem:HI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
(match_operand:SI 2 "reg_or_short_operand" "r,I")))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- ""
+ "TARGET_UPDATE"
"@
lhzux %3,%0,%2
lhzu %3,%2(%0)"
[(set_attr "type" "load")])
-(define_insn ""
+(define_insn "*movhi_update3"
[(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
(sign_extend:SI
(mem:HI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
(match_operand:SI 2 "reg_or_short_operand" "r,I")))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- ""
+ "TARGET_UPDATE"
"@
lhaux %3,%0,%2
lhau %3,%2(%0)"
[(set_attr "type" "load")])
-(define_insn ""
+(define_insn "*movhi_update4"
[(set (mem:HI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
(match_operand:SI 2 "reg_or_short_operand" "r,I")))
(match_operand:HI 3 "gpc_reg_operand" "r,r"))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- ""
+ "TARGET_UPDATE"
"@
sthux %3,%0,%2
sthu %3,%2(%0)"
[(set_attr "type" "store")])
-(define_insn ""
+(define_insn "*movqi_update1"
[(set (match_operand:QI 3 "gpc_reg_operand" "=r,r")
(mem:QI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
(match_operand:SI 2 "reg_or_short_operand" "r,I"))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- ""
+ "TARGET_UPDATE"
"@
lbzux %3,%0,%2
lbzu %3,%2(%0)"
[(set_attr "type" "load")])
-(define_insn ""
+(define_insn "*movqi_update2"
[(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
(zero_extend:SI
(mem:QI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
(match_operand:SI 2 "reg_or_short_operand" "r,I")))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- ""
+ "TARGET_UPDATE"
"@
lbzux %3,%0,%2
lbzu %3,%2(%0)"
[(set_attr "type" "load")])
-(define_insn ""
+(define_insn "*movqi_update3"
[(set (mem:QI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
(match_operand:SI 2 "reg_or_short_operand" "r,I")))
(match_operand:QI 3 "gpc_reg_operand" "r,r"))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- ""
+ "TARGET_UPDATE"
"@
stbux %3,%0,%2
stbu %3,%2(%0)"
[(set_attr "type" "store")])
-(define_insn ""
+(define_insn "*movsf_update1"
[(set (match_operand:SF 3 "gpc_reg_operand" "=f,f")
(mem:SF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
(match_operand:SI 2 "reg_or_short_operand" "r,I"))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_UPDATE"
"@
lfsux %3,%0,%2
lfsu %3,%2(%0)"
[(set_attr "type" "fpload")])
-(define_insn ""
+(define_insn "*movsf_update2"
[(set (mem:SF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
(match_operand:SI 2 "reg_or_short_operand" "r,I")))
(match_operand:SF 3 "gpc_reg_operand" "f,f"))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_UPDATE"
"@
stfsux %3,%0,%2
stfsu %3,%2(%0)"
[(set_attr "type" "fpstore")])
-(define_insn ""
+(define_insn "*movsf_update3"
+ [(set (match_operand:SF 3 "gpc_reg_operand" "=r,r")
+ (mem:SF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
+ (match_operand:SI 2 "reg_or_short_operand" "r,I"))))
+ (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
+ (plus:SI (match_dup 1) (match_dup 2)))]
+ "TARGET_SOFT_FLOAT && TARGET_UPDATE"
+ "@
+ {lux|lwzux} %3,%0,%2
+ {lu|lwzu} %3,%2(%0)"
+ [(set_attr "type" "load")])
+
+(define_insn "*movsf_update4"
+ [(set (mem:SF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
+ (match_operand:SI 2 "reg_or_short_operand" "r,I")))
+ (match_operand:SF 3 "gpc_reg_operand" "r,r"))
+ (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
+ (plus:SI (match_dup 1) (match_dup 2)))]
+ "TARGET_SOFT_FLOAT && TARGET_UPDATE"
+ "@
+ {stux|stwux} %3,%0,%2
+ {stu|stwu} %3,%2(%0)"
+ [(set_attr "type" "store")])
+
+(define_insn "*movdf_update1"
[(set (match_operand:DF 3 "gpc_reg_operand" "=f,f")
(mem:DF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
(match_operand:SI 2 "reg_or_short_operand" "r,I"))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_UPDATE"
"@
lfdux %3,%0,%2
lfdu %3,%2(%0)"
[(set_attr "type" "fpload")])
-(define_insn ""
+(define_insn "*movdf_update2"
[(set (mem:DF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
(match_operand:SI 2 "reg_or_short_operand" "r,I")))
(match_operand:DF 3 "gpc_reg_operand" "f,f"))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_UPDATE"
"@
stfdux %3,%0,%2
stfdu %3,%2(%0)"
@@ -7007,11 +7019,18 @@
else
neg_op0 = GEN_INT (- INTVAL (operands[0]));
- if (TARGET_32BIT)
- emit_insn (gen_movsi_update (stack_pointer_rtx, stack_pointer_rtx, neg_op0, chain));
- else
- emit_insn (gen_movdi_update (stack_pointer_rtx, stack_pointer_rtx, neg_op0, chain));
+ if (TARGET_UPDATE)
+ emit_insn ((* ((TARGET_32BIT) ? gen_movsi_update : gen_movdi_update))
+ (stack_pointer_rtx, stack_pointer_rtx, neg_op0, chain));
+ else
+ {
+ emit_insn ((* ((TARGET_32BIT) ? gen_addsi3 : gen_adddi3))
+ (stack_pointer_rtx, stack_pointer_rtx, neg_op0));
+ emit_move_insn (gen_rtx (MEM, (TARGET_32BIT) ? SImode : DImode,
+ stack_pointer_rtx),
+ chain);
+ }
DONE;
}")
@@ -7089,7 +7108,7 @@
"TARGET_TOC && TARGET_MINIMAL_TOC && get_pool_size () != 0"
"*
{
- rs6000_output_load_toc_table (asm_out_file);
+ rs6000_output_load_toc_table (asm_out_file, 30);
return \"\";
}"
[(set_attr "type" "load")])
diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h
index 73c09df..294debf 100644
--- a/gcc/config/rs6000/sysv4.h
+++ b/gcc/config/rs6000/sysv4.h
@@ -33,20 +33,18 @@ extern enum rs6000_sdata_type rs6000_sdata;
#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_SDATA 0x08000000 /* use small data areas */
+#define MASK_EABI 0x08000000 /* Adhere to eabi, not System V spec */
#define MASK_LITTLE_ENDIAN 0x04000000 /* target is little endian */
#define MASK_REGNAMES 0x02000000 /* use alternate register names. */
#define MASK_PROTOTYPE 0x01000000 /* Only prototyped fcns pass variable args */
-#define MASK_EABI 0x00800000 /* Adhere to eabi, not System V spec */
#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_EABI (target_flags & MASK_EABI)
#define TARGET_LITTLE_ENDIAN (target_flags & MASK_LITTLE_ENDIAN)
#define TARGET_REGNAMES (target_flags & MASK_REGNAMES)
#define TARGET_PROTOTYPE (target_flags & MASK_PROTOTYPE)
-#define TARGET_EABI (target_flags & MASK_EABI)
#define TARGET_TOC ((target_flags & MASK_64BIT) \
|| ((target_flags & (MASK_RELOCATABLE \
| MASK_MINIMAL_TOC)) \
@@ -73,13 +71,9 @@ extern enum rs6000_sdata_type rs6000_sdata;
{ "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 }, \
- { "relocatable-lib", -MASK_SDATA }, \
{ "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 }, \
@@ -94,6 +88,8 @@ extern enum rs6000_sdata_type rs6000_sdata;
{ "no-eabi", -MASK_EABI }, \
{ "regnames", MASK_REGNAMES }, \
{ "no-regnames", -MASK_REGNAMES }, \
+ { "sdata", 0 }, \
+ { "no-sdata", 0 }, \
{ "sim", 0 }, \
{ "mvme", 0 }, \
{ "emb", 0 }, \
@@ -169,12 +165,8 @@ do { \
\
if (rs6000_sdata_name) \
{ \
- target_flags |= MASK_SDATA; \
if (!strcmp (rs6000_sdata_name, "none")) \
- { \
- rs6000_sdata = SDATA_NONE; \
- target_flags &= ~MASK_SDATA; \
- } \
+ rs6000_sdata = SDATA_NONE; \
else if (!strcmp (rs6000_sdata_name, "data")) \
rs6000_sdata = SDATA_DATA; \
else if (!strcmp (rs6000_sdata_name, "default")) \
@@ -186,21 +178,10 @@ do { \
else \
error ("Bad value for -msdata=%s", rs6000_sdata_name); \
} \
- else if (TARGET_SDATA && TARGET_EABI) \
- { \
- rs6000_sdata = SDATA_EABI; \
- rs6000_sdata_name = "eabi"; \
- } \
- else if (TARGET_SDATA) \
- { \
- rs6000_sdata = SDATA_SYSV; \
- rs6000_sdata_name = "sysv"; \
- } \
else if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS) \
{ \
rs6000_sdata = SDATA_DATA; \
rs6000_sdata_name = "data"; \
- target_flags |= MASK_SDATA; \
} \
else \
{ \
@@ -225,10 +206,12 @@ do { \
rs6000_sdata_name); \
} \
\
- if (TARGET_SDATA && DEFAULT_ABI != ABI_V4 && DEFAULT_ABI != ABI_SOLARIS) \
+ if (rs6000_sdata != SDATA_NONE && DEFAULT_ABI != ABI_V4 \
+ && DEFAULT_ABI != ABI_SOLARIS) \
{ \
- target_flags &= ~MASK_SDATA; \
- error ("-msdata and -mcall-%s are incompatible.", rs6000_abi_name); \
+ rs6000_sdata = SDATA_NONE; \
+ error ("-msdata=%s and -mcall-%s are incompatible.", \
+ rs6000_sdata_name, rs6000_abi_name); \
} \
\
if (TARGET_RELOCATABLE && !TARGET_MINIMAL_TOC) \
@@ -467,8 +450,6 @@ extern void sbss_section ();
void \
toc_section () \
{ \
- static int toc_initialized = 0; \
- \
if (in_section != in_toc) \
{ \
in_section = in_toc; \
@@ -628,7 +609,7 @@ extern int rs6000_pic_labelno;
char *init_ptr = (TARGET_64BIT) ? ".quad" : ".long"; \
STRIP_NAME_ENCODING (orig_name, NAME); \
\
- if (TARGET_RELOCATABLE && get_pool_size () != 0) \
+ if (TARGET_RELOCATABLE && (get_pool_size () != 0 || profile_flag)) \
{ \
char buf[256], *buf_ptr; \
\
@@ -701,7 +682,8 @@ extern int rs6000_pic_labelno;
#undef ASM_OUTPUT_ALIGNED_LOCAL
#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
do { \
- if (TARGET_SDATA && (SIZE) > 0 && (SIZE) <= g_switch_value) \
+ if (rs6000_sdata != SDATA_NONE && (SIZE) > 0 \
+ && (SIZE) <= g_switch_value) \
{ \
sdata_section (); \
ASM_OUTPUT_ALIGN (FILE, exact_log2 (ALIGN / BITS_PER_UNIT)); \
@@ -961,7 +943,8 @@ do { \
/* Pass various options to the assembler */
#undef ASM_SPEC
-#define ASM_SPEC "%(asm_cpu) %{mregnames} %{mno-regnames} \
+#define ASM_SPEC "%(asm_cpu) \
+%{.s: %{mregnames} %{mno-regnames}} %{.S: %{mregnames} %{mno-regnames}} \
%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \
%{mrelocatable} %{mrelocatable-lib} %{fpic:-K PIC} %{fPIC:-K PIC} \
%{memb} %{!memb: %{msdata: -memb} %{msdata=eabi: -memb}} \
@@ -983,7 +966,9 @@ do { \
%{!meabi: %{!mno-eabi: \
%{mrelocatable: -meabi } \
%{mcall-solaris: -mno-eabi } \
- %{mcall-linux: -mno-eabi }}}"
+ %{mcall-linux: -mno-eabi }}} \
+%{msdata: -msdata=default} \
+%{mno-sdata: -msdata=none}"
/* Don't put -Y P,<path> for cross compilers */
#undef LINK_PATH_SPEC
@@ -1357,3 +1342,12 @@ do { \
#undef MULTILIB_DEFAULTS
#define MULTILIB_DEFAULTS { "mbig", "mcall-sysv" }
+
+/* Define this macro if the code for function profiling should come
+ before the function prologue. Normally, the profiling code comes
+ after. */
+#define PROFILE_BEFORE_PROLOGUE 1
+
+/* Function name to call to do profiling. */
+#undef RS6000_MCOUNT
+#define RS6000_MCOUNT "_mcount"