This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

do_global_ctors_aux vs. pt placement (Was: Re: sh-elf-4_1-branch created)


Kaz Kojima wrote:



I tried -fno-branch-target-load-optimize but it doesn't solve that
case unfortunately.


I've tried the reload pattern approach, but this was not really effective. If you are curious, I have
attached it as ptabs-diff-20050413-reload.


The problem actually occurs during register allocation, so doing anything at reload time is to late.
I have now followed a different approach, i.e. using PDImode targets in the call insns, and
showing a specific ptabs pattern with side effects, if the target might be dangerous.
See the attachment ptabs-diff-20050413-PDI . I'm regtesting this now.
I've checked that the ctor testcase works with this patch. There is also an option to tell the
compiler not to worry about trapping pt insns: -mpt-fixed. I've also made this disable the
inflation of the gettr cost. The funny thing is, the ctor test also works for the current
architecture with the -mpt-fixed option. The local-alloc dump shows that the register class
preferencing is different. If i use -mpt-fixed -mgettrcost=100, the ctor testcase again gets
the ptabs hoisted into the basic block with the test against -1 - not by pt migration, but
by allocating the pseudo that holds the value loaded from memory into a target register.


? predicates.md
Index: sh-modes.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh-modes.def,v
retrieving revision 1.3
diff -p -u -F^( -r1.3 sh-modes.def
--- sh-modes.def	17 Oct 2004 18:09:46 -0000	1.3
+++ sh-modes.def	13 Apr 2005 18:03:00 -0000
@@ -31,3 +31,7 @@ VECTOR_MODES (FLOAT, 16);     /*       V
 VECTOR_MODE (INT, DI, 4);     /*                 V4DI */
 VECTOR_MODE (INT, DI, 8);     /*                 V8DI */
 VECTOR_MODE (FLOAT, SF, 16);  /*                V16SF */
+
+/* A dummy mode used by dummy registers in dummy secondary reloads to drive
+   reload expanders for SHmedia trapping ptabs.  */
+CC_MODE (CC_DUMMY);
Index: sh-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh-protos.h,v
retrieving revision 1.60.36.1
diff -p -u -F^( -r1.60.36.1 sh-protos.h
--- sh-protos.h	8 Apr 2005 17:41:26 -0000	1.60.36.1
+++ sh-protos.h	13 Apr 2005 18:03:00 -0000
@@ -165,6 +165,7 @@ extern rtx replace_n_hard_rtx (rtx, rtx 
 extern int shmedia_cleanup_truncate (rtx *, void *);
 
 extern int sh_contains_memref_p (rtx);
+extern enum reg_class sh_special_reg_class_from_constraint (const char *str);
 
 #endif /* ! GCC_SH_PROTOS_H */
 
Index: sh.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.c,v
retrieving revision 1.319.2.2
diff -p -u -F^( -r1.319.2.2 sh.c
--- sh.c	11 Apr 2005 20:31:24 -0000	1.319.2.2
+++ sh.c	13 Apr 2005 18:03:01 -0000
@@ -766,6 +766,12 @@ print_operand (FILE *stream, rtx x, int 
 	     but, because Pmode is SImode, the address ends up with a
 	     subreg:SI of the DImode register.  Maybe reload should be
 	     fixed so as to apply alter_subreg to such loads?  */
+	case IF_THEN_ELSE:
+	  gcc_assert (trapping_target_operand (x, VOIDmode));
+	  x = XEXP (x, 2);
+	  if (REG_P (x))
+	    goto reg;
+	  /* Fall through.  */
 	case SUBREG:
 	  if (SUBREG_BYTE (x) != 0
 	      || GET_CODE (SUBREG_REG (x)) != REG)
@@ -6091,7 +6097,10 @@ sh_expand_epilogue (bool sibcall_p)
 		tmp_pnt = schedule.temps;
 	    }
 
-	  insn = emit_move_insn (reg_rtx, mem_rtx);
+	  if (TARGET_REGISTER_P (reg))
+	    insn = emit_insn (gen_ptabs (reg_rtx, mem_rtx));
+	  else
+	    insn = emit_move_insn (reg_rtx, mem_rtx);
 	  if (reg == PR_MEDIA_REG && sh_media_register_for_return () >= 0)
 	    /* This is dead, unless we return with a sibcall.  */
 	    REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
@@ -7551,6 +7560,10 @@ general_movsrc_operand (rtx op, enum mac
       && (GET_CODE (op) == PARALLEL || GET_CODE (op) == CONST_VECTOR)
       && sh_rep_vec (op, mode))
     return 1;
+  if (TARGET_SHMEDIA
+      && (reload_in_progress || reload_completed)
+      && trapping_target_operand (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))
@@ -11142,8 +11155,22 @@ sh_contains_memref_p (rtx insn)
   return for_each_rtx (&PATTERN (insn), &sh_contains_memref_p_1, NULL);
 }
 
+enum reg_class
+sh_special_reg_class_from_constraint (const char *str)
+{
+  /* Register class to use for non-trapping ptabs/ptrel.  */
+  if (str[1] == 't' && str[2] == 'r')
+    return TARGET_PT_FIXED ? TARGET_REGS : NO_REGS;
+  /* reload_insi output */
+  if (str[1] == 's' && str[2] == 'o')
+    return TARGET_SH1 ? FPUL_REGS : TARGET_REGS;
+  /* reload_insi clobber.  Also used for reload_indi.  */
+  if (str[1] == 's' && str[2] == 'c')
+    return TARGET_SH1 ? R0_REGS : DUMMY_REGS;
+}
+
 const char *sh_multcost_str = "";
-const char *sh_gettrcost_str = "100";
+const char *sh_gettrcost_str = 0;
 const char *sh_div_str = "";
 const char *cut2_workaround_str = "";
 enum sh_divide_strategy_e sh_div_strategy = SH_DIV_CALL;
Index: sh.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.h,v
retrieving revision 1.262.2.2
diff -p -u -F^( -r1.262.2.2 sh.h
--- sh.h	11 Apr 2005 14:18:31 -0000	1.262.2.2
+++ sh.h	13 Apr 2005 18:03:01 -0000
@@ -120,6 +120,8 @@ do { \
     {									\
       regno_reg_class[FIRST_GENERAL_REG] = GENERAL_REGS;		\
       CLEAR_HARD_REG_SET (reg_class_contents[FP0_REGS]);		\
+      if (!TARGET_PT_FIXED && !sh_gettrcost_str)			\
+	sh_gettrcost_str = "100";					\
       regno_reg_class[FIRST_FP_REG] = FP_REGS;				\
     }									\
   if (flag_pic)								\
@@ -180,6 +182,7 @@ extern int target_flags;
 #define HARD_SH2A_BIT	(1<<17)
 #define HARD_SH2A_DOUBLE_BIT	(1<<18)
 #define INDEXED_ADDRESS_BIT (1<<19)
+#define PT_FIXED_BIT	(1<<21)
 #define ADJUST_UNROLL_BIT (1<<20)
 
 /* Nonzero if this is an ELF target - compile time only */
@@ -337,7 +340,9 @@ extern int target_flags;
 #define TARGET_DIVIDE_INV_CALL (sh_div_strategy == SH_DIV_INV_CALL)
 #define TARGET_DIVIDE_INV_CALL2 (sh_div_strategy == SH_DIV_INV_CALL2)
 
+/* Target macros pertaining to SHmedia architecture bugs.  */
 #define TARGET_ALLOW_INDEXED_ADDRESS (target_flags & INDEXED_ADDRESS_BIT)
+#define TARGET_PT_FIXED (target_flags & PT_FIXED_BIT)
 
 #define TARGET_ADJUST_UNROLL (target_flags & ADJUST_UNROLL_BIT)
 
@@ -603,7 +608,9 @@ extern int target_flags;
   {"relax",	RELAX_BIT, "Shorten address references during linking" }, \
   {"space", 	SPACE_BIT, "Deprecated. Use -Os instead" },		\
   {"usermode",	USERMODE_BIT, "Generate library function call to invalidate instruction cache entries after fixing trampoline" }, \
-  {"indexed-addressing", INDEXED_ADDRESS_BIT, "Enable the use of the indexed addressing mode for SHmedia32"}, \
+  {"indexed-addressing", INDEXED_ADDRESS_BIT, "Enable the use of the indexed addressing mode for SHmedia32/SHcompact"}, \
+  {"pt-fixed",	PT_FIXED_BIT, "Assume pt* instructions won't trap"}, \
+  {"no-pt-fixed", -PT_FIXED_BIT, "Assume pt* instructions may trap"}, \
   {"no-indexed-addressing", -INDEXED_ADDRESS_BIT, "Disable the use of the indexed addressing mode for SHmedia32"}, \
   {"adjust-unroll", ADJUST_UNROLL_BIT, "Throttle unrolling to avoid thrashing target registers unless the unroll benefit outweighs this"}, \
   {"no-adjust-unroll", -ADJUST_UNROLL_BIT, "Don't throttle unrolling"},	\
@@ -1166,7 +1173,7 @@ extern char sh_register_names[][MAX_REGI
   "tr0",  "tr1",  "tr2",  "tr3",  "tr4",  "tr5",  "tr6",  "tr7", 	\
   "xd0",  "xd2",  "xd4",  "xd6",  "xd8",  "xd10", "xd12", "xd14",	\
   "gbr",  "ap",	  "pr",   "t",    "mach", "macl", "fpul", "fpscr",	\
-  "rap"									\
+  "rap",  "dummy"							\
 }
 
 #define REGNAMES_ARR_INDEX_1(index) \
@@ -1284,7 +1291,8 @@ extern char sh_additional_register_names
   (SHMEDIA_REGISTER_P (REGNO) || XD_REGISTER_P (REGNO) \
    || (REGNO) == AP_REG || (REGNO) == RAP_REG \
    || (TARGET_SH1 && (SPECIAL_REGISTER_P (REGNO) || (REGNO) == PR_REG)) \
-   || (TARGET_SH2E && (REGNO) == FPUL_REG))
+   || (TARGET_SH2E && (REGNO) == FPUL_REG) \
+   || (REGNO) == DUMMY_REG)
 
 /* The mode that should be generally used to store a register by
    itself in the stack, or to load it back.  */
@@ -1295,7 +1303,7 @@ extern char sh_additional_register_names
    ? DImode \
    : SImode)
 
-#define FIRST_PSEUDO_REGISTER 153
+#define FIRST_PSEUDO_REGISTER 154
 
 /* 1 for registers that have pervasive standard uses
    and are not available for the register allocator.
@@ -1334,6 +1342,8 @@ extern char sh_additional_register_names
   1,      1,      1,      1,      1,      1,      0,      1,		\
 /*"rap" */								\
   1,									\
+/* dummy register */							\
+  0,									\
 }
 
 /* 1 for registers not available across function calls.
@@ -1374,6 +1384,8 @@ extern char sh_additional_register_names
   1,      1,      1,      1,      1,      1,      1,      1,		\
 /*"rap" */								\
   1,									\
+/* dummy register */							\
+  1,									\
 }
 
 /* CONDITIONAL_REGISTER_USAGE might want to make a register call-used, yet
@@ -1452,6 +1464,7 @@ extern char sh_additional_register_names
    ? ((MODE) == DImode || (MODE) == SImode) \
    : (REGNO) == PR_REG ? (MODE) == SImode \
    : (REGNO) == FPSCR_REG ? (MODE) == PSImode \
+   : (REGNO) == DUMMY_REG ? (MODE) == CC_DUMMYmode \
    : 1)
 
 /* Value is 1 if it is a good idea to tie two pseudo registers
@@ -1616,6 +1629,7 @@ enum reg_class
   FPSCR_REGS,
   GENERAL_FP_REGS,
   TARGET_REGS,
+  DUMMY_REGS,
   ALL_REGS,
   LIM_REG_CLASSES
 };
@@ -1640,6 +1654,7 @@ enum reg_class
   "FPSCR_REGS",		\
   "GENERAL_FP_REGS",	\
   "TARGET_REGS",	\
+  "DUMMY_REGS",		\
   "ALL_REGS",		\
 }
 
@@ -1679,8 +1694,10 @@ enum reg_class
   { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0102ff00 },	\
 /* TARGET_REGS:  */							\
   { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000ff },	\
+/* DUMMY_REGS:  */							\
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x020000ff },	\
 /* ALL_REGS:  */							\
