+2008-10-10 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * config/sh/sh.h (PREFERRED_RELOAD_CLASS): Test PIC_ADDR_P
+ instead of PIC_DIRECT_ADDR_P.
+ (SECONDARY_INPUT_RELOAD_CLASS): Likewise.
+ (IS_LITERAL_OR_SYMBOLIC_S16_P, IS_LITERAL_OR_SYMBOLIC_U16_P): Delete.
+ (IS_NON_EXPLICIT_CONSTANT_P): Don't test PIC_OFFSET_P.
+ (PIC_OFFSET_P): Rename to...
+ (PCREL_SYMOFF_P): ...this.
+ (PIC_DIRECT_ADDR_P): Delete.
+ (MOVI_SHORI_BASE_OPERAND_P): Check PCREL_SYMOFF_P instead of
+ PIC_OFFSET_P.
+ (OUTPUT_ADDR_CONST_EXTRA): Don't require unspecs to have a
+ single argument. Handle UNSPEC_EXTRACT_S16, UNSPEC_EXTRACT_U16,
+ UNSPEC_SYMOFF and UNSPEC_PCREL_SYMOFF.
+ * config/sh/sh.c (print_operand): Remove CONST handling.
+ (unspec_caller_rtx_p): Rewrite to use split_const and check
+ the operands of UNSPEC bases.
+ (fixup_mova): Replace (unspec [(minus A B)] UNSPEC_PIC)
+ with (unspec [A B] UNSPEC_SYMOFF).
+ (nonpic_symbol_mentioned_p): Check for UNSPEC_SYMOFF and
+ UNSPEC_PCREL_SYMOFF.
+ (sh_secondary_reload): Test PIC_ADDR_P instead of PIC_DIRECT_ADDR_P.
+ * config/sh/sh.md (UNSPEC_EXTRACT_S16): New unspec.
+ (UNSPEC_EXTRACT_U16): Likewise.
+ (UNSPEC_SYMOFF): Likewise.
+ (UNSPEC_PCREL_SYMOFF): Likewise.
+ (movsi_const): Use UNSPEC_EXTRACT_*16s to extract 16-bit portions
+ of constants.
+ (movsi_const_16bit): Likewise.
+ (movdi_const, movdi_const_32bit, movdi_const_16bit): Likewise.
+ (GOTaddr2picreg): Replace (unspec [(minus A (minus B pc))] UNSPEC_PIC)
+ with (unspec [A B] UNSPEC_PCREL_SYMOFF).
+ (sym_label2reg): Replace (minus (const (unspec [A] UNSPEC_PIC)) B)
+ with (unspec [A B] UNSPEC_SYMOFF).
+ (symPLT_label2reg): Replace (minus A (minus B pc)) with
+ (unspec [A B] PCREL_UNSPEC_SYMOFF).
+ * config/sh/constraints.md (Css): Check for an UNSPEC_EXTRACT_S16.
+ (Csu): Likewise UNSPEC_EXTRACT_U16.
+ (Csy): Test PIC_ADDR_P instead of PIC_DIRECT_ADDR_P.
+ (Cpg): Update after changes to IS_NON_EXPLICIT_CONSTANT_P.
+
2008-10-10 Stepan Kasal <skasal@redhat.com>
* gcc/doc/invoke.texi (Optimize Options): Fix typo in examples
;; Csy: label or symbol
;; Cpg: non-explicit constants that can be directly loaded into a general
;; purpose register in PIC code. like 's' except we don't allow
-;; PIC_DIRECT_ADDR_P
+;; PIC_ADDR_P
;; IJKLMNOP: CONT_INT constants
;; Ixx: signed xx bit
;; J16: 0xffffffff00000000 | 0x00000000ffffffff
(define_constraint "Css"
"A signed 16-bit constant, literal or symbolic."
(and (match_code "const")
- (match_test "IS_LITERAL_OR_SYMBOLIC_S16_P (XEXP (op, 0))")))
+ (match_test "GET_CODE (XEXP (op, 0)) == UNSPEC")
+ (match_test "XINT (XEXP (op, 0), 1) == UNSPEC_EXTRACT_S16")))
(define_constraint "Csu"
"An unsigned 16-bit constant, literal or symbolic."
(and (match_code "const")
- (match_test "IS_LITERAL_OR_SYMBOLIC_U16_P (XEXP (op, 0))")))
+ (match_test "GET_CODE (XEXP (op, 0)) == UNSPEC")
+ (match_test "XINT (XEXP (op, 0), 1) == UNSPEC_EXTRACT_U16")))
(define_constraint "Csy"
"A label or a symbol."
(ior (match_test "NON_PIC_REFERENCE_P (op)")
- (match_test "PIC_DIRECT_ADDR_P (op)")))
+ (match_test "PIC_ADDR_P (op)")))
(define_constraint "Z"
"A zero in any shape or form."
(define_constraint "Cpg"
"A non-explicit constant that can be loaded directly into a general
purpose register. This is like 's' except we don't allow
- PIC_DIRECT_ADDR_P."
+ PIC_ADDR_P."
(match_test "IS_NON_EXPLICIT_CONSTANT_P (op)"))
(define_constraint "Pso"
output_address (XEXP (x, 0));
break;
- case CONST:
- if (TARGET_SHMEDIA
- && (GET_CODE (XEXP (x, 0)) == SIGN_EXTEND
- || GET_CODE (XEXP (x, 0)) == ZERO_EXTEND)
- && (GET_MODE (XEXP (x, 0)) == DImode
- || GET_MODE (XEXP (x, 0)) == SImode)
- && GET_CODE (XEXP (XEXP (x, 0), 0)) == TRUNCATE
- && GET_MODE (XEXP (XEXP (x, 0), 0)) == HImode)
- {
- rtx val = XEXP (XEXP (XEXP (x, 0), 0), 0);
- rtx val2 = val;
- bool nested_expr = false;
-
- fputc ('(', stream);
- if (GET_CODE (val) == ASHIFTRT)
- {
- fputc ('(', stream);
- val2 = XEXP (val, 0);
- }
- if (GET_CODE (val2) == CONST
- || GET_RTX_CLASS (GET_CODE (val2)) != RTX_OBJ)
- {
- fputc ('(', stream);
- nested_expr = true;
- }
- output_addr_const (stream, val2);
- if (nested_expr)
- fputc (')', stream);
- if (GET_CODE (val) == ASHIFTRT)
- {
- fputs (" >> ", stream);
- output_addr_const (stream, XEXP (val, 1));
- fputc (')', stream);
- }
- fputs (" & 65535)", stream);
- break;
- }
-
- /* Fall through. */
default:
if (TARGET_SH1)
fputc ('#', stream);
static bool
unspec_caller_rtx_p (rtx pat)
{
- switch (GET_CODE (pat))
+ rtx base, offset;
+ int i;
+
+ split_const (pat, &base, &offset);
+ if (GET_CODE (base) == UNSPEC)
{
- case CONST:
- return unspec_caller_rtx_p (XEXP (pat, 0));
- case PLUS:
- case MINUS:
- if (unspec_caller_rtx_p (XEXP (pat, 0)))
+ if (XINT (base, 1) == UNSPEC_CALLER)
return true;
- return unspec_caller_rtx_p (XEXP (pat, 1));
- case UNSPEC:
- if (XINT (pat, 1) == UNSPEC_CALLER)
- return true;
- default:
- break;
+ for (i = 0; i < XVECLEN (base, 0); i++)
+ if (unspec_caller_rtx_p (XVECEXP (base, 0, i)))
+ return true;
}
-
return false;
}
{
rtx worker = mova;
rtx lab = gen_label_rtx ();
- rtx wpat, wpat0, wpat1, wsrc, diff;
+ rtx wpat, wpat0, wpat1, wsrc, target, base, diff;
do
{
XEXP (XVECEXP (wsrc, 0, 2), 0), lab,
XEXP (wpat1, 0)));
INSN_CODE (worker) = -1;
- diff = gen_rtx_MINUS (Pmode, XVECEXP (SET_SRC (PATTERN (mova)), 0, 0),
- gen_rtx_LABEL_REF (Pmode, lab));
- diff = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, diff), UNSPEC_PIC);
+ target = XVECEXP (SET_SRC (PATTERN (mova)), 0, 0);
+ base = gen_rtx_LABEL_REF (Pmode, lab);
+ diff = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, target, base), UNSPEC_SYMOFF);
SET_SRC (PATTERN (mova)) = gen_rtx_CONST (Pmode, diff);
INSN_CODE (mova) = -1;
}
|| XINT (x, 1) == UNSPEC_GOTPLT
|| XINT (x, 1) == UNSPEC_GOTTPOFF
|| XINT (x, 1) == UNSPEC_DTPOFF
- || XINT (x, 1) == UNSPEC_PLT))
+ || XINT (x, 1) == UNSPEC_PLT
+ || XINT (x, 1) == UNSPEC_SYMOFF
+ || XINT (x, 1) == UNSPEC_PCREL_SYMOFF))
return 0;
fmt = GET_RTX_FORMAT (GET_CODE (x));
return NO_REGS;
}
if (TARGET_SHMEDIA && rclass == GENERAL_REGS
- && (GET_CODE (x) == LABEL_REF || PIC_DIRECT_ADDR_P (x)))
+ && (GET_CODE (x) == LABEL_REF || PIC_ADDR_P (x)))
return TARGET_REGS;
} /* end of input-only processing. */
((CLASS) == NO_REGS && TARGET_SHMEDIA \
&& (GET_CODE (X) == CONST_DOUBLE \
|| GET_CODE (X) == SYMBOL_REF \
- || PIC_DIRECT_ADDR_P (X)) \
+ || PIC_ADDR_P (X)) \
? GENERAL_REGS \
: (CLASS)) \
&& TARGET_SHMEDIA && inqhi_operand ((X), (MODE))) \
? GENERAL_REGS \
: (TARGET_SHMEDIA && (CLASS) == GENERAL_REGS \
- && (GET_CODE (X) == LABEL_REF || PIC_DIRECT_ADDR_P (X))) \
+ && (GET_CODE (X) == LABEL_REF || PIC_ADDR_P (X))) \
? TARGET_REGS \
: SECONDARY_INOUT_RELOAD_CLASS((CLASS),(MODE),(X), NO_REGS))
#endif
&& GET_CODE (XEXP (XEXP ((OP), 0), 0)) == LABEL_REF \
&& GET_CODE (XEXP (XEXP ((OP), 0), 1)) == CONST_INT))
-#define IS_LITERAL_OR_SYMBOLIC_S16_P(OP) \
- (GET_CODE ((OP)) == SIGN_EXTEND \
- && (GET_MODE ((OP)) == DImode \
- || GET_MODE ((OP)) == SImode) \
- && GET_CODE (XEXP ((OP), 0)) == TRUNCATE \
- && GET_MODE (XEXP ((OP), 0)) == HImode \
- && (MOVI_SHORI_BASE_OPERAND_P (XEXP (XEXP ((OP), 0), 0)) \
- || (GET_CODE (XEXP (XEXP ((OP), 0), 0)) == ASHIFTRT \
- && (MOVI_SHORI_BASE_OPERAND_P \
- (XEXP (XEXP (XEXP ((OP), 0), 0), 0))) \
- && GET_CODE (XEXP (XEXP (XEXP ((OP), 0), 0), 1)) == CONST_INT)))
-
-#define IS_LITERAL_OR_SYMBOLIC_U16_P(OP) \
- (GET_CODE ((OP)) == ZERO_EXTEND \
- && (GET_MODE ((OP)) == DImode \
- || GET_MODE ((OP)) == SImode) \
- && GET_CODE (XEXP ((OP), 0)) == TRUNCATE \
- && GET_MODE (XEXP ((OP), 0)) == HImode \
- && (MOVI_SHORI_BASE_OPERAND_P (XEXP (XEXP ((OP), 0), 0)) \
- || (GET_CODE (XEXP (XEXP ((OP), 0), 0)) == ASHIFTRT \
- && (MOVI_SHORI_BASE_OPERAND_P \
- (XEXP (XEXP (XEXP ((OP), 0), 0), 0))) \
- && GET_CODE (XEXP (XEXP (XEXP ((OP), 0), 0), 1)) == CONST_INT)))
-
#define IS_NON_EXPLICIT_CONSTANT_P(OP) \
(CONSTANT_P (OP) \
&& GET_CODE (OP) != CONST_INT \
&& GET_CODE (OP) != CONST_DOUBLE \
&& (!flag_pic \
|| (LEGITIMATE_PIC_OPERAND_P (OP) \
- && (! PIC_ADDR_P (OP) || PIC_OFFSET_P (OP)) \
+ && !PIC_ADDR_P (OP) \
&& GET_CODE (OP) != LABEL_REF)))
/* Check whether OP is a datalabel unspec. */
(GET_CODE (OP) == CONST && GET_CODE (XEXP ((OP), 0)) == UNSPEC \
&& XINT (XEXP ((OP), 0), 1) == UNSPEC_PIC)
-#define PIC_OFFSET_P(OP) \
- (PIC_ADDR_P (OP) \
- && GET_CODE (XVECEXP (XEXP ((OP), 0), 0, 0)) == MINUS \
- && reg_mentioned_p (pc_rtx, XEXP (XVECEXP (XEXP ((OP), 0), 0, 0), 1)))
-
-#define PIC_DIRECT_ADDR_P(OP) \
- (PIC_ADDR_P (OP) && GET_CODE (XVECEXP (XEXP ((OP), 0), 0, 0)) != MINUS)
+#define PCREL_SYMOFF_P(OP) \
+ (GET_CODE (OP) == CONST \
+ && GET_CODE (XEXP ((OP), 0)) == UNSPEC \
+ && XINT (XEXP ((OP), 0), 1) == UNSPEC_PCREL_SYMOFF)
#define NON_PIC_REFERENCE_P(OP) \
(GET_CODE (OP) == LABEL_REF || GET_CODE (OP) == SYMBOL_REF \
#define MOVI_SHORI_BASE_OPERAND_P(OP) \
(flag_pic \
? (GOT_ENTRY_P (OP) || GOTPLT_ENTRY_P (OP) || GOTOFF_P (OP) \
- || PIC_OFFSET_P (OP)) \
+ || PCREL_SYMOFF_P (OP)) \
: NON_PIC_REFERENCE_P (OP))
\f
/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
constants. Used for PIC-specific UNSPECs. */
#define OUTPUT_ADDR_CONST_EXTRA(STREAM, X, FAIL) \
do \
- if (GET_CODE (X) == UNSPEC && XVECLEN ((X), 0) == 1) \
+ if (GET_CODE (X) == UNSPEC) \
{ \
switch (XINT ((X), 1)) \
{ \
assemble_name ((STREAM), name); \
} \
break; \
+ case UNSPEC_EXTRACT_S16: \
+ case UNSPEC_EXTRACT_U16: \
+ { \
+ rtx val, shift; \
+ \
+ val = XVECEXP (X, 0, 0); \
+ shift = XVECEXP (X, 0, 1); \
+ fputc ('(', STREAM); \
+ if (shift != const0_rtx) \
+ fputc ('(', STREAM); \
+ if (GET_CODE (val) == CONST \
+ || GET_RTX_CLASS (GET_CODE (val)) != RTX_OBJ) \
+ { \
+ fputc ('(', STREAM); \
+ output_addr_const (STREAM, val); \
+ fputc (')', STREAM); \
+ } \
+ else \
+ output_addr_const (STREAM, val); \
+ if (shift != const0_rtx) \
+ { \
+ fputs (" >> ", STREAM); \
+ output_addr_const (STREAM, shift); \
+ fputc (')', STREAM); \
+ } \
+ fputs (" & 65535)", STREAM); \
+ } \
+ break; \
+ case UNSPEC_SYMOFF: \
+ output_addr_const (STREAM, XVECEXP (X, 0, 0)); \
+ fputc ('-', STREAM); \
+ if (GET_CODE (XVECEXP (X, 0, 1)) == CONST) \
+ { \
+ fputc ('(', STREAM); \
+ output_addr_const (STREAM, XVECEXP (X, 0, 1)); \
+ fputc (')', STREAM); \
+ } \
+ else \
+ output_addr_const (STREAM, XVECEXP (X, 0, 1)); \
+ break; \
+ case UNSPEC_PCREL_SYMOFF: \
+ output_addr_const (STREAM, XVECEXP (X, 0, 0)); \
+ fputs ("-(", STREAM); \
+ output_addr_const (STREAM, XVECEXP (X, 0, 1)); \
+ fputs ("-.)", STREAM); \
+ break; \
default: \
goto FAIL; \
} \
(UNSPEC_SP_TEST 41)
(UNSPEC_MOVUA 42)
+ ;; (unspec [VAL SHIFT] UNSPEC_EXTRACT_S16) computes (short) (VAL >> SHIFT).
+ ;; UNSPEC_EXTRACT_U16 is the unsigned equivalent.
+ (UNSPEC_EXTRACT_S16 43)
+ (UNSPEC_EXTRACT_U16 44)
+
+ ;; (unspec [TARGET ANCHOR] UNSPEC_SYMOFF) == TARGET - ANCHOR.
+ (UNSPEC_SYMOFF 45)
+
+ ;; (unspec [OFFSET ANCHOR] UNSPEC_PCREL_SYMOFF) == OFFSET - (ANCHOR - .).
+ (UNSPEC_PCREL_SYMOFF 46)
+
;; These are used with unspec_volatile.
(UNSPECV_BLOCKAGE 0)
(UNSPECV_ALIGN 1)
(define_expand "movsi_const"
[(set (match_operand:SI 0 "arith_reg_operand" "=r")
- (const:SI (sign_extend:SI
- (truncate:HI
- (ashiftrt:SI
- (match_operand:DI 1 "immediate_operand" "s")
- (const_int 16))))))
+ (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
+ (const_int 16)] UNSPEC_EXTRACT_S16)))
(set (match_dup 0)
(ior:SI (ashift:SI (match_dup 0) (const_int 16))
- (const:SI
- (zero_extend:SI
- (truncate:HI (match_dup 1))))))]
+ (const:SI (unspec:SI [(match_dup 1)
+ (const_int 0)] UNSPEC_EXTRACT_U16))))]
"TARGET_SHMEDIA && reload_completed
&& MOVI_SHORI_BASE_OPERAND_P (operands[1])"
"
(define_expand "movsi_const_16bit"
[(set (match_operand:SI 0 "arith_reg_operand" "=r")
- (const:SI (sign_extend:SI
- (truncate:HI
- (match_operand:DI 1 "immediate_operand" "s")))))]
+ (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
+ (const_int 0)] UNSPEC_EXTRACT_S16)))]
"TARGET_SHMEDIA && flag_pic && reload_completed
&& GET_CODE (operands[1]) == SYMBOL_REF"
"")
(define_expand "movdi_const"
[(set (match_operand:DI 0 "arith_reg_operand" "=r")
- (const:DI (sign_extend:DI
- (truncate:HI
- (ashiftrt:DI
- (match_operand:DI 1 "immediate_operand" "s")
- (const_int 48))))))
+ (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
+ (const_int 48)] UNSPEC_EXTRACT_S16)))
(set (match_dup 0)
(ior:DI (ashift:DI (match_dup 0) (const_int 16))
- (const:DI
- (zero_extend:DI
- (truncate:HI
- (ashiftrt:SI
- (match_dup 1)
- (const_int 32)))))))
+ (const:DI (unspec:DI [(match_dup 1)
+ (const_int 32)] UNSPEC_EXTRACT_U16))))
(set (match_dup 0)
(ior:DI (ashift:DI (match_dup 0) (const_int 16))
- (const:DI
- (zero_extend:DI
- (truncate:HI
- (ashiftrt:SI
- (match_dup 1)
- (const_int 16)))))))
+ (const:DI (unspec:DI [(match_dup 1)
+ (const_int 16)] UNSPEC_EXTRACT_U16))))
(set (match_dup 0)
(ior:DI (ashift:DI (match_dup 0) (const_int 16))
- (const:DI
- (zero_extend:DI
- (truncate:HI
- (match_dup 1))))))]
+ (const:DI (unspec:DI [(match_dup 1)
+ (const_int 0)] UNSPEC_EXTRACT_U16))))]
"TARGET_SHMEDIA64 && reload_completed
&& MOVI_SHORI_BASE_OPERAND_P (operands[1])"
"
(define_expand "movdi_const_32bit"
[(set (match_operand:DI 0 "arith_reg_operand" "=r")
- (const:DI (sign_extend:DI
- (truncate:HI
- (ashiftrt:DI
- (match_operand:DI 1 "immediate_operand" "s")
- (const_int 16))))))
+ (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
+ (const_int 16)] UNSPEC_EXTRACT_S16)))
(set (match_dup 0)
(ior:DI (ashift:DI (match_dup 0) (const_int 16))
- (const:DI
- (zero_extend:DI
- (truncate:HI
- (match_dup 1))))))]
+ (const:DI (unspec:DI [(match_dup 1)
+ (const_int 0)] UNSPEC_EXTRACT_U16))))]
"TARGET_SHMEDIA32 && reload_completed
&& MOVI_SHORI_BASE_OPERAND_P (operands[1])"
"
(define_expand "movdi_const_16bit"
[(set (match_operand:DI 0 "arith_reg_operand" "=r")
- (const:DI (sign_extend:DI
- (truncate:HI
- (match_operand:DI 1 "immediate_operand" "s")))))]
+ (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
+ (const_int 0)] UNSPEC_EXTRACT_S16)))]
"TARGET_SHMEDIA && flag_pic && reload_completed
&& GET_CODE (operands[1]) == SYMBOL_REF"
"")
rtx insn, equiv;
equiv = operands[1];
- operands[1] = gen_rtx_MINUS (Pmode,
- operands[1],
- gen_rtx_CONST
- (Pmode,
- gen_rtx_MINUS (Pmode,
- gen_rtx_CONST (Pmode,
- lab),
- pc_rtx)));
- operands[1] = gen_sym2PIC (operands[1]);
- PUT_MODE (operands[1], Pmode);
+ operands[1] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1], lab),
+ UNSPEC_PCREL_SYMOFF);
+ operands[1] = gen_rtx_CONST (Pmode, operands[1]);
if (Pmode == SImode)
{
(define_expand "sym_label2reg"
[(set (match_operand:SI 0 "" "")
- (const:SI (minus:SI
- (const:SI
- (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC))
- (const:SI
- (plus:SI
- (match_operand:SI 2 "" "")
- (const_int 2))))))]
+ (const:SI (unspec:SI [(match_operand:SI 1 "" "")
+ (const (plus:SI (match_operand:SI 2 "" "")
+ (const_int 2)))]
+ UNSPEC_SYMOFF)))]
"TARGET_SH1" "")
(define_expand "symGOT_load"
(define_expand "symPLT_label2reg"
[(set (match_operand:SI 0 "" "")
- (const:SI (minus:SI
- (const:SI
- (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
- (const:SI
- (minus:SI
- (const:SI (plus:SI
- (match_operand:SI 2 "" "")
- (const_int 2)))
- (const:SI (unspec:SI [(pc)] UNSPEC_PIC)))))))
+ (const:SI
+ (unspec:SI
+ [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
+ (const:SI (plus:SI (match_operand:SI 2 "" "")
+ (const_int 2)))] UNSPEC_PCREL_SYMOFF)))
;; Even though the PIC register is not really used by the call
;; sequence in which this is expanded, the PLT code assumes the PIC
;; register is set, so we must not skip its initialization. Since