/* ia64-gen.c -- Generate a shrunk set of opcode tables
- Copyright (c) 1999 Free Software Foundation, Inc.
+ Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
Written by Bob Manson, Cygnus Solutions, <manson@cygnus.com>
This file is part of GDB, GAS, and the GNU binutils.
*/
#include <stdio.h>
-#include <ctype.h>
#include "ansidecl.h"
#include "libiberty.h"
+#include "safe-ctype.h"
#include "sysdep.h"
#include "ia64-opc.h"
#include "ia64-opc-a.c"
struct completer_entry *completers;
/* Next entry in the chain. */
struct main_entry *next;
-} *maintable;
+ /* Index in the main table. */
+ int main_index;
+} *maintable, **ordered_table;
+int otlen = 0;
+int ottotlen = 0;
+int opcode_count = 0;
/* The set of possible completers for an opcode. */
struct completer_entry
list). This field is filled in by compute_completer_bits (). */
ia64_insn mask;
- /* Index into the opcode dependency list, or -1 if none */
+ /* Index into the opcode dependency list, or -1 if none. */
int dependencies;
+
+ /* Remember the order encountered in the opcode tables. */
+ int order;
};
/* One entry in the disassembler name table. */
/* The index into the main_table[] array. */
int insn;
+ /* The disassmbly priority of this entry. */
+ int priority;
+
/* The completer_index value for this entry. */
int completer_index;
struct bittree
{
struct disent *disent;
- struct bittree *bits[3];
+ struct bittree *bits[3]; /* 0, 1, and X (don't care) */
int bits_to_skip;
int skip_flag;
} *bittree;
int nchks;
int total_chks; /* total #of terminal insns */
int *chks; /* insn classes which read (RAW), write
- (WAW), or write (WAR) this rsrc */ //
+ (WAW), or write (WAR) this rsrc */
int *chknotes; /* dependency notes for each class */
int nregs;
int total_regs; /* total #of terminal insns */
for (i=0;i < count;i++)
set[deps[i]] = 1;
count = 0;
- for (i=0;i < sizeof(set);i++)
+ for (i=0;i < (int)sizeof(set);i++)
if (set[i])
++count;
list = tmalloc(struct deplist);
list->len = count;
list->deps = (unsigned short *)malloc (sizeof(unsigned short) * count);
- for (i=0, count=0;i < sizeof(set);i++)
+ for (i=0, count=0;i < (int)sizeof(set);i++)
{
if (set[i])
{
if ((comment = strchr(name, '[')) != NULL)
is_class = 1;
if ((notestr = strchr(name, '+')) != NULL)
+ is_class = 1;
+
+ /* If it is a composite class, then ignore comments and notes that come after
+ the '\\', since they don't apply to the part we are decoding now. */
+ if (xsect)
+ {
+ if (comment > xsect)
+ comment = 0;
+ if (notestr > xsect)
+ notestr = 0;
+ }
+
+ if (notestr)
{
char *nextnotestr;
- is_class = 1;
note = atoi (notestr + 1);
if ((nextnotestr = strchr (notestr + 1, '+')) != NULL)
{
}
}
- /* if it's a composite class, leave the notes and comments in place so that
- we have a unique name for the composite class */
+ /* If it's a composite class, leave the notes and comments in place so that
+ we have a unique name for the composite class. Otherwise, we remove
+ them. */
if (!xsect)
{
if (notestr)
existing class or terminal with the same name. */
if ((xsect || comment || notestr) && is_class)
{
- // first, populate with the class we're based on
+ /* First, populate with the class we're based on. */
char *subname = name;
if (xsect)
*xsect = 0;
FILE *fp = fopen("ia64-ic.tbl", "r");
char buf[2048];
+ if (fp == NULL){
+ fprintf (stderr, "Can't find ia64-ic.tbl for reading\n");
+ exit(1);
+ }
+
/* discard first line */
fgets (buf, sizeof(buf), fp);
if (fgets (buf, sizeof(buf), fp) == NULL)
break;
- while (isspace(buf[strlen(buf)-1]))
+ while (ISSPACE (buf[strlen(buf)-1]))
buf[strlen(buf)-1] = '\0';
name = tmp = buf;
char *subname;
int sub;
- while (*tmp && isspace(*tmp))
+ while (*tmp && ISSPACE (*tmp))
{
++tmp;
if (tmp == buf + sizeof(buf))
int create = 0;
char *name;
- while (isspace(*tmp))
+ while (ISSPACE (*tmp))
++tmp;
name = tmp;
while (*tmp && *tmp != ',')
return IA64_DVS_INSTR;
else if (strcmp (sem, "specific") == 0)
return IA64_DVS_SPECIFIC;
+ else if (strcmp (sem, "stop") == 0)
+ return IA64_DVS_STOP;
else
return IA64_DVS_OTHER;
}
FILE *fp = fopen(filename, "r");
char buf[1024];
+ if (fp == NULL){
+ fprintf (stderr, "Can't find %s for reading\n", filename);
+ exit(1);
+ }
+
fgets(buf, sizeof(buf), fp);
while (!feof(fp))
{
if (fgets (buf, sizeof(buf), fp) == NULL)
break;
- while (isspace(buf[strlen(buf)-1]))
+ while (ISSPACE (buf[strlen(buf)-1]))
buf[strlen(buf)-1] = '\0';
name = tmp = buf;
++tmp;
*tmp++ = '\0';
- while (isspace (*tmp))
+ while (ISSPACE (*tmp))
++tmp;
regp = tmp;
tmp = strchr (tmp, ';');
if (!tmp)
abort ();
*tmp++ = 0;
- while (isspace (*tmp))
+ while (ISSPACE (*tmp))
++tmp;
chkp = tmp;
tmp = strchr (tmp, ';');
if (!tmp)
abort ();
*tmp++ = 0;
- while (isspace (*tmp))
+ while (ISSPACE (*tmp))
++tmp;
semantics = parse_semantics (tmp);
extra = semantics == IA64_DVS_OTHER ? xstrdup (tmp) : NULL;
if (!field)
{
return op == IA64_OPND_RR_R3 || op == IA64_OPND_DBR_R3
- || op == IA64_OPND_IBR_R3 || op == IA64_OPND_PKR_R3
- || op == IA64_OPND_PMC_R3 || op == IA64_OPND_PMD_R3
+ || op == IA64_OPND_IBR_R3 || op == IA64_OPND_PKR_R3
+ || op == IA64_OPND_PMC_R3 || op == IA64_OPND_PMD_R3
|| op == IA64_OPND_MSR_R3 || op == IA64_OPND_CPUID_R3;
}
else
resolved = idesc->operands[0] == IA64_OPND_B2;
else if (strcmp (ic->name, "invala") == 0)
resolved = strcmp (idesc->name, ic->name) == 0;
+ else if (strncmp (idesc->name, "st", 2) == 0
+ && strstr (format, "M5") != NULL)
+ resolved = idesc->flags & IA64_OPCODE_POSTINC;
else
resolved = 0;
}
return IA64_RS_FRb;
if (strstr (name, "GR%") != NULL)
return IA64_RS_GR;
- if (strstr (name, "PR%") != NULL)
+ if (strstr (name, "PR%, % in 1 ") != NULL)
return IA64_RS_PR;
+ if (strstr (name, "PR%, % in 16 ") != NULL)
+ return IA64_RS_PRr;
fprintf (stderr, "Warning! Don't know how to specify %% dependency %s\n",
name);
(int)rdeps[i]->mode, (int)rdeps[i]->semantics, regindex);
if (rdeps[i]->semantics == IA64_DVS_OTHER)
printf ("\"%s\", ", rdeps[i]->extra);
+ else
+ printf ("NULL, ");
printf("},\n");
}
printf ("};\n\n");
}
\f
struct disent *
-add_dis_table_ent (which, insn, completer_index)
+add_dis_table_ent (which, insn, order, completer_index)
struct disent *which;
int insn;
+ int order;
int completer_index;
{
int ci = 0;
ent->nextcnt = 0;
ent->nexte = NULL;
ent->insn = insn;
+ ent->priority = order;
+
while (completer_index != 1)
{
ci = (ci << 1) | (completer_index & 1);
}
\f
void
-insert_bit_table_ent (curr_ent, bit, opcode, mask, opcodenum, completer_index)
+insert_bit_table_ent (curr_ent, bit, opcode, mask,
+ opcodenum, order, completer_index)
struct bittree *curr_ent;
int bit;
ia64_insn opcode;
ia64_insn mask;
int opcodenum;
+ int order;
int completer_index;
{
ia64_insn m;
if (bit == -1)
{
- struct disent *nent = add_dis_table_ent (curr_ent->disent, opcodenum,
+ struct disent *nent = add_dis_table_ent (curr_ent->disent,
+ opcodenum, order,
completer_index);
curr_ent->disent = nent;
return;
next = make_bittree_entry ();
curr_ent->bits[b] = next;
}
- insert_bit_table_ent (next, bit - 1, opcode, mask, opcodenum,
+ insert_bit_table_ent (next, bit - 1, opcode, mask, opcodenum, order,
completer_index);
}
\f
void
add_dis_entry (first, opcode, mask, opcodenum, ent, completer_index)
- int first;
+ struct bittree *first;
ia64_insn opcode;
ia64_insn mask;
int opcodenum;
{
abort ();
}
+
while (ent != NULL)
{
ia64_insn newopcode = (opcode & (~ ent->mask)) | ent->bits;
(completer_index << 1) | 1);
if (ent->is_terminal)
{
- insert_bit_table_ent (bittree, 40, newopcode, mask, opcodenum,
+ insert_bit_table_ent (bittree, 40, newopcode, mask,
+ opcodenum, opcode_count - ent->order - 1,
(completer_index << 1) | 1);
}
completer_index <<= 1;
while (ent != NULL)
{
- printf ("{ 0x%x, %d, %d },\n", ent->completer_index,
- ent->insn,
- (ent->nexte != NULL ? 1 : 0));
+ printf ("{ 0x%x, %d, %d, %d },\n", ent->completer_index,
+ ent->insn, (ent->nexte != NULL ? 1 : 0),
+ ent->priority);
ent = ent->nexte;
}
cent = cent->next_ent;
void
generate_disassembler ()
{
- int mainnum = 0;
- struct main_entry *ptr = maintable;
+ int i;
bittree = make_bittree_entry ();
- while (ptr != NULL)
+ for (i=0; i < otlen;i++)
{
+ struct main_entry *ptr = ordered_table[i];
+
if (ptr->opcode->type != IA64_TYPE_DYN)
{
add_dis_entry (bittree,
- ptr->opcode->opcode, ptr->opcode->mask, mainnum,
+ ptr->opcode->opcode, ptr->opcode->mask,
+ ptr->main_index,
ptr->completers, 1);
}
- mainnum++;
- ptr = ptr->next;
}
compact_distree (bittree);
|| ent1->bits != ent2->bits
|| ent1->mask != ent2->mask
|| ent1->is_terminal != ent2->is_terminal
- || ent1->dependencies != ent2->dependencies)
+ || ent1->dependencies != ent2->dependencies
+ || ent1->order != ent2->order)
{
return 0;
}
int
insert_opcode_dependencies (opc, cmp)
struct ia64_opcode *opc;
- struct completer_entry *cmp;
+ struct completer_entry *cmp ATTRIBUTE_UNUSED;
{
/* note all resources which point to this opcode. rfi has the most chks
(79) and cmpxchng has the most regs (54) so 100 here should be enough */
}
\f
void
-insert_completer_entry (opc, tabent)
+insert_completer_entry (opc, tabent, order)
struct ia64_opcode *opc;
struct main_entry *tabent;
+ int order;
{
struct completer_entry **ptr = &tabent->completers;
struct completer_entry *parent = NULL;
need_new_ent = 0;
break;
}
- else if (cmpres < 0)
- {
- break;
- }
else
{
ptr = &((*ptr)->alternative);
(*ptr)->is_terminal = 1;
(*ptr)->mask = (ia64_insn)-1;
(*ptr)->bits = opc->opcode;
-
(*ptr)->dependencies = insert_opcode_dependencies (opc, *ptr);
+ (*ptr)->order = order;
}
\f
void
name = insert_string (prefix);
/* Walk the list of opcode table entries. If it's a new
- instruction, allocate and fill in a new entry. */
+ instruction, allocate and fill in a new entry. Note
+ the main table is alphabetical by opcode name. */
while (*place != NULL)
{
nent->next = *place;
nent->completers = 0;
*place = nent;
+
+ if (otlen == ottotlen)
+ {
+ ottotlen += 20;
+ ordered_table = (struct main_entry **)
+ xrealloc (ordered_table, sizeof (struct main_entry *) * ottotlen);
+ }
+ ordered_table[otlen++] = nent;
}
- insert_completer_entry (opc, *place);
+
+ insert_completer_entry (opc, *place, opcode_count++);
}
\f
void
print_main_table ()
{
struct main_entry *ptr = maintable;
+ int index = 0;
printf ("static const struct ia64_main_table\nmain_table[] = {\n");
while (ptr != NULL)
{
- printf (" { %d, %d, %d, 0x%llxull, 0x%llxull, { %d, %d, %d, %d, %d }, 0x%x, %d, },\n",
+ printf (" { %d, %d, %d, 0x",
ptr->name->num,
ptr->opcode->type,
- ptr->opcode->num_outputs,
- ptr->opcode->opcode,
- ptr->opcode->mask,
+ ptr->opcode->num_outputs);
+ fprintf_vma (stdout, ptr->opcode->opcode);
+ printf ("ull, 0x");
+ fprintf_vma (stdout, ptr->opcode->mask);
+ printf ("ull, { %d, %d, %d, %d, %d }, 0x%x, %d, },\n",
ptr->opcode->operands[0],
ptr->opcode->operands[1],
ptr->opcode->operands[2],
ptr->opcode->flags,
ptr->completers->num);
+ ptr->main_index = index++;
+
ptr = ptr->next;
}
printf ("};\n\n");
}
\f
int
-main (int argc, char **argv)
+main (argc, argv)
+ int argc;
+ char **argv ATTRIBUTE_UNUSED;
{
if (argc > 1)
{