-  { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff },	\
+  { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x03ffffff },	\
 }
 
 /* The same information, inverted:
@@ -1741,9 +1758,11 @@ extern enum reg_class regno_reg_class[FI
    description.  */
 extern enum reg_class reg_class_from_letter[];
 
-/* We might use 'Rxx' constraints in the future for exotic reg classes.*/
+/* We might use more 'Rxx' constraints in the future for exotic reg classes.*/
 #define REG_CLASS_FROM_CONSTRAINT(C, STR) \
-  (ISLOWER (C) ? reg_class_from_letter[(C)-'a'] : NO_REGS )
+  (ISLOWER (C) ? reg_class_from_letter[(C)-'a'] \
+   : (C) == 'R' ? sh_special_reg_class_from_constraint (STR) \
+   : NO_REGS )
 
 /* Overview of uppercase letter constraints:
    A: Addresses (constraint len == 3)
@@ -1752,6 +1771,8 @@ extern enum reg_class reg_class_from_let
    Bxx: miscellaneous constraints
     Bsc: SCRATCH - for the scratch register in movsi_ie in the
 	 fldi0 / fldi0 cases
+    Btt: potentially Trapping Target, used as the source for ptabs.
+    Bsi: reload_insi input
    C: Constants other than only CONST_INT (constraint len == 3)
     C16: 16 bit constant, literal or symbolic
     Csy: label or symbol
@@ -1767,6 +1788,9 @@ extern enum reg_class reg_class_from_let
     P27: 1 | 2 | 8 | 16
    Q: pc relative load operand
    Rxx: reserved for exotic register classes.
+    Rtr: target registers which can hold arbitrary values.
+    Rso: reload_insi output
+    Rsc: reload_insi clobber
    S: extra memory (storage) constraints (constraint len == 3)
     Sua: unaligned memory operations
    W: vector
@@ -1775,30 +1799,11 @@ extern enum reg_class reg_class_from_let
    unused CONST_INT constraint letters: LO
    unused EXTRA_CONSTRAINT letters: D T U Y */
 
