diff options
Diffstat (limited to 'gcc/config/sh')
-rw-r--r-- | gcc/config/sh/elf.h | 2 | ||||
-rw-r--r-- | gcc/config/sh/linux-unwind.h | 94 | ||||
-rw-r--r-- | gcc/config/sh/linux.h | 63 | ||||
-rw-r--r-- | gcc/config/sh/predicates.md | 880 | ||||
-rw-r--r-- | gcc/config/sh/sh-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/sh/sh.c | 866 | ||||
-rw-r--r-- | gcc/config/sh/sh.h | 96 | ||||
-rw-r--r-- | gcc/config/sh/sh.md | 6 | ||||
-rw-r--r-- | gcc/config/sh/sh.opt | 20 | ||||
-rw-r--r-- | gcc/config/sh/symbian-pre.h | 2 | ||||
-rw-r--r-- | gcc/config/sh/symbian.c | 10 | ||||
-rw-r--r-- | gcc/config/sh/ushmedia.h | 4 |
12 files changed, 1066 insertions, 978 deletions
diff --git a/gcc/config/sh/elf.h b/gcc/config/sh/elf.h index 52d0727eb64..c53c4be54ff 100644 --- a/gcc/config/sh/elf.h +++ b/gcc/config/sh/elf.h @@ -1,5 +1,5 @@ /* Definitions of target machine for gcc for Renesas / SuperH SH using ELF. - Copyright (C) 1996, 1997, 2000, 2001, 2002, 2004 + Copyright (C) 1996, 1997, 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc. Contributed by Ian Lance Taylor <ian@cygnus.com>. diff --git a/gcc/config/sh/linux-unwind.h b/gcc/config/sh/linux-unwind.h index 6ca9d567886..ab149d33d42 100644 --- a/gcc/config/sh/linux-unwind.h +++ b/gcc/config/sh/linux-unwind.h @@ -35,18 +35,11 @@ Boston, MA 02111-1307, USA. */ # if defined (__SH5__) #define SH_DWARF_FRAME_GP0 0 -#define SH_DWARF_FRAME_FP0 (__SH5__ == 32 ? 245 : 77) -#define SH_DWARF_FRAME_XD0 289 +#define SH_DWARF_FRAME_FP0 77 #define SH_DWARF_FRAME_BT0 68 -#define SH_DWARF_FRAME_PR 241 #define SH_DWARF_FRAME_PR_MEDIA 18 -#define SH_DWARF_FRAME_GBR 238 -#define SH_DWARF_FRAME_MACH 239 -#define SH_DWARF_FRAME_MACL 240 -#define SH_DWARF_FRAME_PC 64 #define SH_DWARF_FRAME_SR 65 -#define SH_DWARF_FRAME_FPUL 244 -#define SH_DWARF_FRAME_FPSCR 243 +#define SH_DWARF_FRAME_FPSCR 76 #else #define SH_DWARF_FRAME_GP0 0 #define SH_DWARF_FRAME_FP0 25 @@ -62,7 +55,88 @@ Boston, MA 02111-1307, USA. */ #endif /* defined (__SH5__) */ #if defined (__SH5__) -/* MD_FALLBACK_FRAME_STATE_FOR is not yet defined for SHMEDIA. */ + +#define MD_FALLBACK_FRAME_STATE_FOR shmedia_fallback_frame_state + +static _Unwind_Reason_Code +shmedia_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + unsigned char *pc = context->ra; + struct sigcontext *sc; + long new_cfa; + int i, r; + + /* movi 0x10,r9; shori 0x77,r9; trapa r9; nop (sigreturn) */ + /* movi 0x10,r9; shori 0xad,r9; trapa r9; nop (rt_sigreturn) */ + if ((*(unsigned long *) (pc-1) == 0xcc004090) + && (*(unsigned long *) (pc+3) == 0xc801dc90) + && (*(unsigned long *) (pc+7) == 0x6c91fff0) + && (*(unsigned long *) (pc+11) == 0x6ff0fff0)) + sc = context->cfa; + else if ((*(unsigned long *) (pc-1) == 0xcc004090) + && (*(unsigned long *) (pc+3) == 0xc802b490) + && (*(unsigned long *) (pc+7) == 0x6c91fff0) + && (*(unsigned long *) (pc+11) == 0x6ff0fff0)) + { + struct rt_sigframe { + struct siginfo *pinfo; + void *puc; + struct siginfo info; + struct ucontext uc; + } *rt_ = context->cfa; + sc = (struct sigcontext *) &rt_->uc.uc_mcontext; + } + else + return _URC_END_OF_STACK; + + new_cfa = sc->sc_regs[15]; + fs->cfa_how = CFA_REG_OFFSET; + fs->cfa_reg = 15; + fs->cfa_offset = new_cfa - (long) context->cfa; + + for (i = 0; i < 63; i++) + { + if (i == 15) + continue; + + fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.reg[i].loc.offset + = (long)&(sc->sc_regs[i]) - new_cfa; + } + + fs->regs.reg[SH_DWARF_FRAME_SR].how = REG_SAVED_OFFSET; + fs->regs.reg[SH_DWARF_FRAME_SR].loc.offset + = (long)&(sc->sc_sr) - new_cfa; + + r = SH_DWARF_FRAME_BT0; + for (i = 0; i < 8; i++) + { + fs->regs.reg[r+i].how = REG_SAVED_OFFSET; + fs->regs.reg[r+i].loc.offset + = (long)&(sc->sc_tregs[i]) - new_cfa; + } + + r = SH_DWARF_FRAME_FP0; + for (i = 0; i < 32; i++) + { + fs->regs.reg[r+i].how = REG_SAVED_OFFSET; + fs->regs.reg[r+i].loc.offset + = (long)&(sc->sc_fpregs[i]) - new_cfa; + } + + fs->regs.reg[SH_DWARF_FRAME_FPSCR].how = REG_SAVED_OFFSET; + fs->regs.reg[SH_DWARF_FRAME_FPSCR].loc.offset + = (long)&(sc->sc_fpscr) - new_cfa; + + /* We use the slot for the zero register to save return address. */ + fs->regs.reg[63].how = REG_SAVED_OFFSET; + fs->regs.reg[63].loc.offset + = (long)&(sc->sc_pc) - new_cfa; + fs->retaddr_column = 63; + return _URC_NO_REASON; +} + #else /* defined (__SH5__) */ #define MD_FALLBACK_FRAME_STATE_FOR sh_fallback_frame_state diff --git a/gcc/config/sh/linux.h b/gcc/config/sh/linux.h index fe48d0ca0b1..51d52ebfcc4 100644 --- a/gcc/config/sh/linux.h +++ b/gcc/config/sh/linux.h @@ -68,29 +68,56 @@ Boston, MA 02111-1307, USA. */ #undef FUNCTION_PROFILER #define FUNCTION_PROFILER(STREAM,LABELNO) \ do { \ - if (flag_pic) \ + if (TARGET_SHMEDIA) \ { \ - fprintf (STREAM, "\tmov.l\t3f,r1\n"); \ - fprintf (STREAM, "\tmova\t3f,r0\n"); \ - fprintf (STREAM, "\tadd\tr1,r0\n"); \ - fprintf (STREAM, "\tmov.l\t1f,r1\n"); \ - fprintf (STREAM, "\tmov.l\t@(r0,r1),r1\n"); \ + fprintf (STREAM, "\tpt\t1f,tr1\n"); \ + fprintf (STREAM, "\taddi.l\tr15,-8,r15\n"); \ + fprintf (STREAM, "\tst.l\tr15,0,r18\n"); \ + if (flag_pic) \ + { \ + char *gofs = "(datalabel _GLOBAL_OFFSET_TABLE_-(0f-.))"; \ + fprintf (STREAM, "\tmovi\t((%s>>16)&0xffff),r21\n", gofs); \ + fprintf (STREAM, "\tshori\t(%s & 0xffff),r21\n", gofs); \ + fprintf (STREAM, "0:\tptrel/u\tr21,tr0\n"); \ + fprintf (STREAM, "\tmovi\t((mcount@GOTPLT)&0xffff),r22\n"); \ + fprintf (STREAM, "\tgettr\ttr0,r21\n"); \ + fprintf (STREAM, "\tadd.l\tr21,r22,r21\n"); \ + fprintf (STREAM, "\tld.l\tr21,0,r21\n"); \ + fprintf (STREAM, "\tptabs\tr21,tr0\n"); \ + } \ + else \ + fprintf (STREAM, "\tpt\tmcount,tr0\n"); \ + fprintf (STREAM, "\tgettr\ttr1,r18\n"); \ + fprintf (STREAM, "\tblink\ttr0,r63\n"); \ + fprintf (STREAM, "1:\tld.l\tr15,0,r18\n"); \ + fprintf (STREAM, "\taddi.l\tr15,8,r15\n"); \ } \ else \ - fprintf (STREAM, "\tmov.l\t1f,r1\n"); \ - fprintf (STREAM, "\tsts.l\tpr,@-r15\n"); \ - fprintf (STREAM, "\tmova\t2f,r0\n"); \ - fprintf (STREAM, "\tjmp\t@r1\n"); \ - fprintf (STREAM, "\tlds\tr0,pr\n"); \ - fprintf (STREAM, "\t.align\t2\n"); \ - if (flag_pic) \ { \ - fprintf (STREAM, "1:\t.long\tmcount@GOT\n"); \ - fprintf (STREAM, "3:\t.long\t_GLOBAL_OFFSET_TABLE_\n"); \ + if (flag_pic) \ + { \ + fprintf (STREAM, "\tmov.l\t3f,r1\n"); \ + fprintf (STREAM, "\tmova\t3f,r0\n"); \ + fprintf (STREAM, "\tadd\tr1,r0\n"); \ + fprintf (STREAM, "\tmov.l\t1f,r1\n"); \ + fprintf (STREAM, "\tmov.l\t@(r0,r1),r1\n"); \ + } \ + else \ + fprintf (STREAM, "\tmov.l\t1f,r1\n"); \ + fprintf (STREAM, "\tsts.l\tpr,@-r15\n"); \ + fprintf (STREAM, "\tmova\t2f,r0\n"); \ + fprintf (STREAM, "\tjmp\t@r1\n"); \ + fprintf (STREAM, "\tlds\tr0,pr\n"); \ + fprintf (STREAM, "\t.align\t2\n"); \ + if (flag_pic) \ + { \ + fprintf (STREAM, "1:\t.long\tmcount@GOT\n"); \ + fprintf (STREAM, "3:\t.long\t_GLOBAL_OFFSET_TABLE_\n"); \ + } \ + else \ + fprintf (STREAM, "1:\t.long\tmcount\n"); \ + fprintf (STREAM, "2:\tlds.l\t@r15+,pr\n"); \ } \ - else \ - fprintf (STREAM, "1:\t.long\tmcount\n"); \ - fprintf (STREAM, "2:\tlds.l\t@r15+,pr\n"); \ } while (0) #define MD_UNWIND_SUPPORT "config/sh/linux-unwind.h" diff --git a/gcc/config/sh/predicates.md b/gcc/config/sh/predicates.md index 981cc8f10f5..324d30da802 100644 --- a/gcc/config/sh/predicates.md +++ b/gcc/config/sh/predicates.md @@ -1,3 +1,25 @@ +;; Predicate definitions for Renesas / SuperH SH. +;; Copyright (C) 2005 Free Software Foundation, Inc. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. +;; +;; GCC is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING. If not, write to +;; the Free Software Foundation, 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;; TODO: Add a comment here. + (define_predicate "trapping_target_operand" (match_code "if_then_else") { @@ -36,3 +58,861 @@ && INTVAL (XEXP (and, 1)) == 3 && INTVAL (XEXP (cond, 1)) == 3); }) + +;; TODO: Add a comment here. + +(define_predicate "and_operand" + (match_code "subreg,reg,const_int") +{ + if (logical_operand (op, mode)) + return 1; + + /* Check mshflo.l / mshflhi.l opportunities. */ + if (TARGET_SHMEDIA + && mode == DImode + && GET_CODE (op) == CONST_INT + && CONST_OK_FOR_J16 (INTVAL (op))) + return 1; + + return 0; +}) + +;; Like arith_reg_dest, but this predicate belongs to +;; SPECIAL_MODE_PREDICATES. + +(define_special_predicate "any_arith_reg_dest" + (match_code "subreg,reg") +{ + return arith_reg_dest (op, mode); +}) + +;; Like register_operand, but this predicate belongs to +;; SPECIAL_MODE_PREDICATES. + +(define_special_predicate "any_register_operand" + (match_code "subreg,reg") +{ + return register_operand (op, mode); +}) + +;; Returns 1 if OP is a valid source operand for an arithmetic insn. + +(define_predicate "arith_operand" + (match_code "subreg,reg,const_int,truncate") +{ + if (arith_reg_operand (op, mode)) + return 1; + + if (TARGET_SHMEDIA) + { + /* FIXME: We should be checking whether the CONST_INT fits in a + CONST_OK_FOR_I16 here, but this causes reload_cse to crash when + attempting to transform a sequence of two 64-bit sets of the + same register from literal constants into a set and an add, + when the difference is too wide for an add. */ + if (GET_CODE (op) == CONST_INT + || EXTRA_CONSTRAINT_C16 (op)) + return 1; + else if (GET_CODE (op) == TRUNCATE + && ! system_reg_operand (XEXP (op, 0), VOIDmode) + && (mode == VOIDmode || mode == GET_MODE (op)) + && (GET_MODE_SIZE (GET_MODE (op)) + < GET_MODE_SIZE (GET_MODE (XEXP (op, 0)))) + && (! FP_REGISTER_P (REGNO (XEXP (op, 0))) + || GET_MODE_SIZE (GET_MODE (op)) == 4)) + return register_operand (XEXP (op, 0), VOIDmode); + else + return 0; + } + else if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_I08 (INTVAL (op))) + return 1; + + return 0; +}) + +;; Like above, but for DImode destinations: forbid paradoxical DImode +;; subregs, because this would lead to missing sign extensions when +;; truncating from DImode to SImode. + +(define_predicate "arith_reg_dest" + (match_code "subreg,reg") +{ + if (mode == DImode && GET_CODE (op) == SUBREG + && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) < 8 + && TARGET_SHMEDIA) + return 0; + return arith_reg_operand (op, mode); +}) + +;; Returns 1 if OP is a normal arithmetic register. + +(define_predicate "arith_reg_operand" + (match_code "subreg,reg,sign_extend") +{ + if (register_operand (op, mode)) + { + int regno; + + if (GET_CODE (op) == REG) + regno = REGNO (op); + else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG) + regno = REGNO (SUBREG_REG (op)); + else + return 1; + + return (regno != T_REG && regno != PR_REG + && ! TARGET_REGISTER_P (regno) + && (regno != FPUL_REG || TARGET_SH4) + && regno != MACH_REG && regno != MACL_REG); + } + /* Allow a no-op sign extension - compare LOAD_EXTEND_OP. + We allow SImode here, as not using an FP register is just a matter of + proper register allocation. */ + if (TARGET_SHMEDIA + && GET_MODE (op) == DImode && GET_CODE (op) == SIGN_EXTEND + && GET_MODE (XEXP (op, 0)) == SImode + && GET_CODE (XEXP (op, 0)) != SUBREG) + return register_operand (XEXP (op, 0), VOIDmode); +#if 0 /* Can't do this because of PROMOTE_MODE for unsigned vars. */ + if (GET_MODE (op) == SImode && GET_CODE (op) == SIGN_EXTEND + && GET_MODE (XEXP (op, 0)) == HImode + && GET_CODE (XEXP (op, 0)) == REG + && REGNO (XEXP (op, 0)) <= LAST_GENERAL_REG) + return register_operand (XEXP (op, 0), VOIDmode); +#endif + if (GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_INT + && GET_CODE (op) == SUBREG + && GET_MODE (SUBREG_REG (op)) == DImode + && GET_CODE (SUBREG_REG (op)) == SIGN_EXTEND + && GET_MODE (XEXP (SUBREG_REG (op), 0)) == SImode + && GET_CODE (XEXP (SUBREG_REG (op), 0)) != SUBREG) + return register_operand (XEXP (SUBREG_REG (op), 0), VOIDmode); + return 0; +}) + +;; Returns 1 if OP is a valid source operand for a compare insn. + +(define_predicate "arith_reg_or_0_operand" + (match_code "subreg,reg,const_int,const_vector") +{ + if (arith_reg_operand (op, mode)) + return 1; + + if (EXTRA_CONSTRAINT_Z (op)) + return 1; + + return 0; +}) + +;; TODO: Add a comment here. + +(define_predicate "binary_float_operator" + (match_code "plus,minus,mult,div") +{ + if (GET_MODE (op) != mode) + return 0; + switch (GET_CODE (op)) + { + case PLUS: + case MINUS: + case MULT: + case DIV: + return 1; + default: + break; + } + return 0; +}) + +;; TODO: Add a comment here. + +(define_predicate "binary_logical_operator" + (match_code "and,ior,xor") +{ + if (GET_MODE (op) != mode) + return 0; + switch (GET_CODE (op)) + { + case IOR: + case AND: + case XOR: + return 1; + default: + break; + } + return 0; +}) + +;; TODO: Add a comment here. + +(define_predicate "cache_address_operand" + (match_code "plus,reg") +{ + if (GET_CODE (op) == PLUS) + { + if (GET_CODE (XEXP (op, 0)) != REG) + return 0; + if (GET_CODE (XEXP (op, 1)) != CONST_INT + || (INTVAL (XEXP (op, 1)) & 31)) + return 0; + } + else if (GET_CODE (op) != REG) + return 0; + return address_operand (op, mode); +}) + +;; Return 1 if OP is a valid source operand for shmedia cmpgt / cmpgtu. + +(define_predicate "cmp_operand" + (match_code "subreg,reg,const_int") +{ + if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_N (INTVAL (op))) + return 1; + if (TARGET_SHMEDIA + && mode != DImode && GET_CODE (op) == SUBREG + && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4) + return 0; + return arith_reg_operand (op, mode); +}) + +;; TODO: Add a comment here. + +(define_predicate "cmpsi_operand" + (match_code "subreg,reg,const_int") +{ + if (GET_CODE (op) == REG && REGNO (op) == T_REG + && GET_MODE (op) == SImode + && TARGET_SH1) + return 1; + return arith_operand (op, mode); +}) + +;; TODO: Add a comment here. + +(define_predicate "commutative_float_operator" + (match_code "plus,mult") +{ + if (GET_MODE (op) != mode) + return 0; + switch (GET_CODE (op)) + { + case PLUS: + case MULT: + return 1; + default: + break; + } + return 0; +}) + +;; TODO: Add a comment here. + +(define_predicate "equality_comparison_operator" + (match_code "eq,ne") +{ + return ((mode == VOIDmode || GET_MODE (op) == mode) + && (GET_CODE (op) == EQ || GET_CODE (op) == NE)); +}) + +;; TODO: Add a comment here. + +(define_predicate "extend_reg_operand" + (match_code "subreg,reg,truncate") +{ + return (GET_CODE (op) == TRUNCATE + ? arith_operand + : arith_reg_operand) (op, mode); +}) + +;; TODO: Add a comment here. + +(define_predicate "extend_reg_or_0_operand" + (match_code "subreg,reg,truncate,const_int") +{ + return (GET_CODE (op) == TRUNCATE + ? arith_operand + : arith_reg_or_0_operand) (op, mode); +}) + +;; Like arith_reg_operand, but this predicate does not accept SIGN_EXTEND. + +(define_predicate "ext_dest_operand" + (match_code "subreg,reg") +{ + return arith_reg_operand (op, mode); +}) + +;; TODO: Add a comment here. + +(define_predicate "fp_arith_reg_dest" + (match_code "subreg,reg") +{ + if (mode == DImode && GET_CODE (op) == SUBREG + && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) < 8) + return 0; + return fp_arith_reg_operand (op, mode); +}) + +;; TODO: Add a comment here. + +(define_predicate "fp_arith_reg_operand" + (match_code "subreg,reg") +{ + if (register_operand (op, mode)) + { + int regno; + + if (GET_CODE (op) == REG) + regno = REGNO (op); + else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG) + regno = REGNO (SUBREG_REG (op)); + else + return 1; + + return (regno >= FIRST_PSEUDO_REGISTER + || FP_REGISTER_P (regno)); + } + return 0; +}) + +;; TODO: Add a comment here. + +(define_predicate "fpscr_operand" + (match_code "reg") +{ + return (GET_CODE (op) == REG + && (REGNO (op) == FPSCR_REG + || (REGNO (op) >= FIRST_PSEUDO_REGISTER + && !(reload_in_progress || reload_completed))) + && GET_MODE (op) == PSImode); +}) + +;; TODO: Add a comment here. + +(define_predicate "fpul_operand" + (match_code "reg") +{ + if (TARGET_SHMEDIA) + return fp_arith_reg_operand (op, mode); + + return (GET_CODE (op) == REG + && (REGNO (op) == FPUL_REG || REGNO (op) >= FIRST_PSEUDO_REGISTER) + && GET_MODE (op) == mode); +}) + +;; TODO: Add a comment here. + +(define_predicate "general_extend_operand" + (match_code "subreg,reg,mem,truncate") +{ + return (GET_CODE (op) == TRUNCATE + ? arith_operand + : nonimmediate_operand) (op, mode); +}) + +;; Returns 1 if OP can be source of a simple move operation. Same as +;; general_operand, but a LABEL_REF is valid, PRE_DEC is invalid as +;; are subregs of system registers. + +(define_predicate "general_movsrc_operand" + (match_code "subreg,reg,const_int,const_double,mem,symbol_ref,label_ref,const,const_vector") +{ + if (GET_CODE (op) == MEM) + { + rtx inside = XEXP (op, 0); + if (GET_CODE (inside) == CONST) + inside = XEXP (inside, 0); + + if (GET_CODE (inside) == LABEL_REF) + return 1; + + if (GET_CODE (inside) == PLUS + && GET_CODE (XEXP (inside, 0)) == LABEL_REF + && GET_CODE (XEXP (inside, 1)) == CONST_INT) + return 1; + + /* Only post inc allowed. */ + if (GET_CODE (inside) == PRE_DEC) + return 0; + } + + if ((mode == QImode || mode == HImode) + && (GET_CODE (op) == SUBREG + && GET_CODE (XEXP (op, 0)) == REG + && system_reg_operand (XEXP (op, 0), mode))) + return 0; + + if (TARGET_SHMEDIA + && (GET_CODE (op) == PARALLEL || GET_CODE (op) == CONST_VECTOR) + && sh_rep_vec (op, mode)) + return 1; + if (TARGET_SHMEDIA && 1 + && GET_CODE (op) == SUBREG && GET_MODE (op) == mode + && SUBREG_REG (op) == const0_rtx && subreg_lowpart_p (op)) + /* FIXME */ abort (); /* return 1; */ + return general_operand (op, mode); +}) + +;; Returns 1 if OP can be a destination of a move. Same as +;; general_operand, but no preinc allowed. + +(define_predicate "general_movdst_operand" + (match_code "subreg,reg,mem") +{ + /* Only pre dec allowed. */ + if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == POST_INC) + return 0; + if (mode == DImode && TARGET_SHMEDIA && GET_CODE (op) == SUBREG + && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) < 8 + && ! (high_life_started || reload_completed)) + return 0; + + return general_operand (op, mode); +}) + +;; Returns 1 if OP is a MEM that can be source of a simple move operation. + +(define_predicate "unaligned_load_operand" + (match_code "mem") +{ + rtx inside; + + if (GET_CODE (op) != MEM || GET_MODE (op) != mode) + return 0; + + inside = XEXP (op, 0); + + if (GET_CODE (inside) == POST_INC) + inside = XEXP (inside, 0); + + if (GET_CODE (inside) == REG) + return 1; + + return 0; +}) + +;; TODO: Add a comment here. + +(define_predicate "greater_comparison_operator" + (match_code "gt,ge,gtu,geu") +{ + if (mode != VOIDmode && GET_MODE (op) != mode) + return 0; + switch (GET_CODE (op)) + { + case GT: + case GE: + case GTU: + case GEU: + return 1; + default: + return 0; + } +}) + +;; TODO: Add a comment here. + +(define_predicate "inqhi_operand" + (match_code "truncate") +{ + if (GET_CODE (op) != TRUNCATE || mode != GET_MODE (op)) + return 0; + op = XEXP (op, 0); + /* Can't use true_regnum here because copy_cost wants to know about + SECONDARY_INPUT_RELOAD_CLASS. */ + return GET_CODE (op) == REG && FP_REGISTER_P (REGNO (op)); +}) + +;; TODO: Add a comment here. + +(define_special_predicate "int_gpr_dest" + (match_code "subreg,reg") +{ + enum machine_mode op_mode = GET_MODE (op); + + if (GET_MODE_CLASS (op_mode) != MODE_INT + || GET_MODE_SIZE (op_mode) >= UNITS_PER_WORD) + return 0; + if (! reload_completed) + return 0; + return true_regnum (op) <= LAST_GENERAL_REG; +}) + +;; TODO: Add a comment here. + +(define_predicate "less_comparison_operator" + (match_code "lt,le,ltu,leu") +{ + if (mode != VOIDmode && GET_MODE (op) != mode) + return 0; + switch (GET_CODE (op)) + { + case LT: + case LE: + case LTU: + case LEU: + return 1; + default: + return 0; + } +}) + +;; Returns 1 if OP is a valid source operand for a logical operation. + +(define_predicate "logical_operand" + (match_code "subreg,reg,const_int") +{ + if (TARGET_SHMEDIA + && mode != DImode && GET_CODE (op) == SUBREG + && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4) + return 0; + + if (arith_reg_operand (op, mode)) + return 1; + + if (TARGET_SHMEDIA) + { + if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_I10 (INTVAL (op))) + return 1; + else + return 0; + } + else if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_K08 (INTVAL (op))) + return 1; + + return 0; +}) + +;; TODO: Add a comment here. + +(define_predicate "logical_operator" + (match_code "and,ior,xor") +{ + if (mode != VOIDmode && GET_MODE (op) != mode) + return 0; + switch (GET_CODE (op)) + { + case AND: + case IOR: + case XOR: + return 1; + default: + return 0; + } +}) + +;; Like arith_reg_operand, but for register source operands of narrow +;; logical SHMEDIA operations: forbid subregs of DImode / TImode regs. + +(define_predicate "logical_reg_operand" + (match_code "subreg,reg") +{ + if (TARGET_SHMEDIA + && GET_CODE (op) == SUBREG + && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4 + && mode != DImode) + return 0; + return arith_reg_operand (op, mode); +}) + +;; TODO: Add a comment here. + +(define_predicate "mextr_bit_offset" + (match_code "const_int") +{ + HOST_WIDE_INT i; + + if (GET_CODE (op) != CONST_INT) + return 0; + i = INTVAL (op); + return i >= 1 * 8 && i <= 7 * 8 && (i & 7) == 0; +}) + +;; TODO: Add a comment here. + +(define_predicate "minuend_operand" + (match_code "subreg,reg,truncate,const_int") +{ + return op == constm1_rtx || extend_reg_or_0_operand (op, mode); +}) + +;; TODO: Add a comment here. + +(define_predicate "noncommutative_float_operator" + (match_code "minus,div") +{ + if (GET_MODE (op) != mode) + return 0; + switch (GET_CODE (op)) + { + case MINUS: + case DIV: + return 1; + default: + break; + } + return 0; +}) + +;; TODO: Add a comment here. + +(define_predicate "sh_const_vec" + (match_code "const_vector") +{ + int i; + + if (GET_CODE (op) != CONST_VECTOR + || (GET_MODE (op) != mode && mode != VOIDmode)) + return 0; + i = XVECLEN (op, 0) - 1; + for (; i >= 0; i--) + if (GET_CODE (XVECEXP (op, 0, i)) != CONST_INT) + return 0; + return 1; +}) + +;; Determine if OP is a constant vector matching MODE with only one +;; element that is not a sign extension. Two byte-sized elements +;; count as one. + +(define_predicate "sh_1el_vec" + (match_code "const_vector") +{ + int unit_size; + int i, last, least, sign_ix; + rtx sign; + + if (GET_CODE (op) != CONST_VECTOR + || (GET_MODE (op) != mode && mode != VOIDmode)) + return 0; + /* Determine numbers of last and of least significant elements. */ + last = XVECLEN (op, 0) - 1; + least = TARGET_LITTLE_ENDIAN ? 0 : last; + if (GET_CODE (XVECEXP (op, 0, least)) != CONST_INT) + return 0; + sign_ix = least; + if (GET_MODE_UNIT_SIZE (mode) == 1) + sign_ix = TARGET_LITTLE_ENDIAN ? 1 : last - 1; + if (GET_CODE (XVECEXP (op, 0, sign_ix)) != CONST_INT) + return 0; + unit_size = GET_MODE_UNIT_SIZE (GET_MODE (op)); + sign = (INTVAL (XVECEXP (op, 0, sign_ix)) >> (unit_size * BITS_PER_UNIT - 1) + ? constm1_rtx : const0_rtx); + i = XVECLEN (op, 0) - 1; + do + if (i != least && i != sign_ix && XVECEXP (op, 0, i) != sign) + return 0; + while (--i); + return 1; +}) + +;; Like register_operand, but take into account that SHMEDIA can use +;; the constant zero like a general register. + +(define_predicate "sh_register_operand" + (match_code "reg,subreg,const_int") +{ + if (op == CONST0_RTX (mode) && TARGET_SHMEDIA) + return 1; + return register_operand (op, mode); +}) + +;; TODO: Add a comment here. + +(define_predicate "sh_rep_vec" + (match_code "const_vector") +{ + int i; + rtx x, y; + + if ((GET_CODE (op) != CONST_VECTOR && GET_CODE (op) != PARALLEL) + || (GET_MODE (op) != mode && mode != VOIDmode)) + return 0; + i = XVECLEN (op, 0) - 2; + x = XVECEXP (op, 0, i + 1); + if (GET_MODE_UNIT_SIZE (mode) == 1) + { + y = XVECEXP (op, 0, i); + for (i -= 2; i >= 0; i -= 2) + if (! rtx_equal_p (XVECEXP (op, 0, i + 1), x) + || ! rtx_equal_p (XVECEXP (op, 0, i), y)) + return 0; + } + else + for (; i >= 0; i--) + if (XVECEXP (op, 0, i) != x) + return 0; + return 1; +}) + +;; TODO: Add a comment here. + +(define_predicate "shift_count_operand" + (match_code "const_int,const_double,const,symbol_ref,label_ref,subreg,reg,zero_extend,sign_extend") +{ + return (CONSTANT_P (op) + ? (GET_CODE (op) == CONST_INT + ? (unsigned) INTVAL (op) < GET_MODE_BITSIZE (mode) + : nonmemory_operand (op, mode)) + : shift_count_reg_operand (op, mode)); +}) + +;; TODO: Add a comment here. + +(define_predicate "shift_count_reg_operand" + (match_code "subreg,reg,zero_extend,sign_extend") +{ + if ((GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND + || (GET_CODE (op) == SUBREG && SUBREG_BYTE (op) == 0)) + && (mode == VOIDmode || mode == GET_MODE (op)) + && GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0))) >= 6 + && GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_INT) + { + mode = VOIDmode; + do + op = XEXP (op, 0); + while ((GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND + || GET_CODE (op) == TRUNCATE) + && GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0))) >= 6 + && GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_INT); + + } + return arith_reg_operand (op, mode); +}) + +;; TODO: Add a comment here. + +(define_predicate "shift_operator" + (match_code "ashift,ashiftrt,lshiftrt") +{ + if (mode != VOIDmode && GET_MODE (op) != mode) + return 0; + switch (GET_CODE (op)) + { + case ASHIFT: + case ASHIFTRT: + case LSHIFTRT: + return 1; + default: + return 0; + } +}) + +;; TODO: Add a comment here. + +(define_predicate "symbol_ref_operand" + (match_code "symbol_ref") +{ + return (GET_CODE (op) == SYMBOL_REF); +}) + +;; Same as target_reg_operand, except that label_refs and symbol_refs +;; are accepted before reload. + +(define_special_predicate "target_operand" + (match_code "subreg,reg,label_ref,symbol_ref,const,unspec") +{ + if (mode != VOIDmode && mode != Pmode) + return 0; + + if ((GET_MODE (op) == Pmode || GET_MODE (op) == VOIDmode) + && EXTRA_CONSTRAINT_Csy (op)) + return ! reload_completed; + + return target_reg_operand (op, mode); +}) + +;; Accept pseudos and branch target registers. + +(define_special_predicate "target_reg_operand" + (match_code "subreg,reg") +{ + if (mode == VOIDmode + ? GET_MODE (op) != Pmode && GET_MODE (op) != PDImode + : mode != GET_MODE (op)) + return 0; + + if (GET_CODE (op) == SUBREG) + op = XEXP (op, 0); + + if (GET_CODE (op) != REG) + return 0; + + /* We must protect ourselves from matching pseudos that are virtual + register, because they will eventually be replaced with hardware + registers that aren't branch-target registers. */ + if (REGNO (op) > LAST_VIRTUAL_REGISTER + || TARGET_REGISTER_P (REGNO (op))) + return 1; + + return 0; +}) + +;; TODO: Add a comment here. + +(define_special_predicate "trunc_hi_operand" + (match_code "subreg,reg,truncate") +{ + enum machine_mode op_mode = GET_MODE (op); + + if (op_mode != SImode && op_mode != DImode + && op_mode != V4HImode && op_mode != V2SImode) + return 0; + return extend_reg_operand (op, mode); +}) + +;; TODO: Add a comment here. + +(define_predicate "ua_address_operand" + (match_code "subreg,reg,plus") +{ + if (GET_CODE (op) == PLUS + && (GET_CODE (XEXP (op, 1)) != CONST_INT + || ! CONST_OK_FOR_I06 (INTVAL (XEXP (op, 1))))) + return 0; + return address_operand (op, QImode); +}) + +;; TODO: Add a comment here. + +(define_predicate "ua_offset" + (match_code "const_int") +{ + return GET_CODE (op) == CONST_INT && CONST_OK_FOR_I06 (INTVAL (op)); +}) + +;; TODO: Add a comment here. + +(define_predicate "unary_float_operator" + (match_code "abs,neg,sqrt") +{ + if (GET_MODE (op) != mode) + return 0; + switch (GET_CODE (op)) + { + case ABS: + case NEG: + case SQRT: + return 1; + default: + break; + } + return 0; +}) + +;; Return 1 if OP is a valid source operand for xor. + +(define_predicate "xor_operand" + (match_code "subreg,reg,const_int") +{ + if (GET_CODE (op) == CONST_INT) + return (TARGET_SHMEDIA + ? (CONST_OK_FOR_I06 (INTVAL (op)) + || (no_new_pseudos && INTVAL (op) == 0xff)) + : CONST_OK_FOR_K08 (INTVAL (op))); + if (TARGET_SHMEDIA + && mode != DImode && GET_CODE (op) == SUBREG + && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4) + return 0; + return arith_reg_operand (op, mode); +}) diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h index d3644d87805..dd9d5c29540 100644 --- a/gcc/config/sh/sh-protos.h +++ b/gcc/config/sh/sh-protos.h @@ -159,7 +159,6 @@ extern rtx sh_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int); extern void sh_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, tree, int); extern int sh_pass_in_reg_p (CUMULATIVE_ARGS *, enum machine_mode, tree); extern void sh_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, signed int, enum machine_mode); -extern const char *sh_pch_valid_p (const void *data_p, size_t sz); extern bool sh_promote_prototypes (tree); extern rtx replace_n_hard_rtx (rtx, rtx *, int , int); diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index a0b7862299f..91fa5e9ce52 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -228,6 +228,7 @@ static tree sh_handle_trap_exit_attribute (tree *, tree, tree, int, bool *); static tree sh_handle_renesas_attribute (tree *, tree, tree, int, bool *); static void sh_output_function_epilogue (FILE *, HOST_WIDE_INT); static void sh_insert_attributes (tree, tree *); +static const char *sh_check_pch_target_flags (int); static int sh_adjust_cost (rtx, rtx, rtx, int); static int sh_issue_rate (void); static int sh_dfa_new_cycle (FILE *, int, rtx, int, int, int *sort_p); @@ -467,8 +468,8 @@ static int hard_regs_intersect_p (HARD_REG_SET *, HARD_REG_SET *); #undef TARGET_VECTOR_MODE_SUPPORTED_P #define TARGET_VECTOR_MODE_SUPPORTED_P sh_vector_mode_supported_p -#undef TARGET_PCH_VALID_P -#define TARGET_PCH_VALID_P sh_pch_valid_p +#undef TARGET_CHECK_PCH_TARGET_FLAGS +#define TARGET_CHECK_PCH_TARGET_FLAGS sh_check_pch_target_flags #undef TARGET_DWARF_CALLING_CONVENTION #define TARGET_DWARF_CALLING_CONVENTION sh_dwarf_calling_convention @@ -1964,8 +1965,8 @@ addsubcosts (rtx x) static inline int multcosts (rtx x ATTRIBUTE_UNUSED) { - if (*sh_multcost_str) - return atoi (sh_multcost_str); + if (sh_multcost >= 0) + return sh_multcost; if (TARGET_SHMEDIA) /* ??? We have a mul insn, but it has a latency of three, and doesn't accept constants. Ideally, we would use a cost of one or two and @@ -2909,7 +2910,7 @@ gen_datalabel_ref (rtx sym) /* The SH cannot load a large constant into a register, constants have to come from a pc relative load. The reference of a pc relative load - instruction must be less than 1k infront of the instruction. This + instruction must be less than 1k in front of the instruction. This means that we often have to dump a constant inside a function, and generate code to branch around it. @@ -7393,7 +7394,7 @@ sh_handle_interrupt_handler_attribute (tree *node, tree name, { if (TREE_CODE (*node) != FUNCTION_DECL) { - warning (0, "%qs attribute only applies to functions", + warning (OPT_Wattributes, "%qs attribute only applies to functions", IDENTIFIER_POINTER (name)); *no_add_attrs = true; } @@ -7414,21 +7415,21 @@ sh_handle_sp_switch_attribute (tree *node, tree name, tree args, { if (TREE_CODE (*node) != FUNCTION_DECL) { - warning (0, "%qs attribute only applies to functions", + warning (OPT_Wattributes, "%qs attribute only applies to functions", IDENTIFIER_POINTER (name)); *no_add_attrs = true; } else if (!pragma_interrupt) { /* The sp_switch attribute only has meaning for interrupt functions. */ - warning (0, "%qs attribute only applies to interrupt functions", - IDENTIFIER_POINTER (name)); + warning (OPT_Wattributes, "%qs attribute only applies to " + "interrupt functions", IDENTIFIER_POINTER (name)); *no_add_attrs = true; } else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST) { /* The argument must be a constant string. */ - warning (0, "%qs attribute argument not a string constant", + warning (OPT_Wattributes, "%qs attribute argument not a string constant", IDENTIFIER_POINTER (name)); *no_add_attrs = true; } @@ -7449,22 +7450,22 @@ sh_handle_trap_exit_attribute (tree *node, tree name, tree args, { if (TREE_CODE (*node) != FUNCTION_DECL) { - warning (0, "%qs attribute only applies to functions", + warning (OPT_Wattributes, "%qs attribute only applies to functions", IDENTIFIER_POINTER (name)); *no_add_attrs = true; } else if (!pragma_interrupt) { /* The trap_exit attribute only has meaning for interrupt functions. */ - warning (0, "%qs attribute only applies to interrupt functions", - IDENTIFIER_POINTER (name)); + warning (OPT_Wattributes, "%qs attribute only applies to " + "interrupt functions", IDENTIFIER_POINTER (name)); *no_add_attrs = true; } else if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST) { /* The argument must be a constant integer. */ - warning (0, "%qs attribute argument not an integer constant", - IDENTIFIER_POINTER (name)); + warning (OPT_Wattributes, "%qs attribute argument not an " + "integer constant", IDENTIFIER_POINTER (name)); *no_add_attrs = true; } else @@ -7515,36 +7516,11 @@ sh_cfun_interrupt_handler_p (void) != NULL_TREE); } -/* Like default_pch_valid_p, but only check certain target_flags. */ -const char * -sh_pch_valid_p (const void *data_p, size_t len) -{ -#ifdef TARGET_OPTIONS - /* ??? We have a copy of this in toplev.c, but it is static. */ - static const struct - { - const char *const prefix; - const char **const variable; - const char *const description; - const char *const value; - } - target_options[] = TARGET_OPTIONS; -#endif - - const char *data = (const char *)data_p; - const char *flag_that_differs = NULL; - size_t i; - int old_flags; +/* Implement TARGET_CHECK_PCH_TARGET_FLAGS. */ - /* -fpic and -fpie also usually make a PCH invalid. */ - if (data[0] != flag_pic) - return _("created and used with different settings of -fpic"); - if (data[1] != flag_pie) - return _("created and used with different settings of -fpie"); - data += 2; - - /* Check target_flags. */ - memcpy (&old_flags, data, sizeof (target_flags)); +static const char * +sh_check_pch_target_flags (int old_flags) +{ if ((old_flags ^ target_flags) & (MASK_SH1 | MASK_SH2 | MASK_SH3 | MASK_SH_E | MASK_HARD_SH4 | MASK_FPU_SINGLE | MASK_SH4)) @@ -7553,40 +7529,7 @@ sh_pch_valid_p (const void *data_p, size_t len) return _("created and used with different ABIs"); if ((old_flags ^ target_flags) & MASK_LITTLE_ENDIAN) return _("created and used with different endianness"); - - data += sizeof (target_flags); - len -= sizeof (target_flags); - - /* Check string options. */ -#ifdef TARGET_OPTIONS - for (i = 0; i < ARRAY_SIZE (target_options); i++) - { - const char *str = *target_options[i].variable; - size_t l; - if (! str) - str = ""; - l = strlen (str) + 1; - if (len < l || memcmp (data, str, l) != 0) - { - flag_that_differs = target_options[i].prefix; - goto make_message; - } - data += l; - len -= l; - } -#endif - return NULL; - - make_message: - { - char *r; - asprintf (&r, _("created and used with differing settings of '-m%s'"), - flag_that_differs); - if (r == NULL) - return _("out of memory"); - return r; - } } /* Predicates used by the templates. */ @@ -7607,301 +7550,6 @@ system_reg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) return 0; } -/* Returns 1 if OP can be source of a simple move operation. - Same as general_operand, but a LABEL_REF is valid, PRE_DEC is - invalid as are subregs of system registers. */ - -int -general_movsrc_operand (rtx op, enum machine_mode mode) -{ - if (GET_CODE (op) == MEM) - { - rtx inside = XEXP (op, 0); - if (GET_CODE (inside) == CONST) - inside = XEXP (inside, 0); - - if (GET_CODE (inside) == LABEL_REF) - return 1; - - if (GET_CODE (inside) == PLUS - && GET_CODE (XEXP (inside, 0)) == LABEL_REF - && GET_CODE (XEXP (inside, 1)) == CONST_INT) - return 1; - - /* Only post inc allowed. */ - if (GET_CODE (inside) == PRE_DEC) - return 0; - } - - if ((mode == QImode || mode == HImode) - && (GET_CODE (op) == SUBREG - && GET_CODE (XEXP (op, 0)) == REG - && system_reg_operand (XEXP (op, 0), mode))) - return 0; - - if (TARGET_SHMEDIA - && (GET_CODE (op) == PARALLEL || GET_CODE (op) == CONST_VECTOR) - && sh_rep_vec (op, mode)) - return 1; - if (TARGET_SHMEDIA && 1 - && GET_CODE (op) == SUBREG && GET_MODE (op) == mode - && SUBREG_REG (op) == const0_rtx && subreg_lowpart_p (op)) - /* FIXME */ abort (); /* return 1; */ - return general_operand (op, mode); -} - -/* Returns 1 if OP can be a destination of a move. - Same as general_operand, but no preinc allowed. */ - -int -general_movdst_operand (rtx op, enum machine_mode mode) -{ - /* Only pre dec allowed. */ - if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == POST_INC) - return 0; - if (mode == DImode && TARGET_SHMEDIA && GET_CODE (op) == SUBREG - && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) < 8 - && ! (high_life_started || reload_completed)) - return 0; - - return general_operand (op, mode); -} - -/* Returns 1 if OP is a normal arithmetic register. */ - -int -arith_reg_operand (rtx op, enum machine_mode mode) -{ - if (register_operand (op, mode)) - { - int regno; - - if (GET_CODE (op) == REG) - regno = REGNO (op); - else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG) - regno = REGNO (SUBREG_REG (op)); - else - return 1; - - return (regno != T_REG && regno != PR_REG - && ! TARGET_REGISTER_P (regno) - && (regno != FPUL_REG || TARGET_SH4) - && regno != MACH_REG && regno != MACL_REG); - } - /* Allow a no-op sign extension - compare LOAD_EXTEND_OP. - We allow SImode here, as not using an FP register is just a matter of - proper register allocation. */ - if (TARGET_SHMEDIA - && GET_MODE (op) == DImode && GET_CODE (op) == SIGN_EXTEND - && GET_MODE (XEXP (op, 0)) == SImode - && GET_CODE (XEXP (op, 0)) != SUBREG) - return register_operand (XEXP (op, 0), VOIDmode); -#if 0 /* Can't do this because of PROMOTE_MODE for unsigned vars. */ - if (GET_MODE (op) == SImode && GET_CODE (op) == SIGN_EXTEND - && GET_MODE (XEXP (op, 0)) == HImode - && GET_CODE (XEXP (op, 0)) == REG - && REGNO (XEXP (op, 0)) <= LAST_GENERAL_REG) - return register_operand (XEXP (op, 0), VOIDmode); -#endif - if (GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_INT - && GET_CODE (op) == SUBREG - && GET_MODE (SUBREG_REG (op)) == DImode - && GET_CODE (SUBREG_REG (op)) == SIGN_EXTEND - && GET_MODE (XEXP (SUBREG_REG (op), 0)) == SImode - && GET_CODE (XEXP (SUBREG_REG (op), 0)) != SUBREG) - return register_operand (XEXP (SUBREG_REG (op), 0), VOIDmode); - return 0; -} - -/* Like above, but for DImode destinations: forbid paradoxical DImode subregs, - because this would lead to missing sign extensions when truncating from - DImode to SImode. */ -int -arith_reg_dest (rtx op, enum machine_mode mode) -{ - if (mode == DImode && GET_CODE (op) == SUBREG - && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) < 8 - && TARGET_SHMEDIA) - return 0; - return arith_reg_operand (op, mode); -} - -/* Like arith_reg_operand, but for register source operands of narrow - logical SHMEDIA operations: forbid subregs of DImode / TImode regs. */ -int -logical_reg_operand (rtx op, enum machine_mode mode) -{ - if (TARGET_SHMEDIA - && GET_CODE (op) == SUBREG - && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4 - && mode != DImode) - return 0; - return arith_reg_operand (op, mode); -} - -int -int_gpr_dest (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - enum machine_mode op_mode = GET_MODE (op); - - if (GET_MODE_CLASS (op_mode) != MODE_INT - || GET_MODE_SIZE (op_mode) >= UNITS_PER_WORD) - return 0; - if (! reload_completed) - return 0; - return true_regnum (op) <= LAST_GENERAL_REG; -} - -int -fp_arith_reg_operand (rtx op, enum machine_mode mode) -{ - if (register_operand (op, mode)) - { - int regno; - - if (GET_CODE (op) == REG) - regno = REGNO (op); - else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG) - regno = REGNO (SUBREG_REG (op)); - else - return 1; - - return (regno >= FIRST_PSEUDO_REGISTER - || FP_REGISTER_P (regno)); - } - return 0; -} - -int -fp_arith_reg_dest (rtx op, enum machine_mode mode) -{ - if (mode == DImode && GET_CODE (op) == SUBREG - && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) < 8) - return 0; - return fp_arith_reg_operand (op, mode); -} - -/* Returns 1 if OP is a valid source operand for an arithmetic insn. */ - -int -arith_operand (rtx op, enum machine_mode mode) -{ - if (arith_reg_operand (op, mode)) - return 1; - - if (TARGET_SHMEDIA) - { - /* FIXME: We should be checking whether the CONST_INT fits in a - CONST_OK_FOR_I16 here, but this causes reload_cse to crash when - attempting to transform a sequence of two 64-bit sets of the - same register from literal constants into a set and an add, - when the difference is too wide for an add. */ - if (GET_CODE (op) == CONST_INT - || EXTRA_CONSTRAINT_C16 (op)) - return 1; - else if (GET_CODE (op) == TRUNCATE - && ! system_reg_operand (XEXP (op, 0), VOIDmode) - && (mode == VOIDmode || mode == GET_MODE (op)) - && (GET_MODE_SIZE (GET_MODE (op)) - < GET_MODE_SIZE (GET_MODE (XEXP (op, 0)))) - && (! FP_REGISTER_P (REGNO (XEXP (op, 0))) - || GET_MODE_SIZE (GET_MODE (op)) == 4)) - return register_operand (XEXP (op, 0), VOIDmode); - else - return 0; - } - else if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_I08 (INTVAL (op))) - return 1; - - return 0; -} - -/* Returns 1 if OP is a valid source operand for a compare insn. */ - -int -arith_reg_or_0_operand (rtx op, enum machine_mode mode) -{ - if (arith_reg_operand (op, mode)) - return 1; - - if (EXTRA_CONSTRAINT_Z (op)) - return 1; - - return 0; -} - -/* Return 1 if OP is a valid source operand for xor. */ - -int -xor_operand (rtx op, enum machine_mode mode) -{ - if (GET_CODE (op) == CONST_INT) - return (TARGET_SHMEDIA - ? (CONST_OK_FOR_I06 (INTVAL (op)) - || (no_new_pseudos && INTVAL (op) == 0xff)) - : CONST_OK_FOR_K08 (INTVAL (op))); - if (TARGET_SHMEDIA - && mode != DImode && GET_CODE (op) == SUBREG - && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4) - return 0; - return arith_reg_operand (op, mode); -} - -/* Return 1 if OP is a valid source operand for shmedia cmpgt / cmpgtu. */ -int -cmp_operand (rtx op, enum machine_mode mode) -{ - if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_N (INTVAL (op))) - return 1; - if (TARGET_SHMEDIA - && mode != DImode && GET_CODE (op) == SUBREG - && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4) - return 0; - return arith_reg_operand (op, mode); -} - -/* Returns 1 if OP is a valid source operand for a logical operation. */ - -int -logical_operand (rtx op, enum machine_mode mode) -{ - if (TARGET_SHMEDIA - && mode != DImode && GET_CODE (op) == SUBREG - && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4) - return 0; - - if (arith_reg_operand (op, mode)) - return 1; - - if (TARGET_SHMEDIA) - { - if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_I10 (INTVAL (op))) - return 1; - else - return 0; - } - else if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_K08 (INTVAL (op))) - return 1; - - return 0; -} - -int -and_operand (rtx op, enum machine_mode mode) -{ - if (logical_operand (op, mode)) - return 1; - - /* Check mshflo.l / mshflhi.l opportunities. */ - if (TARGET_SHMEDIA - && mode == DImode - && GET_CODE (op) == CONST_INT - && CONST_OK_FOR_J16 (INTVAL (op))) - return 1; - - return 0; -} - /* Nonzero if OP is a floating point value with value 0.0. */ int @@ -7950,33 +7598,6 @@ tertiary_reload_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) return code == MEM || (TARGET_SH4 && code == CONST_DOUBLE); } -int -fpscr_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == REG - && (REGNO (op) == FPSCR_REG - || (REGNO (op) >= FIRST_PSEUDO_REGISTER - && !(reload_in_progress || reload_completed))) - && GET_MODE (op) == PSImode); -} - -int -fpul_operand (rtx op, enum machine_mode mode) -{ - if (TARGET_SHMEDIA) - return fp_arith_reg_operand (op, mode); - - return (GET_CODE (op) == REG - && (REGNO (op) == FPUL_REG || REGNO (op) >= FIRST_PSEUDO_REGISTER) - && GET_MODE (op) == mode); -} - -int -symbol_ref_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == SYMBOL_REF); -} - /* Return the TLS type for TLS symbols, 0 for otherwise. */ int tls_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) @@ -7985,366 +7606,6 @@ tls_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) return 0; return SYMBOL_REF_TLS_MODEL (op); } - -int -commutative_float_operator (rtx op, enum machine_mode mode) -{ - if (GET_MODE (op) != mode) - return 0; - switch (GET_CODE (op)) - { - case PLUS: - case MULT: - return 1; - default: - break; - } - return 0; -} - -int -noncommutative_float_operator (rtx op, enum machine_mode mode) -{ - if (GET_MODE (op) != mode) - return 0; - switch (GET_CODE (op)) - { - case MINUS: - case DIV: - return 1; - default: - break; - } - return 0; -} - -int -unary_float_operator (rtx op, enum machine_mode mode) -{ - if (GET_MODE (op) != mode) - return 0; - switch (GET_CODE (op)) - { - case ABS: - case NEG: - case SQRT: - return 1; - default: - break; - } - return 0; -} - -int -binary_float_operator (rtx op, enum machine_mode mode) -{ - if (GET_MODE (op) != mode) - return 0; - switch (GET_CODE (op)) - { - case PLUS: - case MINUS: - case MULT: - case DIV: - return 1; - default: - break; - } - return 0; -} - -int -binary_logical_operator (rtx op, enum machine_mode mode) -{ - if (GET_MODE (op) != mode) - return 0; - switch (GET_CODE (op)) - { - case IOR: - case AND: - case XOR: - return 1; - default: - break; - } - return 0; -} - -int -equality_comparison_operator (rtx op, enum machine_mode mode) -{ - return ((mode == VOIDmode || GET_MODE (op) == mode) - && (GET_CODE (op) == EQ || GET_CODE (op) == NE)); -} - -int -greater_comparison_operator (rtx op, enum machine_mode mode) -{ - if (mode != VOIDmode && GET_MODE (op) != mode) - return 0; - switch (GET_CODE (op)) - { - case GT: - case GE: - case GTU: - case GEU: - return 1; - default: - return 0; - } -} - -int -less_comparison_operator (rtx op, enum machine_mode mode) -{ - if (mode != VOIDmode && GET_MODE (op) != mode) - return 0; - switch (GET_CODE (op)) - { - case LT: - case LE: - case LTU: - case LEU: - return 1; - default: - return 0; - } -} - -int -shift_operator (rtx op, enum machine_mode mode) -{ - if (mode != VOIDmode && GET_MODE (op) != mode) - return 0; - switch (GET_CODE (op)) - { - case ASHIFT: - case ASHIFTRT: - case LSHIFTRT: - return 1; - default: - return 0; - } -} - -int -logical_operator (rtx op, enum machine_mode mode) -{ - if (mode != VOIDmode && GET_MODE (op) != mode) - return 0; - switch (GET_CODE (op)) - { - case AND: - case IOR: - case XOR: - return 1; - default: - return 0; - } -} - -/* Accept pseudos and branch target registers. */ -int -target_reg_operand (rtx op, enum machine_mode mode) -{ - if (mode == VOIDmode - ? GET_MODE (op) != Pmode && GET_MODE (op) != PDImode - : mode != GET_MODE (op)) - return 0; - - if (GET_CODE (op) == SUBREG) - op = XEXP (op, 0); - - if (GET_CODE (op) != REG) - return 0; - - /* We must protect ourselves from matching pseudos that are virtual - register, because they will eventually be replaced with hardware - registers that aren't branch-target registers. */ - if (REGNO (op) > LAST_VIRTUAL_REGISTER - || TARGET_REGISTER_P (REGNO (op))) - return 1; - - return 0; -} - -/* Same as target_reg_operand, except that label_refs and symbol_refs - are accepted before reload. */ -int -target_operand (rtx op, enum machine_mode mode) -{ - if (mode != VOIDmode && mode != Pmode) - return 0; - - if ((GET_MODE (op) == Pmode || GET_MODE (op) == VOIDmode) - && EXTRA_CONSTRAINT_Csy (op)) - return ! reload_completed; - - return target_reg_operand (op, mode); -} - -int -mextr_bit_offset (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - HOST_WIDE_INT i; - - if (GET_CODE (op) != CONST_INT) - return 0; - i = INTVAL (op); - return i >= 1 * 8 && i <= 7 * 8 && (i & 7) == 0; -} - -int -extend_reg_operand (rtx op, enum machine_mode mode) -{ - return (GET_CODE (op) == TRUNCATE - ? arith_operand - : arith_reg_operand) (op, mode); -} - -int -trunc_hi_operand (rtx op, enum machine_mode mode) -{ - enum machine_mode op_mode = GET_MODE (op); - - if (op_mode != SImode && op_mode != DImode - && op_mode != V4HImode && op_mode != V2SImode) - return 0; - return extend_reg_operand (op, mode); -} - -int -extend_reg_or_0_operand (rtx op, enum machine_mode mode) -{ - return (GET_CODE (op) == TRUNCATE - ? arith_operand - : arith_reg_or_0_operand) (op, mode); -} - -int -minuend_operand (rtx op, enum machine_mode mode) -{ - return op == constm1_rtx || extend_reg_or_0_operand (op, mode); -} - -int -general_extend_operand (rtx op, enum machine_mode mode) -{ - return (GET_CODE (op) == TRUNCATE - ? arith_operand - : nonimmediate_operand) (op, mode); -} - -int -ua_address_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - if (GET_CODE (op) == PLUS - && (GET_CODE (XEXP (op, 1)) != CONST_INT - || ! CONST_OK_FOR_I06 (INTVAL (XEXP (op, 1))))) - return 0; - return address_operand (op, QImode); -} - -int -cache_address_operand (rtx op, enum machine_mode mode) -{ - if (GET_CODE (op) == PLUS) - { - if (GET_CODE (XEXP (op, 0)) != REG) - return 0; - if (GET_CODE (XEXP (op, 1)) != CONST_INT - || (INTVAL (XEXP (op, 1)) & 31)) - return 0; - } - else if (GET_CODE (op) != REG) - return 0; - return address_operand (op, mode); -} - -int -inqhi_operand (rtx op, enum machine_mode mode) -{ - if (GET_CODE (op) != TRUNCATE || mode != GET_MODE (op)) - return 0; - op = XEXP (op, 0); - /* Can't use true_regnum here because copy_cost wants to know about - SECONDARY_INPUT_RELOAD_CLASS. */ - return GET_CODE (op) == REG && FP_REGISTER_P (REGNO (op)); -} - -int -sh_rep_vec (rtx v, enum machine_mode mode) -{ - int i; - rtx x, y; - - if ((GET_CODE (v) != CONST_VECTOR && GET_CODE (v) != PARALLEL) - || (GET_MODE (v) != mode && mode != VOIDmode)) - return 0; - i = XVECLEN (v, 0) - 2; - x = XVECEXP (v, 0, i + 1); - if (GET_MODE_UNIT_SIZE (mode) == 1) - { - y = XVECEXP (v, 0, i); - for (i -= 2; i >= 0; i -= 2) - if (! rtx_equal_p (XVECEXP (v, 0, i + 1), x) - || ! rtx_equal_p (XVECEXP (v, 0, i), y)) - return 0; - } - else - for (; i >= 0; i--) - if (XVECEXP (v, 0, i) != x) - return 0; - return 1; -} - -/* Determine if V is a constant vector matching MODE with only one element - that is not a sign extension. Two byte-sized elements count as one. */ -int -sh_1el_vec (rtx v, enum machine_mode mode) -{ - int unit_size; - int i, last, least, sign_ix; - rtx sign; - - if (GET_CODE (v) != CONST_VECTOR - || (GET_MODE (v) != mode && mode != VOIDmode)) - return 0; - /* Determine numbers of last and of least significant elements. */ - last = XVECLEN (v, 0) - 1; - least = TARGET_LITTLE_ENDIAN ? 0 : last; - if (GET_CODE (XVECEXP (v, 0, least)) != CONST_INT) - return 0; - sign_ix = least; - if (GET_MODE_UNIT_SIZE (mode) == 1) - sign_ix = TARGET_LITTLE_ENDIAN ? 1 : last - 1; - if (GET_CODE (XVECEXP (v, 0, sign_ix)) != CONST_INT) - return 0; - unit_size = GET_MODE_UNIT_SIZE (GET_MODE (v)); - sign = (INTVAL (XVECEXP (v, 0, sign_ix)) >> (unit_size * BITS_PER_UNIT - 1) - ? constm1_rtx : const0_rtx); - i = XVECLEN (v, 0) - 1; - do - if (i != least && i != sign_ix && XVECEXP (v, 0, i) != sign) - return 0; - while (--i); - return 1; -} - -int -sh_const_vec (rtx v, enum machine_mode mode) -{ - int i; - - if (GET_CODE (v) != CONST_VECTOR - || (GET_MODE (v) != mode && mode != VOIDmode)) - return 0; - i = XVECLEN (v, 0) - 1; - for (; i >= 0; i--) - if (GET_CODE (XVECEXP (v, 0, i)) != CONST_INT) - return 0; - return 1; -} /* Return the destination address of a branch. */ @@ -8856,12 +8117,6 @@ mark_constant_pool_use (rtx x) return lab; } - -int -ua_offset (rtx c, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return GET_CODE (c) == CONST_INT && CONST_OK_FOR_I06 (INTVAL (c)); -} /* Return true if it's possible to redirect BRANCH1 to the destination of an unconditional jump BRANCH2. We only want to do this if the @@ -10126,8 +9381,8 @@ sh_register_move_cost (enum machine_mode mode, if (TARGET_SHMEDIA && ((srcclass) == TARGET_REGS || (srcclass) == SIBCALL_REGS)) { - if (*sh_gettrcost_str) - return atoi (sh_gettrcost_str); + if (sh_gettrcost >= 0) + return sh_gettrcost; else if (!TARGET_PT_FIXED) return 100; } @@ -10145,57 +9400,6 @@ sh_register_move_cost (enum machine_mode mode, return 2 * ((GET_MODE_SIZE (mode) + 3) / 4U); } -/* Like register_operand, but take into account that SHMEDIA can use - the constant zero like a general register. */ -int -sh_register_operand (rtx op, enum machine_mode mode) -{ - if (op == CONST0_RTX (mode) && TARGET_SHMEDIA) - return 1; - return register_operand (op, mode); -} - -int -cmpsi_operand (rtx op, enum machine_mode mode) -{ - if (GET_CODE (op) == REG && REGNO (op) == T_REG - && GET_MODE (op) == SImode - && TARGET_SH1) - return 1; - return arith_operand (op, mode); -} - -int -shift_count_reg_operand (rtx op, enum machine_mode mode) -{ - if ((GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND - || (GET_CODE (op) == SUBREG && SUBREG_BYTE (op) == 0)) - && (mode == VOIDmode || mode == GET_MODE (op)) - && GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0))) >= 6 - && GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_INT) - { - mode = VOIDmode; - do - op = XEXP (op, 0); - while ((GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND - || GET_CODE (op) == TRUNCATE) - && GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0))) >= 6 - && GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_INT); - - } - return arith_reg_operand (op, mode); -} - -int -shift_count_operand (rtx op, enum machine_mode mode) -{ - return (CONSTANT_P (op) - ? (GET_CODE (op) == CONST_INT - ? (unsigned) INTVAL (op) < GET_MODE_BITSIZE (mode) - : nonmemory_operand (op, mode)) - : shift_count_reg_operand (op, mode)); -} - static rtx emit_load_ptr (rtx, rtx); static rtx @@ -10598,27 +9802,6 @@ check_use_sfunc_addr (rtx insn, rtx reg) gcc_unreachable (); } -/* Returns 1 if OP is a MEM that can be source of a simple move operation. */ - -int -unaligned_load_operand (rtx op, enum machine_mode mode) -{ - rtx inside; - - if (GET_CODE (op) != MEM || GET_MODE (op) != mode) - return 0; - - inside = XEXP (op, 0); - - if (GET_CODE (inside) == POST_INC) - inside = XEXP (inside, 0); - - if (GET_CODE (inside) == REG) - return 1; - - return 0; -} - /* This function returns a constant rtx that represents pi / 2**15 in SFmode. it's used to scale SFmode angles, in radians, to a fixed-point signed 16.16-bit fraction of a full circle, i.e., 2*pi @@ -11290,11 +10473,6 @@ shmedia_prepare_call_address (rtx fnaddr, int is_sibcall) return fnaddr; } -const char *sh_multcost_str = ""; -const char *sh_gettrcost_str = ""; -const char *sh_div_str = ""; -const char *sh_divsi3_libfunc = ""; -const char *cut2_workaround_str = ""; enum sh_divide_strategy_e sh_div_strategy = SH_DIV_STRATEGY_DEFAULT; /* This defines the storage for the variable part of a -mboard= option. diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h index 92d8ce00696..e194759d388 100644 --- a/gcc/config/sh/sh.h +++ b/gcc/config/sh/sh.h @@ -174,7 +174,8 @@ do { \ #define TARGET_HARVARD (TARGET_HARD_SH4 || TARGET_SH5) /* Nonzero if a double-precision FPU is available. */ -#define TARGET_FPU_DOUBLE (TARGET_SH4 || TARGET_SH2A_DOUBLE) +#define TARGET_FPU_DOUBLE \ + ((target_flags & MASK_SH4) != 0 || TARGET_SH2A_DOUBLE) /* Nonzero if an FPU is available. */ #define TARGET_FPU_ANY (TARGET_SH2E || TARGET_FPU_DOUBLE) @@ -334,26 +335,6 @@ do { \ #define TARGET_DEFAULT \ (TARGET_CPU_DEFAULT | TARGET_ENDIAN_DEFAULT | TARGET_OPT_DEFAULT) -#ifndef SUBTARGET_OPTIONS -#define SUBTARGET_OPTIONS -#endif - -#define TARGET_OPTIONS \ -{ { "ultcost=", &sh_multcost_str, \ - N_("Cost to assume for a multiply insn"), 0 }, \ - { "gettrcost=", &sh_gettrcost_str, \ - N_("Cost to assume for gettr insn"), 0 }, \ - { "div=", &sh_div_str, \ - N_("division strategy, one of: call, call2, fp, inv, inv:minlat, inv20u, inv20l, inv:call, inv:call2, inv:fp"), 0 }, \ - { "divsi3_libfunc=", &sh_divsi3_libfunc, \ - N_("Specify name for 32 bit signed division function"), 0 }, \ - { "cut2-workaround", &cut2_workaround_str, \ - N_("Enable SH5 cut2 workaround"), "\1" }, \ - SUBTARGET_OPTIONS \ -} - -#define TARGET_SH5_CUT2_WORKAROUND (*cut2_workaround_str) - #ifndef SH_MULTILIB_CPU_DEFAULT #define SH_MULTILIB_CPU_DEFAULT "m1" #endif @@ -3265,73 +3246,6 @@ extern struct rtx_def *sp_switch; #define ADJUST_INSN_LENGTH(X, LENGTH) \ (LENGTH) += sh_insn_length_adjustment (X); -/* Define the codes that are matched by predicates in sh.c. */ -#define PREDICATE_CODES \ - {"and_operand", {SUBREG, REG, CONST_INT}}, \ - {"any_arith_reg_dest", {SUBREG, REG}}, \ - {"any_register_operand", {SUBREG, REG}}, \ - {"arith_operand", {SUBREG, REG, CONST_INT}}, \ - {"arith_reg_dest", {SUBREG, REG}}, \ - {"arith_reg_operand", {SUBREG, REG, SIGN_EXTEND}}, \ - {"arith_reg_or_0_operand", {SUBREG, REG, CONST_INT, CONST_VECTOR}}, \ - {"binary_float_operator", {PLUS, MINUS, MULT, DIV}}, \ - {"binary_logical_operator", {AND, IOR, XOR}}, \ - {"cache_address_operand", {PLUS, REG}}, \ - {"cmp_operand", {SUBREG, REG, CONST_INT}}, \ - {"cmpsi_operand", {SUBREG, REG, CONST_INT}}, \ - {"commutative_float_operator", {PLUS, MULT}}, \ - {"equality_comparison_operator", {EQ,NE}}, \ - {"extend_reg_operand", {SUBREG, REG, TRUNCATE}}, \ - {"extend_reg_or_0_operand", {SUBREG, REG, TRUNCATE, CONST_INT}}, \ - {"ext_dest_operand", {SUBREG, REG}}, \ - {"fp_arith_reg_dest", {SUBREG, REG}}, \ - {"fp_arith_reg_operand", {SUBREG, REG}}, \ - {"fpscr_operand", {REG}}, \ - {"fpul_operand", {REG}}, \ - {"general_extend_operand", {SUBREG, REG, MEM, TRUNCATE}}, \ - {"general_movsrc_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE, MEM, CONST }}, \ - {"general_movdst_operand", {SUBREG, REG, MEM}}, \ - {"unaligned_load_operand", {MEM}}, \ - {"greater_comparison_operator", {GT,GE,GTU,GEU}}, \ - {"inqhi_operand", {TRUNCATE}}, \ - {"int_gpr_dest", {SUBREG, REG}}, \ - {"less_comparison_operator", {LT,LE,LTU,LEU}}, \ - {"logical_operand", {SUBREG, REG, CONST_INT}}, \ - {"logical_operator", {AND,IOR,XOR}}, \ - {"logical_reg_operand", {SUBREG, REG}}, \ - {"mextr_bit_offset", {CONST_INT}}, \ - {"minuend_operand", {SUBREG, REG, TRUNCATE, CONST_INT}}, \ - {"noncommutative_float_operator", {MINUS, DIV}}, \ - {"sh_const_vec", {CONST_VECTOR}}, \ - {"sh_1el_vec", {CONST_VECTOR}}, \ - {"sh_register_operand", {REG, SUBREG, CONST_INT}}, \ - {"sh_rep_vec", {CONST_VECTOR}}, \ - {"shift_count_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \ - LABEL_REF, SUBREG, REG, ZERO_EXTEND, SIGN_EXTEND}},\ - {"shift_count_reg_operand", {SUBREG, REG, ZERO_EXTEND, SIGN_EXTEND}}, \ - {"shift_operator", {ASHIFT, ASHIFTRT, LSHIFTRT}}, \ - {"symbol_ref_operand", {SYMBOL_REF}}, \ - {"target_operand", {SUBREG, REG, LABEL_REF, SYMBOL_REF, CONST, UNSPEC}},\ - {"target_reg_operand", {SUBREG, REG}}, \ - {"trunc_hi_operand", {SUBREG, REG, TRUNCATE}}, \ - {"ua_address_operand", {SUBREG, REG, PLUS}}, \ - {"ua_offset", {CONST_INT}}, \ - {"unary_float_operator", {ABS, NEG, SQRT}}, \ - {"xor_operand", {SUBREG, REG, CONST_INT}}, \ - -#define SPECIAL_MODE_PREDICATES \ - "any_arith_reg_dest", \ - "any_register_operand", \ - "int_gpr_dest", \ - "target_operand", \ - "target_reg_operand", \ - "trunc_hi_operand", \ - /* This line intentionally left blank. */ - -#define any_register_operand register_operand -#define any_arith_reg_dest arith_reg_dest -#define ext_dest_operand arith_reg_operand - /* Define this macro if it is advisable to hold scalars in registers in a wider mode than that declared by the program. In such cases, the value is constrained to be within the bounds of the declared @@ -3460,12 +3374,6 @@ extern struct rtx_def *sp_switch; #define SIMULTANEOUS_PREFETCHES 2 -extern const char *sh_multcost_str; -extern const char *sh_gettrcost_str; -extern const char *sh_div_str; -extern const char *sh_divsi3_libfunc; -extern const char *cut2_workaround_str; - /* FIXME: middle-end support for highpart optimizations is missing. */ #define high_life_started reload_in_progress diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index f05be16d92d..4b53129a419 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -1106,7 +1106,7 @@ rtx set1, set2; rtx replacements[4]; - /* We want to replace occurences of operands[0] with operands[1] and + /* We want to replace occurrences of operands[0] with operands[1] and operands[2] with operands[0] in operands[4]/operands[5]. Doing just two replace_rtx calls naively would result in the second replacement undoing all that the first did if operands[1] and operands[2] @@ -11613,7 +11613,7 @@ mov.l\\t1f,r0\\n\\ "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64" "* { - static char templ[16]; + static char templ[21]; sprintf (templ, \"mextr%d\\t%%N1, %%N2, %%0\", (int) INTVAL (operands[3]) >> 3); @@ -11630,7 +11630,7 @@ mov.l\\t1f,r0\\n\\ "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64" "* { - static char templ[16]; + static char templ[21]; sprintf (templ, \"mextr%d\\t%%N2, %%N1, %%0\", (int) INTVAL (operands[4]) >> 3); diff --git a/gcc/config/sh/sh.opt b/gcc/config/sh/sh.opt index c3c659f95d2..553a5576eb0 100644 --- a/gcc/config/sh/sh.opt +++ b/gcc/config/sh/sh.opt @@ -148,13 +148,29 @@ mbigtable Target Report RejectNegative Mask(BIGTABLE) Generate 32-bit offsets in switch tables +mcut2-workaround +Target RejectNegative Var(TARGET_SH5_CUT2_WORKAROUND) +Enable SH5 cut2 workaround + mdalign Target Report RejectNegative Mask(ALIGN_DOUBLE) Align doubles at 64-bit boundaries +mdiv= +Target RejectNegative Joined Var(sh_div_str) Init("") +Division strategy, one of: call, call2, fp, inv, inv:minlat, inv20u, inv20l, inv:call, inv:call2, inv:fp + +mdivsi3_libfunc= +Target RejectNegative Joined Var(sh_divsi3_libfunc) Init("") +Specify name for 32 bit signed division function + mfmovd Target RejectNegative Mask(FMOVD) Undocumented +mgettrcost= +Target RejectNegative Joined UInteger Var(sh_gettrcost) Init(-1) +Cost to assume for gettr insn + mhitachi Target Report RejectNegative Mask(HITACHI) Follow Renesas (formerly Hitachi) / SuperH calling conventions @@ -209,6 +225,10 @@ mspace Target Report RejectNegative Mask(SMALLCODE) Deprecated. Use -Os instead +multcost= +Target RejectNegative Joined UInteger Var(sh_multcost) Init(-1) +Cost to assume for a multiply insn + musermode Target Report RejectNegative Mask(USERMODE) Generate library function call to invalidate instruction cache entries after fixing trampoline diff --git a/gcc/config/sh/symbian-pre.h b/gcc/config/sh/symbian-pre.h index 1d882bec0c3..b1f7ab69061 100644 --- a/gcc/config/sh/symbian-pre.h +++ b/gcc/config/sh/symbian-pre.h @@ -1,7 +1,7 @@ /* Definitions for the Symbian OS running on an SH part. This file is included before any other target specific headers. - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. Contributed by Red Hat. This file is part of GCC. diff --git a/gcc/config/sh/symbian.c b/gcc/config/sh/symbian.c index b3e8287a66b..cc518419792 100644 --- a/gcc/config/sh/symbian.c +++ b/gcc/config/sh/symbian.c @@ -144,7 +144,8 @@ sh_symbian_dllimport_p (tree decl) { /* Don't warn about artificial methods. */ if (!DECL_ARTIFICIAL (decl)) - warning (0, "%H function '%D' is defined after prior declaration as dllimport: attribute ignored", + warning (OPT_Wattributes, "%H function '%D' is defined after prior " + "declaration as dllimport: attribute ignored", & DECL_SOURCE_LOCATION (decl), decl); return false; } @@ -155,7 +156,8 @@ sh_symbian_dllimport_p (tree decl) else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl)) { if (extra_warnings) - warning (0, "%Hinline function '%D' is declared as dllimport: attribute ignored.", + warning (OPT_Wattributes, "%Hinline function '%D' is declared as " + "dllimport: attribute ignored.", & DECL_SOURCE_LOCATION (decl), decl); return false; } @@ -403,14 +405,14 @@ sh_symbian_handle_dll_attribute (tree *pnode, tree name, tree args, | (int) ATTR_FLAG_FUNCTION_NEXT | (int) ATTR_FLAG_ARRAY_NEXT)) { - warning (0, "%qs attribute ignored", attr); + warning (OPT_Wattributes, "%qs attribute ignored", attr); *no_add_attrs = true; return tree_cons (name, args, NULL_TREE); } if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE) { - warning (0, "%qs attribute ignored", attr); + warning (OPT_Wattributes, "%qs attribute ignored", attr); *no_add_attrs = true; } diff --git a/gcc/config/sh/ushmedia.h b/gcc/config/sh/ushmedia.h index 514ddff35b5..98e9a5bd365 100644 --- a/gcc/config/sh/ushmedia.h +++ b/gcc/config/sh/ushmedia.h @@ -720,14 +720,14 @@ sh_media_ADDZ_L (unsigned int mm, unsigned int mn) return mm + mn; } -/* NOP and Synchronization instrinsics not implemented here. */ +/* NOP and Synchronization intrinsics not implemented here. */ static __inline__ void sh_media_PREFO(void *mm, int s) { __builtin_sh_media_PREFO (mm + s, 0, 0); } -/* Event Handling instrinsics not implemented here. */ +/* Event Handling intrinsics not implemented here. */ /* Old asm stuff */ |