Commit 9482d6de by Richard Kenner

*** empty log message ***

From-SVN: r784
parent 3bb22aee
...@@ -2922,7 +2922,7 @@ ...@@ -2922,7 +2922,7 @@
(define_insn "" (define_insn ""
[(call (mem:SI (match_operand:SI 0 "call_operand" "l,s")) [(call (mem:SI (match_operand:SI 0 "call_operand" "l,s"))
(match_operand 1 "" "fg,fg")) (match_operand 1 "" "fg,fg"))
(clobber (match_scratch:SI 3 "=l,l"))] (clobber (match_scratch:SI 2 "=l,l"))]
"" ""
"@ "@
brl\;l 2,20(1) brl\;l 2,20(1)
......
/* Generate code from machine description to extract operands from insn as rtl. /* Generate code from machine description to extract operands from insn as rtl.
Copyright (C) 1987, 1991 Free Software Foundation, Inc. Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc.
This file is part of GNU CC. This file is part of GNU CC.
...@@ -22,6 +22,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -22,6 +22,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h" #include "config.h"
#include "rtl.h" #include "rtl.h"
#include "obstack.h" #include "obstack.h"
#include "insn-config.h"
static struct obstack obstack; static struct obstack obstack;
struct obstack *rtl_obstack = &obstack; struct obstack *rtl_obstack = &obstack;
...@@ -31,46 +32,73 @@ struct obstack *rtl_obstack = &obstack; ...@@ -31,46 +32,73 @@ struct obstack *rtl_obstack = &obstack;
extern void free (); extern void free ();
/* This structure contains all the information needed to describe one
set of extractions methods. Each method may be used by more than
one pattern if the operands are in the same place.
The string for each operand describes that path to the operand and
contains `0' through `9' when going into an expression and `a' through
`z' when going into a vector. We assume here that only the first operand
of an rtl expression is a vector. genrecog.c makes the same assumption
(and uses the same representation) and it is currently true. */
struct extraction
{
int op_count;
char *oplocs[MAX_RECOG_OPERANDS];
int dup_count;
char *duplocs[MAX_DUP_OPERANDS];
int dupnums[MAX_DUP_OPERANDS];
struct code_ptr *insns;
struct extraction *next;
};
/* Holds a single insn code that use an extraction method. */
struct code_ptr
{
int insn_code;
struct code_ptr *next;
};
static struct extraction *extractions;
/* Number instruction patterns handled, starting at 0 for first one. */ /* Number instruction patterns handled, starting at 0 for first one. */
static int insn_code_number; static int insn_code_number;
/* Records the large operand number in this insn. */
static int op_count;
/* Records the location of any operands using the string format described
above. */
static char *oplocs[MAX_RECOG_OPERANDS];
/* Number the occurrences of MATCH_DUP in each instruction, /* Number the occurrences of MATCH_DUP in each instruction,
starting at 0 for the first occurrence. */ starting at 0 for the first occurrence. */
static int dup_count; static int dup_count;
/* Record which operand numbers have been seen in the current pattern. /* Records the location of any MATCH_DUP operands. */
This table is made longer as needed. */
static char *operand_seen;
/* Current allocated length of operand_seen. */ static char *duplocs[MAX_DUP_OPERANDS];
static int operand_seen_length; /* Record the operand number of any MATCH_DUPs. */
/* Have we got any peephole patterns yet? */ static int dupnums[MAX_DUP_OPERANDS];
static int peephole_seen; /* Record the list of insn_codes for peepholes. */
/* While tree-walking an instruction pattern, we keep a chain static struct code_ptr *peepholes;
of these `struct link's to record how to get down to the
current position. In each one, POS is the operand number,
and if the operand is a vector VEC is the element number.
VEC is -1 if the operand is not a vector. */
struct link
{
struct link *next;
int pos;
int vecelt;
};
static void walk_rtx (); static void walk_rtx ();
static void print_path (); static void print_path ();
char *xmalloc (); char *xmalloc ();
char *xrealloc (); char *xrealloc ();
static void fatal (); static void fatal ();
static char *copystr ();
static void mybzero (); static void mybzero ();
void fancy_abort (); void fancy_abort ();
...@@ -79,68 +107,93 @@ gen_insn (insn) ...@@ -79,68 +107,93 @@ gen_insn (insn)
rtx insn; rtx insn;
{ {
register int i; register int i;
register struct extraction *p;
register struct code_ptr *link;
op_count = 0;
dup_count = 0; dup_count = 0;
/* No operands seen so far in this pattern. */ /* No operands seen so far in this pattern. */
mybzero (operand_seen, operand_seen_length); mybzero (oplocs, sizeof oplocs);
printf (" case %d:\n", insn_code_number);
/* Walk the insn's pattern, remembering at all times the path /* Walk the insn's pattern, remembering at all times the path
down to the walking point. */ down to the walking point. */
if (XVECLEN (insn, 1) == 1) if (XVECLEN (insn, 1) == 1)
walk_rtx (XVECEXP (insn, 1, 0), 0); walk_rtx (XVECEXP (insn, 1, 0), "");
else else
for (i = XVECLEN (insn, 1) - 1; i >= 0; i--) for (i = XVECLEN (insn, 1) - 1; i >= 0; i--)
{ {
struct link link; char *path = (char *) alloca (2);
link.next = 0;
link.pos = 0;
link.vecelt = i;
walk_rtx (XVECEXP (insn, 1, i), &link);
}
/* If the operand numbers used in the pattern are not consecutive, path[0] = 'a' + i;
don't leave an operand uninitialized. */ path[1] = 0;
for (i = operand_seen_length - 1; i >= 0; i--)
if (operand_seen[i]) walk_rtx (XVECEXP (insn, 1, i), path);
break;
for (; i >= 0; i--)
if (!operand_seen[i])
{
printf (" ro[%d] = const0_rtx;\n", i);
printf (" ro_loc[%d] = &junk;\n", i);
} }
printf (" break;\n");
}
/* Record that we have seen an operand with number OPNO in this pattern. */ link = (struct code_ptr *) xmalloc (sizeof (struct code_ptr));
link->insn_code = insn_code_number;
static void /* See if we find something that already had this extraction method. */
mark_operand_seen (opno)
int opno; for (p = extractions; p; p = p->next)
{
if (opno >= operand_seen_length)
{ {
operand_seen_length *= 2; if (p->op_count != op_count || p->dup_count != dup_count)
operand_seen = (char *) xrealloc (operand_seen, operand_seen_length); continue;
for (i = 0; i < op_count; i++)
if (p->oplocs[i] != oplocs[i]
&& ! (p->oplocs[i] != 0 && oplocs[i] != 0
&& ! strcmp (p->oplocs[i], oplocs[i])))
break;
if (i != op_count)
continue;
for (i = 0; i < dup_count; i++)
if (p->dupnums[i] != dupnums[i]
|| strcmp (p->duplocs[i], duplocs[i]))
break;
if (i != dup_count)
continue;
/* This extraction is the same as ours. Just link us in. */
link->next = p->insns;
p->insns = link;
return;
} }
operand_seen[opno] = 1; /* Otherwise, make a new extraction method. */
p = (struct extraction *) xmalloc (sizeof (struct extraction));
p->op_count = op_count;
p->dup_count = dup_count;
p->next = extractions;
extractions = p;
p->insns = link;
link->next = 0;
for (i = 0; i < op_count; i++)
p->oplocs[i] = oplocs[i];
for (i = 0; i < dup_count; i++)
p->dupnums[i] = dupnums[i], p->duplocs[i] = duplocs[i];
} }
static void static void
walk_rtx (x, path) walk_rtx (x, path)
rtx x; rtx x;
struct link *path; char *path;
{ {
register RTX_CODE code; register RTX_CODE code;
register int i; register int i;
register int len; register int len;
register char *fmt; register char *fmt;
struct link link; register struct code_ptr *link;
int depth = strlen (path);
char *newpath;
if (x == 0) if (x == 0)
return; return;
...@@ -157,49 +210,44 @@ walk_rtx (x, path) ...@@ -157,49 +210,44 @@ walk_rtx (x, path)
case MATCH_OPERAND: case MATCH_OPERAND:
case MATCH_SCRATCH: case MATCH_SCRATCH:
mark_operand_seen (XINT (x, 0)); oplocs[XINT (x, 0)] = copystr (path);
printf (" ro[%d] = *(ro_loc[%d] = &", op_count = MAX (op_count, XINT (x, 0) + 1);
XINT (x, 0), XINT (x, 0));
print_path (path);
printf (");\n");
break; break;
case MATCH_DUP: case MATCH_DUP:
case MATCH_OP_DUP: case MATCH_OP_DUP:
printf (" recog_dup_loc[%d] = &", dup_count); duplocs[dup_count] = copystr (path);
print_path (path); dupnums[dup_count] = XINT (x, 0);
printf (";\n");
printf (" recog_dup_num[%d] = %d;\n", dup_count, XINT (x, 0));
dup_count++; dup_count++;
break; break;
case MATCH_OPERATOR: case MATCH_OPERATOR:
mark_operand_seen (XINT (x, 0)); oplocs[XINT (x, 0)] = copystr (path);
printf (" ro[%d] = *(ro_loc[%d]\n = &", op_count = MAX (op_count, XINT (x, 0) + 1);
XINT (x, 0), XINT (x, 0));
print_path (path); newpath = (char *) alloca (depth + 2);
printf (");\n"); strcpy (newpath, path);
link.next = path; newpath[depth + 1] = 0;
link.vecelt = -1;
for (i = XVECLEN (x, 2) - 1; i >= 0; i--) for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
{ {
link.pos = i; newpath[depth] = '0' + i;
walk_rtx (XVECEXP (x, 2, i), &link); walk_rtx (XVECEXP (x, 2, i), newpath);
} }
return; return;
case MATCH_PARALLEL: case MATCH_PARALLEL:
mark_operand_seen (XINT (x, 0)); oplocs[XINT (x, 0)] = copystr (path);
printf (" ro[%d] = *(ro_loc[%d]\n = &", op_count = MAX (op_count, XINT (x, 0) + 1);
XINT (x, 0), XINT (x, 0));
print_path (path); newpath = (char *) alloca (depth + 2);
printf (");\n"); strcpy (newpath, path);
link.next = path; newpath[depth + 1] = 0;
link.pos = 0;
for (i = XVECLEN (x, 2) - 1; i >= 0; i--) for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
{ {
link.vecelt = i; newpath[depth] = 'a' + i;
walk_rtx (XVECEXP (x, 2, i), &link); walk_rtx (XVECEXP (x, 2, i), newpath);
} }
return; return;
...@@ -208,24 +256,26 @@ walk_rtx (x, path) ...@@ -208,24 +256,26 @@ walk_rtx (x, path)
return; return;
} }
link.next = path; newpath = (char *) alloca (depth + 2);
link.vecelt = -1; strcpy (newpath, path);
newpath[depth + 1] = 0;
fmt = GET_RTX_FORMAT (code); fmt = GET_RTX_FORMAT (code);
len = GET_RTX_LENGTH (code); len = GET_RTX_LENGTH (code);
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
{ {
link.pos = i;
if (fmt[i] == 'e' || fmt[i] == 'u') if (fmt[i] == 'e' || fmt[i] == 'u')
{ {
walk_rtx (XEXP (x, i), &link); newpath[depth] = '0' + i;
walk_rtx (XEXP (x, i), newpath);
} }
else if (fmt[i] == 'E') else if (fmt[i] == 'E')
{ {
int j; int j;
for (j = XVECLEN (x, i) - 1; j >= 0; j--) for (j = XVECLEN (x, i) - 1; j >= 0; j--)
{ {
link.vecelt = j; newpath[depth] = 'a' + i;
walk_rtx (XVECEXP (x, i, j), &link); walk_rtx (XVECEXP (x, i, j), newpath);
} }
} }
} }
...@@ -237,21 +287,34 @@ walk_rtx (x, path) ...@@ -237,21 +287,34 @@ walk_rtx (x, path)
static void static void
print_path (path) print_path (path)
struct link *path; char *path;
{ {
if (path == 0) register int len = strlen (path);
printf ("insn"); register int i;
else if (path->vecelt >= 0)
/* We first write out the operations (XEXP or XVECEXP) in reverse
order, then write "insn", then the indices in forward order. */
for (i = len - 1; i >=0 ; i--)
{ {
if (path[i] >= 'a' && path[i] <= 'z')
printf ("XVECEXP ("); printf ("XVECEXP (");
print_path (path->next); else if (path[i] >= '0' && path[i] <= '9')
printf (", %d, %d)", path->pos, path->vecelt); printf ("XEXP (");
}
else else
abort ();
}
printf ("insn");
for (i = 0; i < len; i++)
{ {
printf ("XEXP ("); if (path[i] >= 'a' && path[i] <= 'z')
print_path (path->next); printf (", 0, %d)", path[i] - 'a');
printf (", %d)", path->pos); else if (path[i] >= '0' && path[i] <= '9')
printf (", %d)", path[i] - '0');
else
abort ();
} }
} }
...@@ -296,6 +359,21 @@ fancy_abort () ...@@ -296,6 +359,21 @@ fancy_abort ()
fatal ("Internal gcc abort."); fatal ("Internal gcc abort.");
} }
static char *
copystr (s1)
char *s1;
{
register char *tem;
if (s1 == 0)
return 0;
tem = (char *) xmalloc (strlen (s1) + 1);
strcpy (tem, s1);
return tem;
}
static void static void
mybzero (b, length) mybzero (b, length)
register char *b; register char *b;
...@@ -314,6 +392,8 @@ main (argc, argv) ...@@ -314,6 +392,8 @@ main (argc, argv)
FILE *infile; FILE *infile;
extern rtx read_rtx (); extern rtx read_rtx ();
register int c, i; register int c, i;
struct extraction *p;
struct code_ptr *link;
obstack_init (rtl_obstack); obstack_init (rtl_obstack);
...@@ -334,9 +414,6 @@ main (argc, argv) ...@@ -334,9 +414,6 @@ main (argc, argv)
insn_code_number = 0; insn_code_number = 0;
operand_seen_length = 40;
operand_seen = (char *) xmalloc (40);
printf ("/* Generated automatically by the program `genextract'\n\ printf ("/* Generated automatically by the program `genextract'\n\
from the machine description file `md'. */\n\n"); from the machine description file `md'. */\n\n");
...@@ -346,6 +423,7 @@ from the machine description file `md'. */\n\n"); ...@@ -346,6 +423,7 @@ from the machine description file `md'. */\n\n");
/* This variable exists only so it can be the "location" /* This variable exists only so it can be the "location"
of any missing operand whose numbers are skipped by a given pattern. */ of any missing operand whose numbers are skipped by a given pattern. */
printf ("static rtx junk;\n"); printf ("static rtx junk;\n");
printf ("extern rtx recog_operand[];\n"); printf ("extern rtx recog_operand[];\n");
printf ("extern rtx *recog_operand_loc[];\n"); printf ("extern rtx *recog_operand_loc[];\n");
printf ("extern rtx *recog_dup_loc[];\n"); printf ("extern rtx *recog_dup_loc[];\n");
...@@ -359,10 +437,11 @@ from the machine description file `md'. */\n\n"); ...@@ -359,10 +437,11 @@ from the machine description file `md'. */\n\n");
printf (" register rtx *ro = recog_operand;\n"); printf (" register rtx *ro = recog_operand;\n");
printf (" register rtx **ro_loc = recog_operand_loc;\n"); printf (" register rtx **ro_loc = recog_operand_loc;\n");
printf (" int insn_code = INSN_CODE (insn);\n"); printf (" int insn_code = INSN_CODE (insn);\n");
printf (" if (insn_code == -1) fatal_insn_not_found (insn);\n");
printf (" insn = PATTERN (insn);\n"); printf (" insn = PATTERN (insn);\n");
printf (" switch (insn_code)\n"); printf (" switch (insn_code)\n");
printf (" {\n"); printf (" {\n");
printf (" case -1:\n");
printf (" fatal_insn_not_found (insn);\n\n");
/* Read the machine description. */ /* Read the machine description. */
...@@ -379,35 +458,77 @@ from the machine description file `md'. */\n\n"); ...@@ -379,35 +458,77 @@ from the machine description file `md'. */\n\n");
gen_insn (desc); gen_insn (desc);
++insn_code_number; ++insn_code_number;
} }
if (GET_CODE (desc) == DEFINE_PEEPHOLE)
else if (GET_CODE (desc) == DEFINE_PEEPHOLE)
{ {
printf (" case %d: goto peephole;\n", insn_code_number); struct code_ptr *link
= (struct code_ptr *) xmalloc (sizeof (struct code_ptr));
link->insn_code = insn_code_number;
link->next = peepholes;
peepholes = link;
++insn_code_number; ++insn_code_number;
++peephole_seen;
} }
if (GET_CODE (desc) == DEFINE_EXPAND || GET_CODE (desc) == DEFINE_SPLIT)
{ else if (GET_CODE (desc) == DEFINE_EXPAND
printf (" case %d: break;\n", insn_code_number); || GET_CODE (desc) == DEFINE_SPLIT)
++insn_code_number; ++insn_code_number;
} }
}
/* This should never be reached. */ /* Write out code to handle peepholes and the insn_codes that it should
printf ("\n default:\n abort ();\n"); be called for. */
if (peepholes)
if (peephole_seen)
{ {
for (link = peepholes; link; link = link->next)
printf (" case %d:\n", link->insn_code);
/* The vector in the insn says how many operands it has. /* The vector in the insn says how many operands it has.
And all it contains are operands. In fact, the vector was And all it contains are operands. In fact, the vector was
created just for the sake of this function. */ created just for the sake of this function. */
printf (" peephole:\n");
printf ("#if __GNUC__ > 1 && !defined (bcopy)\n"); printf ("#if __GNUC__ > 1 && !defined (bcopy)\n");
printf ("#define bcopy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT)\n"); printf ("#define bcopy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT)\n");
printf ("#endif\n"); printf ("#endif\n");
printf (" bcopy (&XVECEXP (insn, 0, 0), ro,\n"); printf (" bcopy (&XVECEXP (insn, 0, 0), ro,\n");
printf (" sizeof (rtx) * XVECLEN (insn, 0));\n"); printf (" sizeof (rtx) * XVECLEN (insn, 0));\n");
printf (" break;\n"); printf (" break;\n\n");
}
/* Write out all the ways to extract insn operands. */
for (p = extractions; p; p = p->next)
{
for (link = p->insns; link; link = link->next)
printf (" case %d:\n", link->insn_code);
for (i = 0; i < p->op_count; i++)
{
if (p->oplocs[i] == 0)
{
printf (" ro[%d] = const0_rtx;\n", i);
printf (" ro_loc[%d] = &junk;\n", i, i);
} }
else
{
printf (" ro[%d] = *(ro_loc[%d] = &", i, i);
print_path (p->oplocs[i]);
printf (");\n");
}
}
for (i = 0; i < p->dup_count; i++)
{
printf (" recog_dup_loc[%d] = &", i);
print_path (p->duplocs[i]);
printf (";\n");
printf (" recog_dup_num[%d] = %d;\n", i, p->dupnums[i]);
}
printf (" break;\n\n");
}
/* This should never be reached. Note that we would also reach this abort
if we tried to extract something whose INSN_CODE was a DEFINE_EXPAND or
DEFINE_SPLIT, but that is correct. */
printf (" default:\n abort ();\n");
printf (" }\n}\n"); printf (" }\n}\n");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment