mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-30 10:14:53 +08:00
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
This commit is contained in:
parent
43c0563453
commit
422be3c3cc
@ -1,3 +1,19 @@
|
||||
Thu Nov 23 04:33:33 2000 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
* 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.
|
||||
|
||||
Thu Nov 23 04:10:30 2000 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
* config/sh/sh.md (mova_const): New pattern.
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
17
gcc/final.c
17
gcc/final.c
@ -3677,10 +3677,8 @@ output_addr_const (file, x)
|
||||
break;
|
||||
|
||||
case LABEL_REF:
|
||||
ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
|
||||
assemble_name (file, buf);
|
||||
break;
|
||||
|
||||
x = XEXP (x, 0);
|
||||
/* Fall through. */
|
||||
case CODE_LABEL:
|
||||
ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
|
||||
assemble_name (file, buf);
|
||||
@ -3741,8 +3739,9 @@ output_addr_const (file, x)
|
||||
|
||||
output_addr_const (file, XEXP (x, 0));
|
||||
fprintf (file, "-");
|
||||
if (GET_CODE (XEXP (x, 1)) == CONST_INT
|
||||
&& INTVAL (XEXP (x, 1)) < 0)
|
||||
if ((GET_CODE (XEXP (x, 1)) == CONST_INT
|
||||
&& INTVAL (XEXP (x, 1)) < 0)
|
||||
|| GET_CODE (XEXP (x, 1)) != CONST_INT)
|
||||
{
|
||||
fprintf (file, "%s", ASM_OPEN_PAREN);
|
||||
output_addr_const (file, XEXP (x, 1));
|
||||
@ -3758,6 +3757,12 @@ output_addr_const (file, x)
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef OUTPUT_ADDR_CONST_EXTRA
|
||||
OUTPUT_ADDR_CONST_EXTRA (file, x, fail);
|
||||
break;
|
||||
|
||||
fail:
|
||||
#endif
|
||||
output_operand_lossage ("invalid expression as operand");
|
||||
}
|
||||
}
|
||||
|
12
gcc/tm.texi
12
gcc/tm.texi
@ -5500,6 +5500,18 @@ would be identical to repeatedly calling the macro corresponding to
|
||||
a size of @code{UNITS_PER_WORD}, once for each word, you need not define
|
||||
the macro.
|
||||
|
||||
@findex OUTPUT_ADDR_CONST_EXTRA
|
||||
@item OUTPUT_ADDR_CONST_EXTRA (@var{stream}, @var{x}, @var{fail})
|
||||
A C statement to recognize @var{rtx} patterns that
|
||||
@code{output_addr_const} can't deal with, and output assembly code to
|
||||
@var{stream} corresponding to the pattern @var{x}. This may be used to
|
||||
allow machine-dependent @code{UNSPEC}s to appear within constants.
|
||||
|
||||
If @code{OUTPUT_ADDR_CONST_EXTRA} fails to recognize a pattern, it must
|
||||
@code{goto fail}, so that a standard error message is printed. If it
|
||||
prints an error message itself, by calling, for example,
|
||||
@code{output_operand_lossage}, it may just complete normally.
|
||||
|
||||
@findex ASM_OUTPUT_BYTE
|
||||
@item ASM_OUTPUT_BYTE (@var{stream}, @var{value})
|
||||
A C statement to output to the stdio stream @var{stream} an assembler
|
||||
|
13
gcc/varasm.c
13
gcc/varasm.c
@ -3486,22 +3486,21 @@ decode_rtx_const (mode, x, value)
|
||||
|
||||
case CONST:
|
||||
x = XEXP (x, 0);
|
||||
if (GET_CODE (x) == PLUS)
|
||||
if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT)
|
||||
{
|
||||
value->un.addr.base = XEXP (x, 0);
|
||||
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
|
||||
abort ();
|
||||
value->un.addr.offset = INTVAL (XEXP (x, 1));
|
||||
}
|
||||
else if (GET_CODE (x) == MINUS)
|
||||
else if (GET_CODE (x) == MINUS && GET_CODE (XEXP (x, 1)) == CONST_INT)
|
||||
{
|
||||
value->un.addr.base = XEXP (x, 0);
|
||||
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
|
||||
abort ();
|
||||
value->un.addr.offset = - INTVAL (XEXP (x, 1));
|
||||
}
|
||||
else
|
||||
abort ();
|
||||
{
|
||||
value->un.addr.base = x;
|
||||
value->un.addr.offset = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
Loading…
Reference in New Issue
Block a user