aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/sh
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2000-11-23 06:37:23 +0000
committerAlexandre Oliva <aoliva@gcc.gnu.org>2000-11-23 06:37:23 +0000
commit422be3c3ccc0a941ea3a0a40c339322681b28b2b (patch)
tree5c0256af6368b27411a55e15e137d7e09aea0433 /gcc/config/sh
parent43c05634539cbdb4162ac6e067891e8f01ac2f62 (diff)
downloadgcc-422be3c3ccc0a941ea3a0a40c339322681b28b2b.zip
gcc-422be3c3ccc0a941ea3a0a40c339322681b28b2b.tar.gz
gcc-422be3c3ccc0a941ea3a0a40c339322681b28b2b.tar.bz2
final.c (output_addr_const): Simplify.
* final.c (output_addr_const) [LABEL_REF]: Simplify. [MINUS]: Enclose non-CONST_INTs in parentheses. [default]: Try OUTPUT_ADDR_CONST_EXTRA. * tm.texi (OUTPUT_ADDR_CONST_EXTRA): Document it. * varasm.c (decode_rtx_const) [CONST]: If it's not something PLUS or MINUS a CONST_INT, use the whole CONST with offset 0 instead of abort()ing. * sh.c (output_pic_addr_const): Removed. Fixed all callers. * sh.h (OUTPUT_ADDR_CONST_EXTRA): New. Handle the UNSPECs formerly handled in output_pic_addr_const. * sh.md (sym_label2reg, symPLT_label2reg): Enclose UNSPEC operands of MINUS in CONSTs so that decode_rtx_const() will accept them. From-SVN: r37691
Diffstat (limited to 'gcc/config/sh')
-rw-r--r--gcc/config/sh/sh.c118
-rw-r--r--gcc/config/sh/sh.h38
-rw-r--r--gcc/config/sh/sh.md15
3 files changed, 45 insertions, 126 deletions
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index e41ae32..7f3fdd3 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -202,7 +202,7 @@ print_operand_address (stream, x)
break;
default:
- output_pic_addr_const (stream, x);
+ output_addr_const (stream, x);
break;
}
}
@@ -5334,119 +5334,3 @@ legitimize_pic_address (orig, mode, reg)
}
return orig;
}
-
-/* Like output_addr_const(), but recognize PIC unspecs and special
- expressions. */
-void
-output_pic_addr_const (file, x)
- FILE *file;
- rtx x;
-{
- char buf[256];
-
- switch (GET_CODE (x))
- {
- case PC:
- if (flag_pic)
- putc ('.', file);
- else
- abort ();
- break;
-
- case SYMBOL_REF:
- assemble_name (file, XSTR (x, 0));
- break;
-
- case LABEL_REF:
- x = XEXP (x, 0);
- /* FALLTHRU */
- case CODE_LABEL:
- ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
- assemble_name (asm_out_file, buf);
- break;
-
- case CONST:
- output_pic_addr_const (file, XEXP (x, 0));
- break;
-
- case CONST_INT:
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
- break;
-
- case CONST_DOUBLE:
- if (GET_MODE (x) == VOIDmode)
- {
- /* We can use %d if the number is <32 bits and positive. */
- if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0)
- fprintf (file, "0x%lx%08lx",
- (unsigned long) CONST_DOUBLE_HIGH (x),
- (unsigned long) CONST_DOUBLE_LOW (x));
- else
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x));
- }
- else
- /* We can't handle floating point constants;
- PRINT_OPERAND must handle them. */
- output_operand_lossage ("floating constant misused");
- break;
-
- case PLUS:
- /* Some assemblers need integer constants to appear first. */
- if (GET_CODE (XEXP (x, 0)) == CONST_INT)
- {
- output_pic_addr_const (file, XEXP (x, 0));
- fprintf (file, "+");
- output_pic_addr_const (file, XEXP (x, 1));
- }
- else if (GET_CODE (XEXP (x, 1)) == CONST_INT
- || GET_CODE (XEXP (x, 0)) == PC)
- {
- output_pic_addr_const (file, XEXP (x, 1));
- fprintf (file, "+");
- output_pic_addr_const (file, XEXP (x, 0));
- }
- else
- abort ();
- break;
-
- case MINUS:
- output_pic_addr_const (file, XEXP (x, 0));
- fprintf (file, "-");
- if (GET_CODE (XEXP (x, 1)) == CONST)
- {
- putc ('(', file);
- output_pic_addr_const (file, XEXP (x, 1));
- putc (')', file);
- }
- else
- output_pic_addr_const (file, XEXP (x, 1));
- break;
-
- case UNSPEC:
- if ((XVECLEN (x, 0)) > 3)
- abort ();
- output_pic_addr_const (file, XVECEXP (x, 0, 0));
- switch (XINT (x, 1))
- {
- case 6:
- /* GLOBAL_OFFSET_TABLE or local symbols, no suffix. */
- break;
- case 7:
- fputs ("@GOT", file);
- break;
- case 8:
- fputs ("@GOTOFF", file);
- break;
- case 9:
- fputs ("@PLT", file);
- break;
- default:
- output_operand_lossage ("invalid UNSPEC as operand");
- break;
- }
- break;
-
- default:
- output_operand_lossage ("invalid expression as operand");
- }
-}
diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h
index 5dfd213..5476d14 100644
--- a/gcc/config/sh/sh.h
+++ b/gcc/config/sh/sh.h
@@ -2072,12 +2072,12 @@ do { char dstr[30]; \
#define ASM_OUTPUT_INT(STREAM, EXP) \
(fprintf ((STREAM), "\t.long\t"), \
- output_pic_addr_const ((STREAM), (EXP)), \
+ output_addr_const ((STREAM), (EXP)), \
fputc ('\n', (STREAM)))
#define ASM_OUTPUT_SHORT(STREAM, EXP) \
(fprintf ((STREAM), "\t.short\t"), \
- output_pic_addr_const ((STREAM), (EXP)), \
+ output_addr_const ((STREAM), (EXP)), \
fputc ('\n', (STREAM)))
#define ASM_OUTPUT_CHAR(STREAM, EXP) \
@@ -2157,6 +2157,40 @@ do { char dstr[30]; \
#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
((CHAR) == '.' || (CHAR) == '#' || (CHAR) == '@' || (CHAR) == ',' \
|| (CHAR) == '$')
+
+/* Recognize machine-specific patterns that may appear within
+ constants. Used for PIC-specific UNSPECs. */
+#define OUTPUT_ADDR_CONST_EXTRA(STREAM, X, FAIL) \
+ do \
+ if (flag_pic && GET_CODE (X) == UNSPEC && XVECLEN ((X), 0) == 1) \
+ { \
+ switch (XINT ((X), 1)) \
+ { \
+ case UNSPEC_PIC: \
+ /* GLOBAL_OFFSET_TABLE or local symbols, no suffix. */ \
+ output_addr_const ((STREAM), XVECEXP ((X), 0, 0)); \
+ break; \
+ case UNSPEC_GOT: \
+ output_addr_const ((STREAM), XVECEXP ((X), 0, 0)); \
+ fputs ("@GOT", (STREAM)); \
+ break; \
+ case UNSPEC_GOTOFF: \
+ output_addr_const ((STREAM), XVECEXP ((X), 0, 0)); \
+ fputs ("@GOTOFF", (STREAM)); \
+ break; \
+ case UNSPEC_PLT: \
+ output_addr_const ((STREAM), XVECEXP ((X), 0, 0)); \
+ fputs ("@PLT", (STREAM)); \
+ break; \
+ default: \
+ goto FAIL; \
+ } \
+ break; \
+ } \
+ else \
+ goto FAIL; \
+ while (0)
+
extern struct rtx_def *sh_compare_op0;
extern struct rtx_def *sh_compare_op1;
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 34649e0..549c7e7 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -3596,7 +3596,7 @@
(define_expand "sym_label2reg"
[(set (match_operand:SI 0 "" "")
(const (minus:SI
- (unspec [(match_operand:SI 1 "" "")] UNSPEC_PIC)
+ (const (unspec [(match_operand:SI 1 "" "")] UNSPEC_PIC))
(const (plus:SI
(unspec [(label_ref (match_operand:SI 2 "" ""))]
UNSPEC_PIC)
@@ -3629,12 +3629,13 @@
(define_expand "symPLT_label2reg"
[(set (match_operand:SI 0 "" "")
(const (minus:SI
- (plus:SI (pc)
- (unspec [(match_operand:SI 1 "" "")] UNSPEC_PLT))
- (const
- (plus:SI
- (unspec [(label_ref (match_operand:SI 2 "" ""))] UNSPEC_PIC)
- (const_int 2))))))
+ (const (plus:SI
+ (unspec [(match_operand:SI 1 "" "")] UNSPEC_PLT)
+ (pc)))
+ (const (plus:SI
+ (unspec [(label_ref (match_operand:SI 2 "" ""))]
+ UNSPEC_PIC)
+ (const_int 2))))))
(use (match_dup 3))]
;; Even though the PIC register is not really used by the call
;; sequence in which this is expanded, the PLT code assumes the PIC