-#if 1 /* check that the transition went well.  */
-#define CONSTRAINT_LEN(C,STR) \
-  (((C) == 'L' || (C) == 'O' || (C) == 'D' || (C) == 'T' || (C) == 'U' \
-    || (C) == 'Y' \
-    || ((C) == 'I' \
-        && (((STR)[1] != '0' && (STR)[1] != '1' && (STR)[1] != '2') \
-	    || (STR)[2] < '0' || (STR)[2] > '9')) \
-    || ((C) == 'B' && ((STR)[1] != 's' || (STR)[2] != 'c')) \
-    || ((C) == 'J' && ((STR)[1] != '1' || (STR)[2] != '6')) \
-    || ((C) == 'K' && ((STR)[1] != '0' || (STR)[2] != '8')) \
-    || ((C) == 'P' && ((STR)[1] != '2' || (STR)[2] != '7'))) \
-   ? -1 \
-   : ((C) == 'A' || (C) == 'B' || (C) == 'C' \
-      || (C) == 'I' || (C) == 'J' || (C) == 'K' || (C) == 'P' \
-      || (C) == 'R' || (C) == 'S') \
-   ? 3 \
-   : DEFAULT_CONSTRAINT_LEN ((C), (STR)))
-#else
 #define CONSTRAINT_LEN(C,STR) \
   (((C) == 'A' || (C) == 'B' || (C) == 'C' \
     || (C) == 'I' || (C) == 'J' || (C) == 'K' || (C) == 'P' \
     || (C) == 'R' || (C) == 'S') \
    ? 3 : DEFAULT_CONSTRAINT_LEN ((C), (STR)))
-#endif
 
 /* The letters I, J, K, L and M in a register constraint string
    can be used to stand for particular ranges of immediate operands.
@@ -1883,7 +1888,7 @@ ((C) == 'G' ? (fp_zero_operand (VALUE) &
    ? GENERAL_REGS \
    : (CLASS)) \
 
-#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS,MODE,X) \
+#define SECONDARY_INOUT_RELOAD_CLASS(CLASS,MODE,X,ELSE) \
   ((((REGCLASS_HAS_FP_REG (CLASS) 					\
       && (GET_CODE (X) == REG						\
       && (GENERAL_OR_AP_REGISTER_P (REGNO (X))				\
@@ -1904,18 +1909,26 @@ ((C) == 'G' ? (fp_zero_operand (VALUE) &
 		  || REGNO (X) == T_REG					\
 		  || system_reg_operand (X, VOIDmode)))))		\
    ? GENERAL_REGS							\
-   : ((CLASS) == TARGET_REGS						\
-      || (TARGET_SHMEDIA && (CLASS) == SIBCALL_REGS))			\
-   ? ((target_operand ((X), (MODE))					\
-       && ! target_reg_operand ((X), (MODE)))				\
-      ? NO_REGS : GENERAL_REGS)						\
+   : (((CLASS) == TARGET_REGS						\
+       || (TARGET_SHMEDIA && (CLASS) == SIBCALL_REGS))			\
+      && !EXTRA_CONSTRAINT_Csy (X)					\
+      && (GET_CODE (X) != REG || ! GENERAL_REGISTER_P (REGNO (X))))	\
+   ? GENERAL_REGS							\
    : (((CLASS) == MAC_REGS || (CLASS) == PR_REGS)			\
       && GET_CODE (X) == REG && ! GENERAL_REGISTER_P (REGNO (X))	\
       && (CLASS) != REGNO_REG_CLASS (REGNO (X)))			\
    ? GENERAL_REGS							\
    : ((CLASS) != GENERAL_REGS && GET_CODE (X) == REG			\
       && TARGET_REGISTER_P (REGNO (X)))					\
-   ? GENERAL_REGS : NO_REGS)
+   ? GENERAL_REGS : (ELSE))
+
+#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS,MODE,X) \
+ (SECONDARY_INOUT_RELOAD_CLASS(CLASS,MODE,X,				\
+  (!TARGET_PT_FIXED							\
+   && GET_CODE (X) == REG && TARGET_REGISTER_P (REGNO (X))		\
+   && CLASS == GENERAL_REGS)						\
+  ? DUMMY_REGS								\
+  : NO_REGS))
 
 #define SECONDARY_INPUT_RELOAD_CLASS(CLASS,MODE,X)  \
   ((REGCLASS_HAS_FP_REG (CLASS) 					\
@@ -1950,7 +1963,10 @@ ((C) == 'G' ? (fp_zero_operand (VALUE) &
    : (TARGET_SHMEDIA && (CLASS) == GENERAL_REGS				\
       && (GET_CODE (X) == LABEL_REF || PIC_DIRECT_ADDR_P (X)))		\
    ? TARGET_REGS							\
-   : SECONDARY_OUTPUT_RELOAD_CLASS((CLASS),(MODE),(X)))
+   : (!TARGET_PT_FIXED && (CLASS) == TARGET_REGS			\
+      && GET_CODE (X) == REG && GENERAL_REGISTER_P (REGNO (X)))		\
+   ? DUMMY_REGS								\
+   : SECONDARY_INOUT_RELOAD_CLASS((CLASS),(MODE),(X), NO_REGS))
 
 /* Return the maximum number of consecutive registers
    needed to represent mode MODE in a register of class CLASS.
@@ -2573,8 +2589,15 @@ struct sh_args {
    operand is not SCRATCH (i.e. REG) then R0 is probably being
    used, hence mova is being used, hence do not select this pattern */
 #define EXTRA_CONSTRAINT_Bsc(OP)    (GET_CODE(OP) == SCRATCH)
