This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
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;
}