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
This commit is contained in:
Michael Meissner 1997-06-29 16:13:13 +00:00
parent 8b0c969eb1
commit 38c1f2d7e6
4 changed files with 532 additions and 316 deletions

View File

@ -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)
switch (DEFAULT_ABI)
{
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 ();
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

View File

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

View File

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

View File

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