+#define EXTRA_CONSTRAINT_Btt(OP) trapping_target_operand ((OP), VOIDmode)
+#define EXTRA_CONSTRAINT_Bsi(OP) \
+  (TARGET_SH1 \
+   ? immediate_operand ((OP), VOIDmode) \
+   : register_operand ((OP), VOIDmode) && GENERAL_REGISTER_P (true_regnum (OP)))
 #define EXTRA_CONSTRAINT_B(OP, STR) \
   ((STR)[1] == 's' && (STR)[2] == 'c' ? EXTRA_CONSTRAINT_Bsc (OP) \
+   : (STR)[1] == 't' && (STR)[2] == 't' ? EXTRA_CONSTRAINT_Btt (OP) \
+   : (STR)[1] == 's' && (STR)[2] == 'i' ? EXTRA_CONSTRAINT_Bsi (OP) \
    : 0)
 
 /* The `C16' constraint is a 16-bit constant, literal or symbolic.  */
@@ -3545,7 +3568,7 @@ extern struct rtx_def *sp_switch;
   {"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_movsrc_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE, MEM, CONST, IF_THEN_ELSE }}, \
   {"general_movdst_operand", {SUBREG, REG, MEM}},			\
   {"unaligned_load_operand", {MEM}},					\
   {"greater_comparison_operator", {GT,GE,GTU,GEU}},			\
Index: sh.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.md,v
retrieving revision 1.191.2.1
diff -p -u -F^( -r1.191.2.1 sh.md
--- sh.md	8 Apr 2005 17:41:31 -0000	1.191.2.1
+++ sh.md	13 Apr 2005 18:03:01 -0000
@@ -78,6 +78,7 @@ (define_constants [
   (MACL_REG	149)
   (FPUL_REG	150)
   (RAP_REG	152)
+  (DUMMY_REG    153)
 
   (FPSCR_REG	151)
 
@@ -444,6 +445,8 @@ (include "sh1.md")
 (include "shmedia.md")
 (include "sh4.md")
 
+(include "predicates.md")
+
 ;; Definitions for filling delay slots
 
 (define_attr "needs_delay_slot" "yes,no" (const_string "no"))
@@ -4839,9 +4842,9 @@ (define_insn_and_split "load_ra"
 ;; point registers for storing integer values.
 (define_insn "*movsi_media"
   [(set (match_operand:SI 0 "general_movdst_operand"
-	        "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b")
+	        "=r,r,r,r,m,f?,m,f?,r,f?,*Rtr,*b,r,b")
 	(match_operand:SI 1 "general_movsrc_operand"
-	 "r,I16C16,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
+	 "r,I16C16,nCpg,m,rZ,m,f?,rZ,f?,f?,r,Btt,*b,Csy"))]
   "TARGET_SHMEDIA_FPU
    && (register_operand (operands[0], SImode)
        || sh_register_operand (operands[1], SImode)
@@ -4858,10 +4861,11 @@ (define_insn "*movsi_media"
 	fmov.sl	%1, %0
 	fmov.s	%1, %0
 	ptabs	%1, %0
+	ptabs	%1, %0
 	gettr	%1, %0
 	pt	%1, %0"
-  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,fload_media,fstore_media,fload_media,fpconv_media,fmove_media,ptabs_media,gettr_media,pt_media")
-   (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")
+  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,fload_media,fstore_media,fload_media,fpconv_media,fmove_media,ptabs_media,ptabs_media,gettr_media,pt_media")
+   (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,4,12")
    (set (attr "highpart")
 	(cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
 	       (const_string "user")]
@@ -4869,9 +4873,9 @@ (define_insn "*movsi_media"
 
 (define_insn "*movsi_media_nofpu"
   [(set (match_operand:SI 0 "general_movdst_operand"
-	        "=r,r,r,r,m,*b,r,*b")
+	        "=r,r,r,r,m,*Rtr,*b,r,*b")
 	(match_operand:SI 1 "general_movsrc_operand"
-	 "r,I16C16,nCpg,m,rZ,r,*b,Csy"))]
+	 "r,I16C16,nCpg,m,rZ,r,Btt,*b,Csy"))]
   "TARGET_SHMEDIA
    && (register_operand (operands[0], SImode)
        || sh_register_operand (operands[1], SImode)
@@ -4883,10 +4887,11 @@ (define_insn "*movsi_media_nofpu"
 	ld%M1.l	%m1, %0
 	st%M0.l	%m0, %N1
 	ptabs	%1, %0
+	ptabs	%1, %0
 	gettr	%1, %0
 	pt	%1, %0"
-  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
-   (set_attr "length" "4,4,8,4,4,4,4,12")
+  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,ptabs_media,gettr_media,pt_media")
+   (set_attr "length" "4,4,8,4,4,4,4,4,12")
    (set (attr "highpart")
 	(cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
 	       (const_string "user")]
@@ -5261,9 +5266,9 @@ (define_split
 ;; point registers for storing integer values.
 (define_insn "*movdi_media"
   [(set (match_operand:DI 0 "general_movdst_operand"
-	         "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b")
+	         "=r,r,r,rl,m,f?,m,f?,r,f?,*Rtr,*b,r,*b")
 	(match_operand:DI 1 "general_movsrc_operand"
-	 "r,I16C16,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
+	 "r,I16C16,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,Btt,*b,Csy"))]
   "TARGET_SHMEDIA_FPU
    && (register_operand (operands[0], DImode)
        || sh_register_operand (operands[1], DImode))"
@@ -5279,14 +5284,15 @@ (define_insn "*movdi_media"
 	fmov.dq	%1, %0
 	fmov.d	%1, %0
 	ptabs	%1, %0
+	ptabs	%1, %0
 	gettr	%1, %0
 	pt	%1, %0"
-  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,fload_media,fstore_media,fload_media,dfpconv_media,fmove_media,ptabs_media,gettr_media,pt_media")
-   (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
+  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,fload_media,fstore_media,fload_media,dfpconv_media,fmove_media,ptabs_media,ptabs_media,gettr_media,pt_media")
+   (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,4,*")])
 
 (define_insn "*movdi_media_nofpu"
-  [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b");
-	(match_operand:DI 1 "general_movsrc_operand" "r,I16C16,nCpgF,m,rlZ,r,*b,Csy"))]
+  [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*Rtr,*b,r,*b");
+	(match_operand:DI 1 "general_movsrc_operand" "r,I16C16,nCpgF,m,rlZ,r,Btt,*b,Csy"))]
   "TARGET_SHMEDIA
    && (register_operand (operands[0], DImode)
        || sh_register_operand (operands[1], DImode))"
@@ -5297,10 +5303,11 @@ (define_insn "*movdi_media_nofpu"
 	ld%M1.q	%m1, %0
 	st%M0.q	%m0, %N1
 	ptabs	%1, %0
+	ptabs	%1, %0
 	gettr	%1, %0
 	pt	%1, %0"
-  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
-   (set_attr "length" "4,4,16,4,4,4,4,*")])
+  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,ptabs_media,gettr_media,pt_media")
+   (set_attr "length" "4,4,16,4,4,4,4,4,*")])
 
 (define_insn "*movdi_media_I16"
   [(set (match_operand:DI 0 "ext_dest_operand" "=r")
@@ -6469,12 +6476,75 @@ (define_expand "reload_insf"
   "TARGET_SH1"
   "")
 
+;;(define_expand "reload_insi_2e"
+;;  [(parallel [(set (match_operand:SI 0 "register_operand" "=y")
+;;		   (match_operand:SI 1 "immediate_operand" "i"))
+;;	      (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
+;;  "TARGET_SH1"
+;;  "")
+;;
+(define_expand "ptabs"
+  [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))]
+  "TARGET_SHMEDIA"
+  "
+{
+  if (!TARGET_PT_FIXED)
+    operands[1]
+      = (gen_rtx_IF_THEN_ELSE
+	  (Pmode,
+	   gen_rtx_EQ (SImode,
+		       gen_rtx_AND (Pmode, operands[1], GEN_INT (3)),
+		       GEN_INT (3)),
+	   gen_rtx_MEM (Pmode, operands[1]),
+	   operands[1]));
+}")
+
 (define_expand "reload_insi"
-  [(parallel [(set (match_operand:SF 0 "register_operand" "=y")
-		   (match_operand:SF 1 "immediate_operand" "FQ"))
-	      (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
+  [(parallel [(set (match_operand:SI 0 "reload_insidi_out_operand" "=Rso")
+		   (match_operand:SI 1 "reload_insidi_in_operand" "Bsi"))
+	      (clobber (match_operand 2 "reload_insidi_clobber_operand" "=&Rsc"))])]
   "TARGET_SH1"
-  "")
+  "
+{
+  if (TARGET_SHMEDIA)
+    {
+      emit_insn (gen_ptabs (operands[0], operands[1]));
+      DONE;
+    }
+}")
+
+(define_expand "reload_outsi"
+  [(parallel [(set (match_operand:SI 0 "reload_insidi_out_operand" "=Rso")
+		   (match_operand:SI 1 "reload_insidi_in_operand" "r"))
+	      (clobber (match_operand:CC_DUMMY 2 "reload_insidi_clobber_operand" "=&Rsc"))])]
+  "TARGET_SHMEDIA"
+  "
+{
+  emit_insn (gen_ptabs (operands[0], operands[1]));
+  DONE;
+}")
+
+(define_expand "reload_indi"
+  [(parallel [(set (match_operand:DI 0 "reload_insidi_out_operand" "=Rso")
+		   (match_operand:DI 1 "reload_insidi_in_operand" "r"))
+	      (clobber (match_operand:CC_DUMMY 2 "reload_insidi_clobber_operand" "=&Rsc"))])]
+  "TARGET_SHMEDIA"
+  "
+{
+  emit_insn (gen_ptabs (operands[0], operands[1]));
+  DONE;
+}")
+
+(define_expand "reload_outdi"
+  [(parallel [(set (match_operand:DI 0 "reload_insidi_out_operand" "=Rso")
+		   (match_operand:DI 1 "reload_insidi_in_operand" "r"))
+	      (clobber (match_operand:CC_DUMMY 2 "reload_insidi_clobber_operand" "=&Rsc"))])]
+  "TARGET_SHMEDIA"
+  "
+{
+  emit_insn (gen_ptabs (operands[0], operands[1]));
+  DONE;
+}")
 
 (define_insn "*movsi_y"
   [(set (match_operand:SI 0 "register_operand" "=y,y")
@@ -8926,7 +8996,7 @@ (define_expand "return_media"
 	abort ();
       tr_regno = TR0_REG;
       tr = gen_rtx_REG (Pmode, tr_regno);
-      emit_move_insn (tr, r18);
+      emit_insn (gen_ptabs (tr, r18));
     }
   else
     tr = gen_rtx_REG (Pmode, tr_regno);
? predicates.md
Index: sh-modes.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh-modes.def,v
retrieving revision 1.3
diff -d -u -p -r1.3 sh-modes.def
--- sh-modes.def	17 Oct 2004 18:09:46 -0000	1.3
+++ sh-modes.def	13 Apr 2005 22:30:09 -0000
@@ -20,6 +20,8 @@ Boston, MA 02111-1307, USA.  */
 
 /* The SH uses a partial integer mode to represent the FPSCR register.  */
 PARTIAL_INT_MODE (SI);
+/* PDI mode is used to represent a function address in a target register.  */
+PARTIAL_INT_MODE (DI);
 
 /* Vector modes.  */
 VECTOR_MODE  (INT, QI, 2);    /*                 V2QI */
Index: sh-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh-protos.h,v
retrieving revision 1.60.36.1
diff -d -u -p -r1.60.36.1 sh-protos.h
--- sh-protos.h	8 Apr 2005 17:41:26 -0000	1.60.36.1
+++ sh-protos.h	13 Apr 2005 22:30:09 -0000
@@ -165,6 +165,7 @@ extern rtx replace_n_hard_rtx (rtx, rtx 
 extern int shmedia_cleanup_truncate (rtx *, void *);
 
 extern int sh_contains_memref_p (rtx);
+extern rtx shmedia_prepare_call_address (rtx fnaddr, int is_sibcall);
 
 #endif /* ! GCC_SH_PROTOS_H */
 
Index: sh.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.c,v
retrieving revision 1.319.2.2
diff -d -u -p -r1.319.2.2 sh.c
--- sh.c	11 Apr 2005 20:31:24 -0000	1.319.2.2
+++ sh.c	13 Apr 2005 22:30:10 -0000
@@ -766,6 +766,12 @@ print_operand (FILE *stream, rtx x, int 
 	     but, because Pmode is SImode, the address ends up with a
 	     subreg:SI of the DImode register.  Maybe reload should be
 	     fixed so as to apply alter_subreg to such loads?  */
+	case IF_THEN_ELSE:
+	  gcc_assert (trapping_target_operand (x, VOIDmode));
+	  x = XEXP (XEXP (x, 2), 0);
+	  if (REG_P (x))
+	    goto reg;
+	  /* Fall through.  */
 	case SUBREG:
 	  if (SUBREG_BYTE (x) != 0
 	      || GET_CODE (SUBREG_REG (x)) != REG)
@@ -8055,8 +8061,9 @@ logical_operator (rtx op, enum machine_m
 int
 target_reg_operand (rtx op, enum machine_mode mode)
 {
-  if ((mode != VOIDmode && mode != Pmode)
-      || GET_MODE (op) != Pmode)
+  if (mode == VOIDmode
+     ? GET_MODE (op) != Pmode && GET_MODE (op) != PDImode
+     : mode != GET_MODE (op))
     return 0;
 
   if (GET_CODE (op) == SUBREG)
@@ -11142,8 +11149,54 @@ sh_contains_memref_p (rtx insn)
   return for_each_rtx (&PATTERN (insn), &sh_contains_memref_p_1, NULL);
 }
 
+/* FNADDR is the MEM expression from a call expander.  Return an address
+   to use in an SHmedia insn pattern.  */
+rtx
+shmedia_prepare_call_address (rtx fnaddr, int is_sibcall)
+{
+  int is_sym;
+
+  fnaddr = XEXP (fnaddr, 0);
+  is_sym = GET_CODE (fnaddr) == SYMBOL_REF;
+  if (flag_pic && is_sym)
+    {
+      if (! SYMBOL_REF_LOCAL_P (fnaddr))
+	{
+	  rtx reg = gen_reg_rtx (Pmode);
+
+	  /* We must not use GOTPLT for sibcalls, because PIC_REG
+	     must be restored before the PLT code gets to run.  */
+	  if (is_sibcall)
+	    emit_insn (gen_symGOT2reg (reg, fnaddr));
+	  else
+	    emit_insn (gen_symGOTPLT2reg (reg, fnaddr));
+	  fnaddr = reg;
+	}
+      else
+	{
+	  fnaddr = gen_sym2PIC (fnaddr);
+	  PUT_MODE (fnaddr, Pmode);
+	}
+    }
+  /* If ptabs might trap, make this visible to the rest of the compiler.
+     We generally assume that symbols pertain to valid locations, but
+     it is possible to generate invalid symbols with asm or linker tricks.
+     In a list of functions where each returns its sucessor, an invalid
+     symbol might denote an empty list.  */
+  if (!TARGET_PT_FIXED && (!is_sym || TARGET_INVALID_SYMBOLS))
+    {
+      rtx tr = gen_reg_rtx (PDImode);
+
+      emit_insn (gen_ptabs (tr, fnaddr));
+      fnaddr = tr;
+    }
+  else if (! target_reg_operand (fnaddr, Pmode))
+    fnaddr = copy_to_mode_reg (Pmode, fnaddr);
+  return fnaddr;
+}
+
 const char *sh_multcost_str = "";
-const char *sh_gettrcost_str = "100";
+const char *sh_gettrcost_str = "";
 const char *sh_div_str = "";
 const char *cut2_workaround_str = "";
 enum sh_divide_strategy_e sh_div_strategy = SH_DIV_CALL;
Index: sh.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.h,v
retrieving revision 1.262.2.2
diff -d -u -p -r1.262.2.2 sh.h
--- sh.h	11 Apr 2005 14:18:31 -0000	1.262.2.2
+++ sh.h	13 Apr 2005 22:30:10 -0000
@@ -120,6 +120,8 @@ do { \
     {									\
       regno_reg_class[FIRST_GENERAL_REG] = GENERAL_REGS;		\
       CLEAR_HARD_REG_SET (reg_class_contents[FP0_REGS]);		\
+      if (!TARGET_PT_FIXED && !*sh_gettrcost_str)			\
+	sh_gettrcost_str = "100";					\
       regno_reg_class[FIRST_FP_REG] = FP_REGS;				\
     }									\
   if (flag_pic)								\
@@ -180,6 +182,8 @@ extern int target_flags;
 #define HARD_SH2A_BIT	(1<<17)
 #define HARD_SH2A_DOUBLE_BIT	(1<<18)
 #define INDEXED_ADDRESS_BIT (1<<19)
+#define PT_FIXED_BIT	(1<<21)
+#define INVALID_SYMBOLS_BIT (1<<25)
 #define ADJUST_UNROLL_BIT (1<<20)
 
 /* Nonzero if this is an ELF target - compile time only */
@@ -337,7 +341,10 @@ extern int target_flags;
 #define TARGET_DIVIDE_INV_CALL (sh_div_strategy == SH_DIV_INV_CALL)
 #define TARGET_DIVIDE_INV_CALL2 (sh_div_strategy == SH_DIV_INV_CALL2)
 
+/* Target macros pertaining to SHmedia architecture bugs.  */
 #define TARGET_ALLOW_INDEXED_ADDRESS (target_flags & INDEXED_ADDRESS_BIT)
+#define TARGET_PT_FIXED (target_flags & PT_FIXED_BIT)
+#define TARGET_INVALID_SYMBOLS (target_flags & INVALID_SYMBOLS_BIT)
 
 #define TARGET_ADJUST_UNROLL (target_flags & ADJUST_UNROLL_BIT)
 
@@ -603,8 +610,12 @@ extern int target_flags;
   {"relax",	RELAX_BIT, "Shorten address references during linking" }, \
   {"space", 	SPACE_BIT, "Deprecated. Use -Os instead" },		\
   {"usermode",	USERMODE_BIT, "Generate library function call to invalidate instruction cache entries after fixing trampoline" }, \
-  {"indexed-addressing", INDEXED_ADDRESS_BIT, "Enable the use of the indexed addressing mode for SHmedia32"}, \
+  {"indexed-addressing", INDEXED_ADDRESS_BIT, "Enable the use of the indexed addressing mode for SHmedia32/SHcompact"}, \
   {"no-indexed-addressing", -INDEXED_ADDRESS_BIT, "Disable the use of the indexed addressing mode for SHmedia32"}, \
+  {"pt-fixed",	PT_FIXED_BIT, "Assume pt* instructions won't trap"}, \
+  {"no-pt-fixed", -PT_FIXED_BIT, "Assume pt* instructions may trap"}, \
+  {"invalid-symbols",INVALID_SYMBOLS_BIT, "Assume symbols might be invalid"}, \
+  {"no-invalid-symbols",-INVALID_SYMBOLS_BIT, "Assume symbols won't be invalid"}, \
   {"adjust-unroll", ADJUST_UNROLL_BIT, "Throttle unrolling to avoid thrashing target registers unless the unroll benefit outweighs this"}, \
   {"no-adjust-unroll", -ADJUST_UNROLL_BIT, "Don't throttle unrolling"},	\
   SUBTARGET_SWITCHES                            			\
@@ -1449,7 +1460,7 @@ extern char sh_additional_register_names
    : XD_REGISTER_P (REGNO) \
    ? (MODE) == DFmode \
    : TARGET_REGISTER_P (REGNO) \
-   ? ((MODE) == DImode || (MODE) == SImode) \
+   ? ((MODE) == DImode || (MODE) == SImode || (MODE) == PDImode) \
    : (REGNO) == PR_REG ? (MODE) == SImode \
    : (REGNO) == FPSCR_REG ? (MODE) == PSImode \
    : 1)
@@ -1752,6 +1763,7 @@ extern enum reg_class reg_class_from_let
    Bxx: miscellaneous constraints
     Bsc: SCRATCH - for the scratch register in movsi_ie in the
 	 fldi0 / fldi0 cases
+    Btt: potentially Trapping Target, used as the source for ptabs.
    C: Constants other than only CONST_INT (constraint len == 3)
     C16: 16 bit constant, literal or symbolic
     Csy: label or symbol
@@ -1775,30 +1787,11 @@ extern enum reg_class reg_class_from_let
    unused CONST_INT constraint letters: LO
    unused EXTRA_CONSTRAINT letters: D T U Y */
 
-#if 1 /* check that the transition went well.  */
-#define CONSTRAINT_LEN(C,STR) \
-  (((C) == 'L' || (C) == 'O' || (C) == 'D' || (C) == 'T' || (C) == 'U' \
-    || (C) == 'Y' \
-    || ((C) == 'I' \
-        && (((STR)[1] != '0' && (STR)[1] != '1' && (STR)[1] != '2') \
-	    || (STR)[2] < '0' || (STR)[2] > '9')) \
-    || ((C) == 'B' && ((STR)[1] != 's' || (STR)[2] != 'c')) \
-    || ((C) == 'J' && ((STR)[1] != '1' || (STR)[2] != '6')) \
-    || ((C) == 'K' && ((STR)[1] != '0' || (STR)[2] != '8')) \
-    || ((C) == 'P' && ((STR)[1] != '2' || (STR)[2] != '7'))) \
-   ? -1 \
-   : ((C) == 'A' || (C) == 'B' || (C) == 'C' \
-      || (C) == 'I' || (C) == 'J' || (C) == 'K' || (C) == 'P' \
-      || (C) == 'R' || (C) == 'S') \
-   ? 3 \
-   : DEFAULT_CONSTRAINT_LEN ((C), (STR)))
-#else
 #define CONSTRAINT_LEN(C,STR) \
   (((C) == 'A' || (C) == 'B' || (C) == 'C' \
     || (C) == 'I' || (C) == 'J' || (C) == 'K' || (C) == 'P' \
     || (C) == 'R' || (C) == 'S') \
    ? 3 : DEFAULT_CONSTRAINT_LEN ((C), (STR)))
-#endif
 
 /* The letters I, J, K, L and M in a register constraint string
    can be used to stand for particular ranges of immediate operands.
@@ -1883,7 +1876,7 @@ extern enum reg_class reg_class_from_let
    ? GENERAL_REGS \
    : (CLASS)) \
 
-#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS,MODE,X) \
+#define SECONDARY_INOUT_RELOAD_CLASS(CLASS,MODE,X,ELSE) \
   ((((REGCLASS_HAS_FP_REG (CLASS) 					\
       && (GET_CODE (X) == REG						\
       && (GENERAL_OR_AP_REGISTER_P (REGNO (X))				\
@@ -1904,18 +1897,21 @@ extern enum reg_class reg_class_from_let
 		  || REGNO (X) == T_REG					\
 		  || system_reg_operand (X, VOIDmode)))))		\
    ? GENERAL_REGS							\
-   : ((CLASS) == TARGET_REGS						\
-      || (TARGET_SHMEDIA && (CLASS) == SIBCALL_REGS))			\
-   ? ((target_operand ((X), (MODE))					\
-       && ! target_reg_operand ((X), (MODE)))				\
-      ? NO_REGS : GENERAL_REGS)						\
+   : (((CLASS) == TARGET_REGS						\
+       || (TARGET_SHMEDIA && (CLASS) == SIBCALL_REGS))			\
+      && !EXTRA_CONSTRAINT_Csy (X)					\
+      && (GET_CODE (X) != REG || ! GENERAL_REGISTER_P (REGNO (X))))	\
+   ? GENERAL_REGS							\
    : (((CLASS) == MAC_REGS || (CLASS) == PR_REGS)			\
       && GET_CODE (X) == REG && ! GENERAL_REGISTER_P (REGNO (X))	\
       && (CLASS) != REGNO_REG_CLASS (REGNO (X)))			\
    ? GENERAL_REGS							\
    : ((CLASS) != GENERAL_REGS && GET_CODE (X) == REG			\
       && TARGET_REGISTER_P (REGNO (X)))					\
-   ? GENERAL_REGS : NO_REGS)
+   ? GENERAL_REGS : (ELSE))
+
+#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS,MODE,X) \
+ SECONDARY_INOUT_RELOAD_CLASS(CLASS,MODE,X,NO_REGS)
 
 #define SECONDARY_INPUT_RELOAD_CLASS(CLASS,MODE,X)  \
   ((REGCLASS_HAS_FP_REG (CLASS) 					\
@@ -1950,7 +1946,7 @@ extern enum reg_class reg_class_from_let
    : (TARGET_SHMEDIA && (CLASS) == GENERAL_REGS				\
       && (GET_CODE (X) == LABEL_REF || PIC_DIRECT_ADDR_P (X)))		\
    ? TARGET_REGS							\
-   : SECONDARY_OUTPUT_RELOAD_CLASS((CLASS),(MODE),(X)))
+   : SECONDARY_INOUT_RELOAD_CLASS((CLASS),(MODE),(X), NO_REGS))
 
 /* Return the maximum number of consecutive registers
    needed to represent mode MODE in a register of class CLASS.
@@ -2573,8 +2569,10 @@ struct sh_args {
    operand is not SCRATCH (i.e. REG) then R0 is probably being
    used, hence mova is being used, hence do not select this pattern */
 #define EXTRA_CONSTRAINT_Bsc(OP)    (GET_CODE(OP) == SCRATCH)
+#define EXTRA_CONSTRAINT_Btt(OP) trapping_target_operand ((OP), VOIDmode)
 #define EXTRA_CONSTRAINT_B(OP, STR) \
   ((STR)[1] == 's' && (STR)[2] == 'c' ? EXTRA_CONSTRAINT_Bsc (OP) \
+   : (STR)[1] == 't' && (STR)[2] == 't' ? EXTRA_CONSTRAINT_Btt (OP) \
    : 0)
 
 /* The `C16' constraint is a 16-bit constant, literal or symbolic.  */
@@ -3545,7 +3543,7 @@ extern struct rtx_def *sp_switch;
   {"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_movsrc_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE, MEM, CONST, IF_THEN_ELSE }}, \
   {"general_movdst_operand", {SUBREG, REG, MEM}},			\
   {"unaligned_load_operand", {MEM}},					\
   {"greater_comparison_operator", {GT,GE,GTU,GEU}},			\
Index: sh.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.md,v
retrieving revision 1.191.2.1
diff -d -u -p -r1.191.2.1 sh.md
--- sh.md	8 Apr 2005 17:41:31 -0000	1.191.2.1
+++ sh.md	13 Apr 2005 22:30:10 -0000
@@ -444,6 +444,8 @@
 (include "shmedia.md")
 (include "sh4.md")
 
+(include "predicates.md")
+
 ;; Definitions for filling delay slots
 
 (define_attr "needs_delay_slot" "yes,no" (const_string "no"))
@@ -6470,12 +6472,37 @@ label:
   "")
 
 (define_expand "reload_insi"
-  [(parallel [(set (match_operand:SF 0 "register_operand" "=y")
-		   (match_operand:SF 1 "immediate_operand" "FQ"))
+  [(parallel [(set (match_operand:SI 0 "register_operand" "=y")
+		   (match_operand:SI 1 "immediate_operand" "i"))
 	      (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
   "TARGET_SH1"
   "")
 
+(define_expand "ptabs"
+  [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))]
+  "TARGET_SHMEDIA"
+  "
+{
+  if (!TARGET_PT_FIXED)
+    operands[1]
+      = (gen_rtx_IF_THEN_ELSE
+	  (PDImode,
+	   gen_rtx_EQ (SImode,
+		       gen_rtx_AND (Pmode, operands[1], GEN_INT (3)),
+		       GEN_INT (3)),
+	   gen_rtx_MEM (PDImode, operands[1]),
+	   gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE,
+			  PDImode, operands[1])));
+}")
+
+(define_insn "*movpdi_media"
+  [(set (match_operand:PDI 0 "target_reg_operand" "=b");
+	(match_operand:PDI 1 "trapping_target_operand" "Btt"))]
+  "TARGET_SHMEDIA && !TARGET_PT_FIXED"
+  "ptabs	%1, %0"
+  [(set_attr "type"   "ptabs_media")
+   (set_attr "length" "4")])
+
 (define_insn "*movsi_y"
   [(set (match_operand:SI 0 "register_operand" "=y,y")
 	(match_operand:SI 1 "immediate_operand" "Qi,I08"))
@@ -7361,43 +7388,7 @@ label:
 {
   if (TARGET_SHMEDIA)
     {
-      operands[0] = XEXP (operands[0], 0);
-      if (flag_pic && GET_CODE (operands[0]) == SYMBOL_REF)
-	{
-	  if (! SYMBOL_REF_LOCAL_P (operands[0]))
-	    {
-	      rtx reg = gen_reg_rtx (Pmode);
-
-	      emit_insn (gen_symGOTPLT2reg (reg, operands[0]));
-	      operands[0] = reg;
-	    }
-	  else
-	    {
-	      operands[0] = gen_sym2PIC (operands[0]);
-	      PUT_MODE (operands[0], Pmode);
-	    }
-	}
-      if (TARGET_SHMEDIA64)
-	{
-	  if (GET_MODE (operands[0]) == SImode)
-	    {
-	      if (GET_CODE (operands[0]) == REG)
-		operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
-	      else if (GET_CODE (operands[0]) == SUBREG)
-		{
-		  operands[0] = SUBREG_REG (operands[0]);
-		  if (GET_MODE (operands[0]) != DImode)
-		    operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
-		}
-	      else
-		{
-		  operands[0] = shallow_copy_rtx (operands[0]);
-		  PUT_MODE (operands[0], DImode);
-		}
-	    }
-	}
-      if (! target_reg_operand (operands[0], Pmode))
-	operands[0] = copy_to_mode_reg (Pmode, operands[0]);
+      operands[0] = shmedia_prepare_call_address (operands[0], 0);
       emit_call_insn (gen_call_media (operands[0], operands[1]));
       DONE;
     }
@@ -7579,43 +7570,7 @@ label:
 {
   if (TARGET_SHMEDIA)
     {
-      operands[1] = XEXP (operands[1], 0);
-      if (flag_pic && GET_CODE (operands[1]) == SYMBOL_REF)
-	{
-	  if (! SYMBOL_REF_LOCAL_P (operands[1]))
-	    {
-	      rtx reg = gen_reg_rtx (Pmode);
-
-	      emit_insn (gen_symGOTPLT2reg (reg, operands[1]));
-	      operands[1] = reg;
-	    }
-	  else
-	    {
-	      operands[1] = gen_sym2PIC (operands[1]);
-	      PUT_MODE (operands[1], Pmode);
-	    }
-	}
-      if (TARGET_SHMEDIA64)
-	{
-	  if (GET_MODE (operands[1]) == SImode)
-	    {
-	      if (GET_CODE (operands[1]) == REG)
-		operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
-	      else if (GET_CODE (operands[1]) == SUBREG)
-		{
-		  operands[1] = SUBREG_REG (operands[1]);
-		  if (GET_MODE (operands[1]) != DImode)
-		    operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
-		}
-	      else
-		{
-		  operands[1] = shallow_copy_rtx (operands[1]);
-		  PUT_MODE (operands[1], DImode);
-		}
-	    }
-	}
-      if (! target_reg_operand (operands[1], Pmode))
-	operands[1] = copy_to_mode_reg (Pmode, operands[1]);
+      operands[1] = shmedia_prepare_call_address (operands[1], 0);
       emit_call_insn (gen_call_value_media (operands[0], operands[1],
 					    operands[2]));
       DONE;
@@ -7801,50 +7756,7 @@ label:
 {
   if (TARGET_SHMEDIA)
     {
-      operands[0] = XEXP (operands[0], 0);
-      if (flag_pic && GET_CODE (operands[0]) == SYMBOL_REF)
-	{
-	  if (! SYMBOL_REF_LOCAL_P (operands[0]))
-	    {
-	      rtx reg = gen_reg_rtx (Pmode);
-
-	      /* We must not use GOTPLT for sibcalls, because PIC_REG
-		 must be restored before the PLT code gets to run.  */
-	      emit_insn (gen_symGOT2reg (reg, operands[0]));
-	      operands[0] = reg;
-	    }
-	  else
-	    {
-	      operands[0] = gen_sym2PIC (operands[0]);
-	      PUT_MODE (operands[0], Pmode);
-	    }
-	}
-      if (TARGET_SHMEDIA64)
-	{
-	  if (GET_MODE (operands[0]) == SImode)
-	    {
-	      if (GET_CODE (operands[0]) == REG)
-		operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
-	      else if (GET_CODE (operands[0]) == SUBREG)
-		{
-		  operands[0] = SUBREG_REG (operands[0]);
-		  if (GET_MODE (operands[0]) != DImode)
-		    operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
-		}
-	      else
-		{
-		  operands[0] = shallow_copy_rtx (operands[0]);
-		  PUT_MODE (operands[0], DImode);
-		}
-	    }
-	  if (! target_reg_operand (operands[0], DImode))
-	    operands[0] = copy_to_mode_reg (DImode, operands[0]);
-	}
-      else
-	{
-	  if (! target_reg_operand (operands[0], SImode))
-	    operands[0] = copy_to_mode_reg (SImode, operands[0]);
-	}
+      operands[0] = shmedia_prepare_call_address (operands[0], 1);
       emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
       DONE;
     }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]