From 38c1f2d7e6de970a7345b7d7fabe3952f2f7af89 Mon Sep 17 00:00:00 2001 From: Michael Meissner Date: Sun, 29 Jun 1997 16:13:13 +0000 Subject: [PATCH] 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 --- gcc/config/rs6000/rs6000.c | 342 +++++++++++++++++++++++++++--------- gcc/config/rs6000/rs6000.h | 195 +++++++++++--------- gcc/config/rs6000/rs6000.md | 251 ++++++++++++++------------ gcc/config/rs6000/sysv4.h | 60 +++---- 4 files changed, 532 insertions(+), 316 deletions(-) diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 8146ce97806..60262a9aba4 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, ®); } + + 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 diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index f469061a0d8..60b4c529e82 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 fc1323a7b3c..0e6e259c8c8 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 73c09dfa24e..294debf3f98 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, 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"