/* ia64-gen.c -- Generate a shrunk set of opcode tables
- Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1999-2020 Free Software Foundation, Inc.
Written by Bob Manson, Cygnus Solutions, <manson@cygnus.com>
- This file is part of GDB, GAS, and the GNU binutils.
+ This file is part of the GNU opcodes library.
- GDB, GAS, and the GNU binutils are free software; you can redistribute
- them and/or modify them under the terms of the GNU General Public
- License as published by the Free Software Foundation; either version
- 2, or (at your option) any later version.
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
- GDB, GAS, and the GNU binutils are distributed in the hope that they
- will be useful, but WITHOUT ANY WARRANTY; without even the implied
- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- the GNU General Public License for more details.
+ It is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
You should have received a copy of the GNU General Public License
along with this file; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
/* While the ia64-opc-* set of opcode tables are easy to maintain,
they waste a tremendous amount of space. ia64-gen rearranges the
- instructions into a directed acyclic graph (DAG) of instruction opcodes and
- their possible completers, as well as compacting the set of strings used.
+ instructions into a directed acyclic graph (DAG) of instruction opcodes and
+ their possible completers, as well as compacting the set of strings used.
The disassembler table consists of a state machine that does
branching based on the bits of the opcode being disassembled. The
state encodings have been chosen to minimize the amount of space
- required.
+ required.
- The resource table is constructed based on some text dependency tables,
+ The resource table is constructed based on some text dependency tables,
which are also easier to maintain than the final representation. */
+#include "sysdep.h"
#include <stdio.h>
#include <stdarg.h>
#include <errno.h>
-#include "ansidecl.h"
#include "libiberty.h"
#include "safe-ctype.h"
-#include "sysdep.h"
#include "getopt.h"
#include "ia64-opc.h"
#include "ia64-opc-a.c"
#include <libintl.h>
#define _(String) gettext (String)
+/* This is a copy of fprintf_vma from bfd/bfd-in2.h. We have to use this
+ always, because we might be compiled without BFD64 defined, if configured
+ for a 32-bit target and --enable-targets=all is used. This will work for
+ both 32-bit and 64-bit hosts. */
+#define _opcode_int64_low(x) ((unsigned long) (((x) & 0xffffffff)))
+#define _opcode_int64_high(x) ((unsigned long) (((x) >> 32) & 0xffffffff))
+#define opcode_fprintf_vma(s,x) \
+ fprintf ((s), "%08lx%08lx", _opcode_int64_high (x), _opcode_int64_low (x))
+
const char * program_name = NULL;
int debug = 0;
+#define NELEMS(a) (sizeof (a) / sizeof ((a)[0]))
#define tmalloc(X) (X *) xmalloc (sizeof (X))
+typedef unsigned long long ci_t;
/* The main opcode table entry. Each entry is a unique combination of
name and flags (no two entries in the table compare as being equal
via opcodes_eq). */
int priority;
/* The completer_index value for this entry. */
- int completer_index;
+ ci_t completer_index;
/* How many other entries share this decode. */
int nextcnt;
alphabetical order. */
/* One entry in the string table. */
-struct string_entry
+struct string_entry
{
/* The index in the ia64_strings[] array for this entry. */
int num;
struct rdep
{
char *name; /* Resource name. */
- unsigned
+ unsigned
mode:2, /* RAW, WAW, or WAR. */
semantics:3; /* Dependency semantics. */
char *extra; /* Additional semantics info. */
- int nchks;
+ int nchks;
int total_chks; /* Total #of terminal insns. */
int *chks; /* Insn classes which read (RAW), write
(WAW), or write (WAR) this rsrc. */
/* Array of all instruction classes. */
struct iclass
-{
+{
char *name; /* Instruction class name. */
int is_class; /* Is a class, not a terminal. */
- int nsubs;
+ int nsubs;
int *subs; /* Other classes within this class. */
- int nxsubs;
+ int nxsubs;
int xsubs[4]; /* Exclusions. */
char *comment; /* Optional comment. */
int note; /* Optional note. */
static int dlisttotlen = 0;
-static void fail (const char *, ...);
-static void warn (const char *, ...);
+static void fail (const char *, ...) ATTRIBUTE_PRINTF_1;
+static void warn (const char *, ...) ATTRIBUTE_PRINTF_1;
static struct rdep * insert_resource (const char *, enum ia64_dependency_mode);
static int deplist_equals (struct deplist *, struct deplist *);
static short insert_deplist (int, unsigned short *);
static void print_version (void);
static void usage (FILE *, int);
static void finish_distable (void);
-static void insert_bit_table_ent (struct bittree *, int, ia64_insn, ia64_insn, int, int, int);
-static void add_dis_entry (struct bittree *, ia64_insn, ia64_insn, int, struct completer_entry *, int);
+static void insert_bit_table_ent (struct bittree *, int, ia64_insn, ia64_insn, int, int, ci_t);
+static void add_dis_entry (struct bittree *, ia64_insn, ia64_insn, int, struct completer_entry *, ci_t);
static void compact_distree (struct bittree *);
static struct bittree * make_bittree_entry (void);
-static struct disent * add_dis_table_ent (struct disent *, int, int, int);
+static struct disent * add_dis_table_ent (struct disent *, int, int, ci_t);
\f
static void
fail (const char *message, ...)
{
va_list args;
-
+
va_start (args, message);
fprintf (stderr, _("%s: Error: "), program_name);
vfprintf (stderr, message, args);
rdeps[rdepslen]->name = xstrdup (name);
rdeps[rdepslen]->mode = type;
rdeps[rdepslen]->waw_special = 0;
-
+
return rdeps[rdepslen++];
}
/* Add the given pair of dependency lists to the opcode dependency list. */
static short
-insert_dependencies (int nchks, unsigned short *chks,
+insert_dependencies (int nchks, unsigned short *chks,
int nregs, unsigned short *regs)
{
struct opdep *pair;
chkind = insert_deplist (nchks, chks);
for (i = 0; i < opdeplen; i++)
- if (opdeps[i]->chk == chkind
+ if (opdeps[i]->chk == chkind
&& opdeps[i]->reg == regind)
return i;
pair = tmalloc (struct opdep);
pair->chk = chkind;
pair->reg = regind;
-
+
if (opdeplen == opdeptotlen)
{
opdeptotlen += 20;
return opdeplen++;
}
-static void
+static void
mark_used (struct iclass *ic, int clear_terminals)
{
int i;
int ind;
int is_class = 0;
- if (strncmp (full_name, "IC:", 3) == 0)
+ if (CONST_STRNEQ (full_name, "IC:"))
{
name = xstrdup (full_name + 3);
is_class = 1;
if (strcmp (name, ics[i]->name) == 0
&& ((comment == NULL && ics[i]->comment == NULL)
|| (comment != NULL && ics[i]->comment != NULL
- && strncmp (ics[i]->comment, comment,
+ && strncmp (ics[i]->comment, comment,
strlen (ics[i]->comment)) == 0))
&& note == ics[i]->note)
return i;
ics[ind]->nsubs = 1;
ics[ind]->subs = tmalloc(int);
- ics[ind]->subs[0] = fetch_insn_class (subname, 1);;
+ ics[ind]->subs[0] = fetch_insn_class (subname, 1);
}
while (xsect)
int iclass;
char *name;
char *tmp;
-
+
if (fgets (buf, sizeof (buf), fp) == NULL)
break;
-
+
while (ISSPACE (buf[strlen (buf) - 1]))
buf[strlen (buf) - 1] = '\0';
}
if (*tmp == ',')
*tmp++ = '\0';
-
+
ics[iclass]->subs = (int *)
- xrealloc ((void *)ics[iclass]->subs,
+ xrealloc ((void *)ics[iclass]->subs,
(ics[iclass]->nsubs + 1) * sizeof (int));
sub = fetch_insn_class (subname, 1);
}
/* Make sure classes come before terminals. */
- qsort ((void *)ics[iclass]->subs,
+ qsort ((void *)ics[iclass]->subs,
ics[iclass]->nsubs, sizeof(int), sub_compare);
}
fclose (fp);
/* Extract the insn classes from the given line. */
static void
-parse_resource_users (ref, usersp, nusersp, notesp)
- const char *ref;
- int **usersp;
- int *nusersp;
- int **notesp;
+parse_resource_users (const char *ref, int **usersp, int *nusersp,
+ int **notesp)
{
int c;
char *line = xstrdup (ref);
int iclass;
int create = 0;
char *name;
-
+
while (ISSPACE (*tmp))
++tmp;
name = tmp;
++tmp;
c = *tmp;
*tmp++ = '\0';
-
+
xsect = strchr (name, '\\');
if ((notestr = strstr (name, "+")) != NULL)
{
if (!xsect)
*notestr = '\0';
}
- else
+ else
note = 0;
/* All classes are created when the insn class table is parsed;
are read. Only create new classes if it's *not* an insn class,
or if it's a composite class (which wouldn't necessarily be in the IC
table). */
- if (strncmp (name, "IC:", 3) != 0 || xsect != NULL)
+ if (! CONST_STRNEQ (name, "IC:") || xsect != NULL)
create = 1;
-
+
iclass = fetch_insn_class (name, create);
if (iclass != -1)
{
return IA64_DVS_SPECIFIC;
else if (strcmp (sem, "stop") == 0)
return IA64_DVS_STOP;
- else
+ else
return IA64_DVS_OTHER;
}
while (*tmp != ';')
++tmp;
*tmp++ = '\0';
-
+
while (ISSPACE (*tmp))
++tmp;
regp = tmp;
}
/* Is the given operand an indirect register file operand? */
-static int
+static int
irf_operand (int op, const char *field)
{
if (!field)
|| (op == IA64_OPND_PMC_R3 && strstr (field, "pmc"))
|| (op == IA64_OPND_PMD_R3 && strstr (field, "pmd"))
|| (op == IA64_OPND_MSR_R3 && strstr (field, "msr"))
- || (op == IA64_OPND_CPUID_R3 && strstr (field, "cpuid")));
+ || (op == IA64_OPND_CPUID_R3 && strstr (field, "cpuid"))
+ || (op == IA64_OPND_DAHR_R3 && strstr (field, "dahr")));
}
}
-/* Handle mov_ar, mov_br, mov_cr, mov_indirect, mov_ip, mov_pr, mov_psr, and
- mov_um insn classes. */
+/* Handle mov_ar, mov_br, mov_cr, move_dahr, mov_indirect, mov_ip, mov_pr,
+ * mov_psr, and mov_um insn classes. */
static int
-in_iclass_mov_x (struct ia64_opcode *idesc, struct iclass *ic,
+in_iclass_mov_x (struct ia64_opcode *idesc, struct iclass *ic,
const char *format, const char *field)
{
int plain_mov = strcmp (idesc->name, "mov") == 0;
return strstr (format, "M33") != NULL;
}
break;
+ case 'd':
+ {
+ int m50 = plain_mov && idesc->operands[0] == IA64_OPND_DAHR3;
+ if (m50)
+ return strstr (format, "M50") != NULL;
+ }
+ break;
case 'i':
if (ic->name[5] == 'n')
{
/* Is the given opcode in the given insn class? */
static int
-in_iclass (struct ia64_opcode *idesc, struct iclass *ic,
+in_iclass (struct ia64_opcode *idesc, struct iclass *ic,
const char *format, const char *field, int *notep)
{
int i;
if (ic->comment)
{
- if (!strncmp (ic->comment, "Format", 6))
+ if (CONST_STRNEQ (ic->comment, "Format"))
{
/* Assume that the first format seen is the most restrictive, and
only keep a later one if it looks like it's more restrictive. */
{
warn (_("most recent format '%s'\nappears more restrictive than '%s'\n"),
ic->comment, format);
- format = ic->comment;
+ format = ic->comment;
}
}
else
format = ic->comment;
}
- else if (!strncmp (ic->comment, "Field", 5))
+ else if (CONST_STRNEQ (ic->comment, "Field"))
{
if (field)
warn (_("overlapping field %s->%s\n"),
instructions. */
if (ic->nsubs == 0 && ic->nxsubs == 0)
{
- int is_mov = strncmp (idesc->name, "mov", 3) == 0;
+ int is_mov = CONST_STRNEQ (idesc->name, "mov");
int plain_mov = strcmp (idesc->name, "mov") == 0;
int len = strlen(ic->name);
resolved = ((strncmp (ic->name, idesc->name, len) == 0)
- && (idesc->name[len] == '\0'
+ && (idesc->name[len] == '\0'
|| idesc->name[len] == '.'));
- /* All break and nop variations must match exactly. */
+ /* All break, nop, and hint variations must match exactly. */
if (resolved &&
(strcmp (ic->name, "break") == 0
- || strcmp (ic->name, "nop") == 0))
+ || strcmp (ic->name, "nop") == 0
+ || strcmp (ic->name, "hint") == 0))
resolved = strcmp (ic->name, idesc->name) == 0;
/* Assume restrictions in the FORMAT/FIELD negate resolution,
if (resolved && format)
{
- if (strncmp (idesc->name, "dep", 3) == 0
+ if (CONST_STRNEQ (idesc->name, "dep")
&& strstr (format, "I13") != NULL)
resolved = idesc->operands[1] == IA64_OPND_IMM8;
- else if (strncmp (idesc->name, "chk", 3) == 0
+ else if (CONST_STRNEQ (idesc->name, "chk")
&& strstr (format, "M21") != NULL)
resolved = idesc->operands[0] == IA64_OPND_F2;
- else if (strncmp (idesc->name, "lfetch", 6) == 0)
+ else if (CONST_STRNEQ (idesc->name, "lfetch"))
resolved = (strstr (format, "M14 M15") != NULL
&& (idesc->operands[1] == IA64_OPND_R2
|| idesc->operands[1] == IA64_OPND_IMM9b));
- else if (strncmp (idesc->name, "br.call", 7) == 0
+ else if (CONST_STRNEQ (idesc->name, "br.call")
&& strstr (format, "B5") != NULL)
resolved = idesc->operands[1] == IA64_OPND_B2;
- else if (strncmp (idesc->name, "br.call", 7) == 0
+ else if (CONST_STRNEQ (idesc->name, "br.call")
&& strstr (format, "B3") != NULL)
resolved = idesc->operands[1] == IA64_OPND_TGT25c;
- else if (strncmp (idesc->name, "brp", 3) == 0
+ else if (CONST_STRNEQ (idesc->name, "brp")
&& strstr (format, "B7") != NULL)
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)
+ else if (CONST_STRNEQ (idesc->name, "st")
+ && (strstr (format, "M5") != NULL
+ || strstr (format, "M10") != NULL))
+ resolved = idesc->flags & IA64_OPCODE_POSTINC;
+ else if (CONST_STRNEQ (idesc->name, "ld")
+ && (strstr (format, "M2 M3") != NULL
+ || strstr (format, "M12") != NULL
+ || strstr (format, "M7 M8") != NULL))
resolved = idesc->flags & IA64_OPCODE_POSTINC;
else
resolved = 0;
}
- /* Misc brl variations ('.cond' is optional);
+ /* Misc brl variations ('.cond' is optional);
plain brl matches brl.cond. */
if (!resolved
&& (strcmp (idesc->name, "brl") == 0
- || strncmp (idesc->name, "brl.", 4) == 0)
+ || CONST_STRNEQ (idesc->name, "brl."))
&& strcmp (ic->name, "brl.cond") == 0)
{
resolved = 1;
}
/* Misc br variations ('.cond' is optional). */
- if (!resolved
+ if (!resolved
&& (strcmp (idesc->name, "br") == 0
- || strncmp (idesc->name, "br.", 3) == 0)
+ || CONST_STRNEQ (idesc->name, "br."))
&& strcmp (ic->name, "br.cond") == 0)
{
if (format)
}
/* probe variations. */
- if (!resolved && strncmp (idesc->name, "probe", 5) == 0)
+ if (!resolved && CONST_STRNEQ (idesc->name, "probe"))
{
- resolved = strcmp (ic->name, "probe") == 0
- && !((strstr (idesc->name, "fault") != NULL)
+ resolved = strcmp (ic->name, "probe") == 0
+ && !((strstr (idesc->name, "fault") != NULL)
^ (format && strstr (format, "M40") != NULL));
}
}
/* Some variants of mov and mov.[im]. */
- if (!resolved && strncmp (ic->name, "mov_", 4) == 0)
+ if (!resolved && CONST_STRNEQ (ic->name, "mov_"))
resolved = in_iclass_mov_x (idesc, ic, format, field);
}
- /* Keep track of this so we can flag any insn classes which aren't
+ /* Keep track of this so we can flag any insn classes which aren't
mapped onto at least one real insn. */
if (resolved)
ic->terminal_resolved = 1;
break;
}
}
-
+
/* If it's in this IC, add the IC note (if any) to the insn. */
if (resolved)
{
return 18;
else if (strstr (name, "[RNAT]"))
return 19;
+ else if (strstr (name, "[FCR]"))
+ return 21;
+ else if (strstr (name, "[EFLAG]"))
+ return 24;
+ else if (strstr (name, "[CSD]"))
+ return 25;
+ else if (strstr (name, "[SSD]"))
+ return 26;
+ else if (strstr (name, "[CFLG]"))
+ return 27;
+ else if (strstr (name, "[FSR]"))
+ return 28;
+ else if (strstr (name, "[FIR]"))
+ return 29;
+ else if (strstr (name, "[FDR]"))
+ return 30;
else if (strstr (name, "[CCV]"))
return 32;
else if (strstr (name, "[ITC]"))
return 44;
+ else if (strstr (name, "[RUC]"))
+ return 45;
else if (strstr (name, "[PFS]"))
return 64;
else if (strstr (name, "[LC]"))
return 44;
else if (strstr (name, ".ia"))
return 45;
+ else if (strstr (name, ".vm"))
+ return 46;
else
abort ();
default:
return IA64_RS_ARb;
if (strstr (name, "BR%") != NULL)
return IA64_RS_BR;
+ if (strstr (name, "CR[IIB%]") != NULL)
+ return IA64_RS_CR_IIB;
if (strstr (name, "CR[IRR%]") != NULL)
return IA64_RS_CR_IRR;
if (strstr (name, "CR[LRR%]") != NULL)
return IA64_RS_CR_LRR;
if (strstr (name, "CR%") != NULL)
return IA64_RS_CR;
+ if (strstr (name, "DAHR%, % in 0") != NULL)
+ return IA64_RS_DAHR;
if (strstr (name, "FR%, % in 0") != NULL)
return IA64_RS_FR;
if (strstr (name, "FR%, % in 2") != NULL)
return IA64_RS_PMD;
if (strstr (name, "RR#") != NULL)
return IA64_RS_RR;
-
+
warn (_("Don't know how to specify # dependency %s\n"),
name);
}
- else if (strncmp (name, "AR[FPSR]", 8) == 0)
+ else if (CONST_STRNEQ (name, "AR[FPSR]"))
return IA64_RS_AR_FPSR;
- else if (strncmp (name, "AR[", 3) == 0)
+ else if (CONST_STRNEQ (name, "AR["))
return IA64_RS_ARX;
- else if (strncmp (name, "CR[", 3) == 0)
+ else if (CONST_STRNEQ (name, "CR["))
return IA64_RS_CRX;
- else if (strncmp (name, "PSR.", 4) == 0)
+ else if (CONST_STRNEQ (name, "PSR."))
return IA64_RS_PSR;
else if (strcmp (name, "InService*") == 0)
return IA64_RS_INSERVICE;
}
static void
-print_dependency_table ()
+print_dependency_table (void)
{
int i, j;
- if (debug)
+ if (debug)
{
for (i=0;i < iclen;i++)
{
ics[i]->name);
}
}
- else
+ else
{
if (!ics[i]->terminal_resolved && !ics[i]->orphan)
{
if (debug > 1)
for (i = 0; i < rdepslen; i++)
- {
+ {
static const char *mode_str[] = { "RAW", "WAW", "WAR" };
if (rdeps[i]->total_chks == 0)
- warn (_("Warning: rsrc %s (%s) has no chks%s\n"),
- rdeps[i]->name, mode_str[rdeps[i]->mode],
- rdeps[i]->total_regs ? "" : " or regs");
+ {
+ if (rdeps[i]->total_regs)
+ warn (_("Warning: rsrc %s (%s) has no chks\n"),
+ rdeps[i]->name, mode_str[rdeps[i]->mode]);
+ else
+ warn (_("Warning: rsrc %s (%s) has no chks or regs\n"),
+ rdeps[i]->name, mode_str[rdeps[i]->mode]);
+ }
else if (rdeps[i]->total_regs == 0)
warn (_("rsrc %s (%s) has no regs\n"),
rdeps[i]->name, mode_str[rdeps[i]->mode]);
for (i = 0; i < rdepslen; i++)
{
/* '%', '#', AR[], CR[], or PSR. indicates we need to specify the actual
- resource used. */
+ resource used. */
int specifier = lookup_specifier (rdeps[i]->name);
int regindex = lookup_regindex (rdeps[i]->name, specifier);
rdeps[i]->name, specifier,
(int)rdeps[i]->mode, (int)rdeps[i]->semantics, regindex);
if (rdeps[i]->semantics == IA64_DVS_OTHER)
- printf ("\"%s\", ", rdeps[i]->extra);
+ {
+ const char *quote, *rest;
+
+ putchar ('\"');
+ rest = rdeps[i]->extra;
+ quote = strchr (rest, '\"');
+ while (quote != NULL)
+ {
+ printf ("%.*s\\\"", (int) (quote - rest), rest);
+ rest = quote + 1;
+ quote = strchr (rest, '\"');
+ }
+ printf ("%s\", ", rest);
+ }
else
printf ("NULL, ");
printf("},\n");
/* And dependency lists. */
for (i=0;i < dlistlen;i++)
{
- int len = 2;
- printf ("static const short dep%d[] = {\n ", i);
+ unsigned int len = (unsigned) -1;
+ printf ("static const unsigned short dep%d[] = {", i);
for (j=0;j < dlists[i]->len; j++)
{
- len += printf ("%d, ", dlists[i]->deps[j]);
- if (len > 75)
+ if (len > 74)
{
- printf("\n ");
- len = 2;
+ printf("\n ");
+ len = 1;
}
+ len += printf (" %d,", dlists[i]->deps[j]);
}
printf ("\n};\n\n");
}
printf (" { ");
if (opdeps[i]->chk == -1)
printf ("0, NULL, ");
- else
+ else
printf ("NELS(dep%d), dep%d, ", opdeps[i]->chk, opdeps[i]->chk);
if (opdeps[i]->reg == -1)
printf ("0, NULL, ");
- else
+ else
printf ("NELS(dep%d), dep%d, ", opdeps[i]->reg, opdeps[i]->reg);
printf ("},\n");
}
{
strtabtotlen += 20;
string_table = (struct string_entry **)
- xrealloc (string_table,
+ xrealloc (string_table,
sizeof (struct string_entry **) * strtabtotlen);
}
res->bits_to_skip = 0;
return res;
}
-
+
\f
static struct disent *
-add_dis_table_ent (which, insn, order, completer_index)
- struct disent *which;
- int insn;
- int order;
- int completer_index;
+add_dis_table_ent (struct disent *which, int insn, int order,
+ ci_t completer_index)
{
int ci = 0;
struct disent *ent;
}
\f
static void
-finish_distable ()
+finish_distable (void)
{
struct disent *ent = disinsntable;
struct disent *prev = ent;
}
\f
static void
-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;
+insert_bit_table_ent (struct bittree *curr_ent, int bit, ia64_insn opcode,
+ ia64_insn mask, int opcodenum, int order,
+ ci_t completer_index)
{
ia64_insn m;
int b;
if (bit == -1)
{
- struct disent *nent = add_dis_table_ent (curr_ent->disent,
+ struct disent *nent = add_dis_table_ent (curr_ent->disent,
opcodenum, order,
completer_index);
curr_ent->disent = nent;
}
\f
static void
-add_dis_entry (first, opcode, mask, opcodenum, ent, completer_index)
- struct bittree *first;
- ia64_insn opcode;
- ia64_insn mask;
- int opcodenum;
- struct completer_entry *ent;
- int completer_index;
+add_dis_entry (struct bittree *first, ia64_insn opcode, ia64_insn mask,
+ int opcodenum, struct completer_entry *ent, ci_t completer_index)
{
- if (completer_index & (1 << 20))
+ if (completer_index & ((ci_t)1 << 32) )
abort ();
while (ent != NULL)
if (ent->is_terminal)
{
- insert_bit_table_ent (bittree, 40, newopcode, mask,
- opcodenum, opcode_count - ent->order - 1,
+ insert_bit_table_ent (bittree, 40, newopcode, mask,
+ opcodenum, opcode_count - ent->order - 1,
(completer_index << 1) | 1);
}
completer_index <<= 1;
\f
/* This optimization pass combines multiple "don't care" nodes. */
static void
-compact_distree (ent)
- struct bittree *ent;
+compact_distree (struct bittree *ent)
{
#define IS_SKIP(ent) \
((ent->bits[2] !=NULL) \
/* Generate the disassembler state machine corresponding to the tree
in ENT. */
static void
-gen_dis_table (ent)
- struct bittree *ent;
+gen_dis_table (struct bittree *ent)
{
int x;
int our_offset = insn_list_len;
if ((needed_bytes + insn_list_len) > tot_insn_list_len)
{
tot_insn_list_len += 256;
- insn_list = (char *) xrealloc (insn_list, tot_insn_list_len);
+ insn_list = (unsigned char *) xrealloc (insn_list, tot_insn_list_len);
}
our_offset = insn_list_len;
insn_list_len += needed_bytes;
else
idest = ent->disent->ournum;
- /* If the destination offset for the if (bit is 1) test is less
+ /* If the destination offset for the if (bit is 1) test is less
than 256 bytes away, we can store it as 8-bits instead of 16;
the instruction has bit 5 set for the 16-bit address, and bit
4 for the 8-bit address. Since we've already allocated 16
/* Store the address of the entry being branched to. */
while (currbits >= 0)
{
- char *byte = insn_list + our_offset + bitsused / 8;
+ unsigned char *byte = insn_list + our_offset + bitsused / 8;
if (idest & (1 << currbits))
*byte |= (1 << (7 - (bitsused % 8)));
{
if (ent->skip_flag)
printf ("%d: skipping %d\n", our_offset, ent->bits_to_skip);
-
+
if (ent->bits[0] != NULL)
printf ("%d: if (0:%d) goto %d\n", our_offset, zero_count + 1,
zero_dest);
int x;
struct disent *cent = disinsntable;
- printf ("static const char dis_table[] = {\n");
+ printf ("static const char dis_table[] = {");
for (x = 0; x < insn_list_len; x++)
{
- if ((x > 0) && ((x % 12) == 0))
- printf ("\n");
+ if (x % 12 == 0)
+ printf ("\n ");
- printf ("0x%02x, ", insn_list[x]);
+ printf (" 0x%02x,", insn_list[x]);
}
printf ("\n};\n\n");
while (ent != NULL)
{
- printf ("{ 0x%x, %d, %d, %d },\n", ent->completer_index,
+ printf ("{ 0x%lx, %d, %d, %d },\n", ( long ) ent->completer_index,
ent->insn, (ent->nexte != NULL ? 1 : 0),
ent->priority);
ent = ent->nexte;
if (ptr->opcode->type != IA64_TYPE_DYN)
add_dis_entry (bittree,
- ptr->opcode->opcode, ptr->opcode->mask,
+ ptr->opcode->opcode, ptr->opcode->mask,
ptr->main_index,
ptr->completers, 1);
}
for (x = 0; x < strtablen; x++)
{
int len;
-
+
if (strlen (string_table[x]->s) > 75)
abort ();
/* If the completer trees ENT1 and ENT2 are equal, return 1. */
static int
-completer_entries_eq (ent1, ent2)
- struct completer_entry *ent1, *ent2;
+completer_entries_eq (struct completer_entry *ent1,
+ struct completer_entry *ent2)
{
while (ent1 != NULL && ent2 != NULL)
{
end = i - 1;
else if (c == 0)
{
- while (i > 0
+ while (i > 0
&& ent->name->num == glist[i - 1]->name->num)
i--;
}
\f
static int
-get_prefix_len (name)
- const char *name;
+get_prefix_len (const char *name)
{
char *c;
}
\f
static void
-compute_completer_bits (ment, ent)
- struct main_entry *ment;
- struct completer_entry *ent;
+compute_completer_bits (struct main_entry *ment, struct completer_entry *ent)
{
while (ent != NULL)
{
while (p != NULL && ! p->is_terminal)
p = p->parent;
-
+
if (p != NULL)
p_bits = p->bits;
else
/* Attach two lists of dependencies to each opcode.
1) all resources which, when already marked in use, conflict with this
- opcode (chks)
+ opcode (chks)
2) all resources which must be marked in use when this opcode is used
(regs). */
static int
-insert_opcode_dependencies (opc, cmp)
- struct ia64_opcode *opc;
- struct completer_entry *cmp ATTRIBUTE_UNUSED;
+insert_opcode_dependencies (struct ia64_opcode *opc,
+ 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. */
int i;
int nregs = 0;
- unsigned short regs[256];
+ unsigned short regs[256];
int nchks = 0;
unsigned short chks[256];
/* Flag insns for which no class matched; there should be none. */
int j;
if (strcmp (opc->name, "cmp.eq.and") == 0
- && strncmp (rs->name, "PR%", 3) == 0
+ && CONST_STRNEQ (rs->name, "PR%")
&& rs->mode == 1)
no_class_found = 99;
if (in_iclass (opc, ics[rs->regs[j]], NULL, NULL, &ic_note))
{
/* We can ignore ic_note 11 for non PR resources. */
- if (ic_note == 11 && strncmp (rs->name, "PR", 2) != 0)
+ if (ic_note == 11 && ! CONST_STRNEQ (rs->name, "PR"))
ic_note = 0;
if (ic_note != 0 && rs->regnotes[j] != 0
if (in_iclass (opc, ics[rs->chks[j]], NULL, NULL, &ic_note))
{
/* We can ignore ic_note 11 for non PR resources. */
- if (ic_note == 11 && strncmp (rs->name, "PR", 2) != 0)
+ if (ic_note == 11 && ! CONST_STRNEQ (rs->name, "PR"))
ic_note = 0;
if (ic_note != 0 && rs->chknotes[j] != 0
if (no_class_found)
warn (_("opcode %s has no class (ops %d %d %d)\n"),
- opc->name,
+ opc->name,
opc->operands[0], opc->operands[1], opc->operands[2]);
return insert_dependencies (nchks, chks, nregs, regs);
}
\f
static void
-insert_completer_entry (opc, tabent, order)
- struct ia64_opcode *opc;
- struct main_entry *tabent;
- int order;
+insert_completer_entry (struct ia64_opcode *opc, struct main_entry *tabent,
+ int order)
{
struct completer_entry **ptr = &tabent->completers;
struct completer_entry *parent = NULL;
}
\f
static void
-print_completer_entry (ent)
- struct completer_entry *ent;
+print_completer_entry (struct completer_entry *ent)
{
int moffset = 0;
ia64_insn mask = ent->mask, bits = ent->bits;
if (bits & 0xffffffff00000000LL)
abort ();
}
-
+
printf (" { 0x%x, 0x%x, %d, %d, %d, %d, %d, %d },\n",
(int)bits,
(int)mask,
}
\f
static void
-print_completer_table ()
+print_completer_table (void)
{
int x;
}
\f
static int
-opcodes_eq (opc1, opc2)
- struct ia64_opcode *opc1;
- struct ia64_opcode *opc2;
+opcodes_eq (struct ia64_opcode *opc1, struct ia64_opcode *opc2)
{
int x;
int plen1, plen2;
- if ((opc1->mask != opc2->mask) || (opc1->type != opc2->type)
+ if ((opc1->mask != opc2->mask) || (opc1->type != opc2->type)
|| (opc1->num_outputs != opc2->num_outputs)
|| (opc1->flags != opc2->flags))
return 0;
}
\f
static void
-add_opcode_entry (opc)
- struct ia64_opcode *opc;
+add_opcode_entry (struct ia64_opcode *opc)
{
struct main_entry **place;
struct string_entry *name;
name = insert_string (prefix);
/* Walk the list of opcode table entries. If it's a new
- instruction, allocate and fill in a new entry. Note
+ instruction, allocate and fill in a new entry. Note
the main table is alphabetical by opcode name. */
while (*place != NULL)
print_main_table (void)
{
struct main_entry *ptr = maintable;
- int index = 0;
+ int tindex = 0;
printf ("static const struct ia64_main_table\nmain_table[] = {\n");
while (ptr != NULL)
ptr->name->num,
ptr->opcode->type,
ptr->opcode->num_outputs);
- fprintf_vma (stdout, ptr->opcode->opcode);
+ opcode_fprintf_vma (stdout, ptr->opcode->opcode);
printf ("ull, 0x");
- fprintf_vma (stdout, ptr->opcode->mask);
+ opcode_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->flags,
ptr->completers->num);
- ptr->main_index = index++;
+ ptr->main_index = tindex++;
ptr = ptr->next;
}
}
\f
static void
-shrink (table)
- struct ia64_opcode *table;
+shrink (struct ia64_opcode *table)
{
int curr_opcode;
for (curr_opcode = 0; table[curr_opcode].name != NULL; curr_opcode++)
- add_opcode_entry (table + curr_opcode);
+ {
+ add_opcode_entry (table + curr_opcode);
+ if (table[curr_opcode].num_outputs == 2
+ && ((table[curr_opcode].operands[0] == IA64_OPND_P1
+ && table[curr_opcode].operands[1] == IA64_OPND_P2)
+ || (table[curr_opcode].operands[0] == IA64_OPND_P2
+ && table[curr_opcode].operands[1] == IA64_OPND_P1)))
+ {
+ struct ia64_opcode *alias = tmalloc(struct ia64_opcode);
+ unsigned i;
+
+ *alias = table[curr_opcode];
+ for (i = 2; i < NELEMS (alias->operands); ++i)
+ alias->operands[i - 1] = alias->operands[i];
+ alias->operands[NELEMS (alias->operands) - 1] = IA64_OPND_NIL;
+ --alias->num_outputs;
+ alias->flags |= PSEUDO;
+ add_opcode_entry (alias);
+ }
+ }
}
\f
/* Program options. */
#define OPTION_SRCDIR 200
-struct option long_options[] =
+struct option long_options[] =
{
{"srcdir", required_argument, NULL, OPTION_SRCDIR},
{"debug", no_argument, NULL, 'd'},
extern int chdir (char *);
char *srcdir = NULL;
int c;
-
+
program_name = *argv;
xmalloc_set_program_name (program_name);
if (optind != argc)
usage (stdout, 1);
- if (srcdir != NULL)
+ if (srcdir != NULL)
if (chdir (srcdir) != 0)
fail (_("unable to change directory to \"%s\", errno = %s\n"),
srcdir, strerror (errno));
collapse_redundant_completers ();
printf ("/* This file is automatically generated by ia64-gen. Do not edit! */\n");
+ printf ("/* Copyright (C) 2007-2020 Free Software Foundation, Inc.\n\
+\n\
+ This file is part of the GNU opcodes library.\n\
+\n\
+ This library is free software; you can redistribute it and/or modify\n\
+ it under the terms of the GNU General Public License as published by\n\
+ the Free Software Foundation; either version 3, or (at your option)\n\
+ any later version.\n\
+\n\
+ It is distributed in the hope that it will be useful, but WITHOUT\n\
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
+ License for more details.\n\
+\n\
+ You should have received a copy of the GNU General Public License\n\
+ along with this program; see the file COPYING. If not, write to the\n\
+ Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA\n\
+ 02110-1301, USA. */\n");
+
print_string_table ();
print_dependency_table ();
print_completer_table ();