#include "bconfig.h"
#include "system.h"
#include "errors.h"
#include "hashtab.h"
#include "mode-classes.def"
#define DEF_MODE_CLASS(M) M
enum mode_class { MODE_CLASSES, MAX_MODE_CLASS };
#undef DEF_MODE_CLASS
#define DEF_MODE_CLASS(M) #M
static const char *const mode_class_names[MAX_MODE_CLASS] =
{
MODE_CLASSES
};
#undef DEF_MODE_CLASS
#undef MODE_CLASSES
#ifdef EXTRA_MODES_FILE
# define HAVE_EXTRA_MODES 1
#else
# define HAVE_EXTRA_MODES 0
# define EXTRA_MODES_FILE ""
#endif
struct mode_data
{
struct mode_data *next;
const char *name;
enum mode_class cl;
unsigned int precision;
unsigned int bytesize;
unsigned int ncomponents;
unsigned int alignment;
const char *format;
struct mode_data *component;
struct mode_data *wider;
struct mode_data *wider_2x;
struct mode_data *contained;
struct mode_data *next_cont;
const char *file;
unsigned int line;
unsigned int counter;
};
static struct mode_data *modes[MAX_MODE_CLASS];
static unsigned int n_modes[MAX_MODE_CLASS];
static struct mode_data *void_mode;
static const struct mode_data blank_mode = {
0, "<unknown>", MAX_MODE_CLASS,
-1U, -1U, -1U, -1U,
0, 0, 0, 0, 0, 0,
"<unknown>", 0, 0
};
static htab_t modes_by_name;
struct mode_adjust
{
struct mode_adjust *next;
struct mode_data *mode;
const char *adjustment;
const char *file;
unsigned int line;
};
static struct mode_adjust *adj_bytesize;
static struct mode_adjust *adj_alignment;
static struct mode_adjust *adj_format;
static enum mode_class
complex_class (enum mode_class c)
{
switch (c)
{
case MODE_INT: return MODE_COMPLEX_INT;
case MODE_FLOAT: return MODE_COMPLEX_FLOAT;
default:
error ("no complex class for class %s", mode_class_names[c]);
return MODE_RANDOM;
}
}
static enum mode_class
vector_class (enum mode_class cl)
{
switch (cl)
{
case MODE_INT: return MODE_VECTOR_INT;
case MODE_FLOAT: return MODE_VECTOR_FLOAT;
default:
error ("no vector class for class %s", mode_class_names[cl]);
return MODE_RANDOM;
}
}
static inline struct mode_data *
find_mode (const char *name)
{
struct mode_data key;
key.name = name;
return (struct mode_data *) htab_find (modes_by_name, &key);
}
static struct mode_data *
new_mode (enum mode_class cl, const char *name,
const char *file, unsigned int line)
{
struct mode_data *m;
static unsigned int count = 0;
m = find_mode (name);
if (m)
{
error ("%s:%d: duplicate definition of mode \"%s\"",
trim_filename (file), line, name);
error ("%s:%d: previous definition here", m->file, m->line);
return m;
}
m = XNEW (struct mode_data);
memcpy (m, &blank_mode, sizeof (struct mode_data));
m->cl = cl;
m->name = name;
if (file)
m->file = trim_filename (file);
m->line = line;
m->counter = count++;
m->next = modes[cl];
modes[cl] = m;
n_modes[cl]++;
*htab_find_slot (modes_by_name, m, INSERT) = m;
return m;
}
static hashval_t
hash_mode (const void *p)
{
const struct mode_data *m = (const struct mode_data *)p;
return htab_hash_string (m->name);
}
static int
eq_mode (const void *p, const void *q)
{
const struct mode_data *a = (const struct mode_data *)p;
const struct mode_data *b = (const struct mode_data *)q;
return !strcmp (a->name, b->name);
}
#define for_all_modes(C, M) \
for (C = 0; C < MAX_MODE_CLASS; C++) \
for (M = modes[C]; M; M = M->next)
static void ATTRIBUTE_UNUSED
new_adjust (const char *name,
struct mode_adjust **category, const char *catname,
const char *adjustment,
enum mode_class required_class,
const char *file, unsigned int line)
{
struct mode_data *mode = find_mode (name);
struct mode_adjust *a;
file = trim_filename (file);
if (!mode)
{
error ("%s:%d: no mode \"%s\"", file, line, name);
return;
}
if (required_class != MODE_RANDOM && mode->cl != required_class)
{
error ("%s:%d: mode \"%s\" is not class %s",
file, line, name, mode_class_names[required_class] + 5);
return;
}
for (a = *category; a; a = a->next)
if (a->mode == mode)
{
error ("%s:%d: mode \"%s\" already has a %s adjustment",
file, line, name, catname);
error ("%s:%d: previous adjustment here", a->file, a->line);
return;
}
a = XNEW (struct mode_adjust);
a->mode = mode;
a->adjustment = adjustment;
a->file = file;
a->line = line;
a->next = *category;
*category = a;
}
enum requirement { SET, UNSET, OPTIONAL };
#define validate_field_(mname, fname, req, val, unset, file, line) do { \
switch (req) \
{ \
case SET: \
if (val == unset) \
error ("%s:%d: (%s) field %s must be set", \
file, line, mname, fname); \
break; \
case UNSET: \
if (val != unset) \
error ("%s:%d: (%s) field %s must not be set", \
file, line, mname, fname); \
case OPTIONAL: \
break; \
} \
} while (0)
#define validate_field(M, F) \
validate_field_(M->name, #F, r_##F, M->F, blank_mode.F, M->file, M->line)
static void
validate_mode (struct mode_data *m,
enum requirement r_precision,
enum requirement r_bytesize,
enum requirement r_component,
enum requirement r_ncomponents,
enum requirement r_format)
{
validate_field (m, precision);
validate_field (m, bytesize);
validate_field (m, component);
validate_field (m, ncomponents);
validate_field (m, format);
}
#undef validate_field
#undef validate_field_
static void
complete_mode (struct mode_data *m)
{
unsigned int alignment;
if (!m->name)
{
error ("%s:%d: mode with no name", m->file, m->line);
return;
}
if (m->cl == MAX_MODE_CLASS)
{
error ("%s:%d: %smode has no mode class", m->file, m->line, m->name);
return;
}
switch (m->cl)
{
case MODE_RANDOM:
if (!strcmp (m->name, "VOID"))
void_mode = m;
validate_mode (m, UNSET, UNSET, UNSET, UNSET, UNSET);
m->precision = 0;
m->bytesize = 0;
m->ncomponents = 0;
m->component = 0;
break;
case MODE_CC:
validate_mode (m, UNSET, UNSET, UNSET, UNSET, UNSET);
m->bytesize = 4;
m->ncomponents = 1;
m->component = 0;
break;
case MODE_INT:
case MODE_FLOAT:
case MODE_DECIMAL_FLOAT:
validate_mode (m, OPTIONAL, SET, UNSET, UNSET,
m->cl != MODE_INT ? SET : UNSET);
m->ncomponents = 1;
m->component = 0;
break;
case MODE_PARTIAL_INT:
validate_mode (m, OPTIONAL, UNSET, SET, UNSET, UNSET);
m->bytesize = m->component->bytesize;
m->ncomponents = 1;
m->component = 0;
break;
case MODE_COMPLEX_INT:
case MODE_COMPLEX_FLOAT:
validate_mode (m, UNSET, UNSET, SET, UNSET, UNSET);
m->ncomponents = 2;
if (m->component->precision != (unsigned int)-1)
m->precision = 2 * m->component->precision;
m->bytesize = 2 * m->component->bytesize;
break;
case MODE_VECTOR_INT:
case MODE_VECTOR_FLOAT:
validate_mode (m, UNSET, UNSET, SET, SET, UNSET);
if (m->component->precision != (unsigned int)-1)
m->precision = m->ncomponents * m->component->precision;
m->bytesize = m->ncomponents * m->component->bytesize;
break;
default:
gcc_unreachable ();
}
if (m->cl == MODE_COMPLEX_INT || m->cl == MODE_COMPLEX_FLOAT)
alignment = m->component->bytesize;
else
alignment = m->bytesize;
m->alignment = alignment & (~alignment + 1);
if (m->component)
{
m->next_cont = m->component->contained;
m->component->contained = m;
}
}
static void
complete_all_modes (void)
{
struct mode_data *m;
int cl;
for_all_modes (cl, m)
complete_mode (m);
}
#define COMPLEX_MODES(C) make_complex_modes(MODE_##C, __FILE__, __LINE__)
static void
make_complex_modes (enum mode_class cl,
const char *file, unsigned int line)
{
struct mode_data *m;
struct mode_data *c;
char buf[8];
enum mode_class cclass = complex_class (cl);
if (cclass == MODE_RANDOM)
return;
for (m = modes[cl]; m; m = m->next)
{
if (m->precision == 1)
continue;
if (strlen (m->name) >= sizeof buf)
{
error ("%s:%d:mode name \"%s\" is too long",
m->file, m->line, m->name);
continue;
}
if (cl == MODE_FLOAT)
{
char *p, *q = 0;
strncpy (buf, m->name, sizeof buf);
p = strchr (buf, 'F');
if (p == 0)
q = strchr (buf, 'D');
if (p == 0 && q == 0)
{
error ("%s:%d: float mode \"%s\" has no 'F' or 'D'",
m->file, m->line, m->name);
continue;
}
if (p != 0)
*p = 'C';
else
snprintf (buf, sizeof buf, "C%s", m->name);
}
else
snprintf (buf, sizeof buf, "C%s", m->name);
c = new_mode (cclass, xstrdup (buf), file, line);
c->component = m;
}
}
#define VECTOR_MODES(C, W) make_vector_modes(MODE_##C, W, __FILE__, __LINE__)
static void ATTRIBUTE_UNUSED
make_vector_modes (enum mode_class cl, unsigned int width,
const char *file, unsigned int line)
{
struct mode_data *m;
struct mode_data *v;
char buf[8];
unsigned int ncomponents;
enum mode_class vclass = vector_class (cl);
if (vclass == MODE_RANDOM)
return;
for (m = modes[cl]; m; m = m->next)
{
ncomponents = width / m->bytesize;
if (ncomponents < 2)
continue;
if (width % m->bytesize)
continue;
if (cl == MODE_FLOAT && m->bytesize == 1)
continue;
if (cl == MODE_INT && m->precision == 1)
continue;
if ((size_t)snprintf (buf, sizeof buf, "V%u%s", ncomponents, m->name)
>= sizeof buf)
{
error ("%s:%d: mode name \"%s\" is too long",
m->file, m->line, m->name);
continue;
}
v = new_mode (vclass, xstrdup (buf), file, line);
v->component = m;
v->ncomponents = ncomponents;
}
}
#define _SPECIAL_MODE(C, N) make_special_mode(MODE_##C, #N, __FILE__, __LINE__)
#define RANDOM_MODE(N) _SPECIAL_MODE (RANDOM, N)
#define CC_MODE(N) _SPECIAL_MODE (CC, N)
static void
make_special_mode (enum mode_class cl, const char *name,
const char *file, unsigned int line)
{
new_mode (cl, name, file, line);
}
#define INT_MODE(N, Y) FRACTIONAL_INT_MODE (N, -1U, Y)
#define FRACTIONAL_INT_MODE(N, B, Y) \
make_int_mode (#N, B, Y, __FILE__, __LINE__)
static void
make_int_mode (const char *name,
unsigned int precision, unsigned int bytesize,
const char *file, unsigned int line)
{
struct mode_data *m = new_mode (MODE_INT, name, file, line);
m->bytesize = bytesize;
m->precision = precision;
}
#define FLOAT_MODE(N, Y, F) FRACTIONAL_FLOAT_MODE (N, -1U, Y, F)
#define FRACTIONAL_FLOAT_MODE(N, B, Y, F) \
make_float_mode (#N, B, Y, #F, __FILE__, __LINE__)
static void
make_float_mode (const char *name,
unsigned int precision, unsigned int bytesize,
const char *format,
const char *file, unsigned int line)
{
struct mode_data *m = new_mode (MODE_FLOAT, name, file, line);
m->bytesize = bytesize;
m->precision = precision;
m->format = format;
}
#define DECIMAL_FLOAT_MODE(N, Y, F) \
FRACTIONAL_DECIMAL_FLOAT_MODE (N, -1U, Y, F)
#define FRACTIONAL_DECIMAL_FLOAT_MODE(N, B, Y, F) \
make_decimal_float_mode (#N, B, Y, #F, __FILE__, __LINE__)
static void
make_decimal_float_mode (const char *name,
unsigned int precision, unsigned int bytesize,
const char *format,
const char *file, unsigned int line)
{
struct mode_data *m = new_mode (MODE_DECIMAL_FLOAT, name, file, line);
m->bytesize = bytesize;
m->precision = precision;
m->format = format;
}
#define RESET_FLOAT_FORMAT(N, F) \
reset_float_format (#N, #F, __FILE__, __LINE__)
static void ATTRIBUTE_UNUSED
reset_float_format (const char *name, const char *format,
const char *file, unsigned int line)
{
struct mode_data *m = find_mode (name);
if (!m)
{
error ("%s:%d: no mode \"%s\"", file, line, name);
return;
}
if (m->cl != MODE_FLOAT && m->cl != MODE_DECIMAL_FLOAT)
{
error ("%s:%d: mode \"%s\" is not a FLOAT class", file, line, name);
return;
}
m->format = format;
}
#define PARTIAL_INT_MODE(M) \
make_partial_integer_mode (#M, "P" #M, -1U, __FILE__, __LINE__)
static void ATTRIBUTE_UNUSED
make_partial_integer_mode (const char *base, const char *name,
unsigned int precision,
const char *file, unsigned int line)
{
struct mode_data *m;
struct mode_data *component = find_mode (base);
if (!component)
{
error ("%s:%d: no mode \"%s\"", file, line, name);
return;
}
if (component->cl != MODE_INT)
{
error ("%s:%d: mode \"%s\" is not class INT", file, line, name);
return;
}
m = new_mode (MODE_PARTIAL_INT, name, file, line);
m->precision = precision;
m->component = component;
}
#define VECTOR_MODE(C, M, N) \
make_vector_mode (MODE_##C, #M, N, __FILE__, __LINE__);
static void ATTRIBUTE_UNUSED
make_vector_mode (enum mode_class bclass,
const char *base,
unsigned int ncomponents,
const char *file, unsigned int line)
{
struct mode_data *v;
enum mode_class vclass = vector_class (bclass);
struct mode_data *component = find_mode (base);
char namebuf[8];
if (vclass == MODE_RANDOM)
return;
if (component == 0)
{
error ("%s:%d: no mode \"%s\"", file, line, base);
return;
}
if (component->cl != bclass
&& (component->cl != MODE_PARTIAL_INT
|| bclass != MODE_INT))
{
error ("%s:%d: mode \"%s\" is not class %s",
file, line, base, mode_class_names[bclass] + 5);
return;
}
if ((size_t)snprintf (namebuf, sizeof namebuf, "V%u%s",
ncomponents, base) >= sizeof namebuf)
{
error ("%s:%d: mode name \"%s\" is too long",
file, line, base);
return;
}
v = new_mode (vclass, xstrdup (namebuf), file, line);
v->ncomponents = ncomponents;
v->component = component;
}
#define _ADD_ADJUST(A, M, X, C) \
new_adjust (#M, &adj_##A, #A, #X, MODE_##C, __FILE__, __LINE__)
#define ADJUST_BYTESIZE(M, X) _ADD_ADJUST(bytesize, M, X, RANDOM)
#define ADJUST_ALIGNMENT(M, X) _ADD_ADJUST(alignment, M, X, RANDOM)
#define ADJUST_FLOAT_FORMAT(M, X) _ADD_ADJUST(format, M, X, FLOAT)
static void
create_modes (void)
{
#include "machmode.def"
}
static int
cmp_modes (const void *a, const void *b)
{
struct mode_data *m = *(struct mode_data **)a;
struct mode_data *n = *(struct mode_data **)b;
if (m->bytesize > n->bytesize)
return 1;
else if (m->bytesize < n->bytesize)
return -1;
if (m->precision > n->precision)
return 1;
else if (m->precision < n->precision)
return -1;
if (!m->component && !n->component)
{
if (m->counter < n->counter)
return -1;
else
return 1;
}
if (m->component->bytesize > n->component->bytesize)
return 1;
else if (m->component->bytesize < n->component->bytesize)
return -1;
if (m->component->precision > n->component->precision)
return 1;
else if (m->component->precision < n->component->precision)
return -1;
if (m->counter < n->counter)
return -1;
else
return 1;
}
static void
calc_wider_mode (void)
{
int c;
struct mode_data *m;
struct mode_data **sortbuf;
unsigned int max_n_modes = 0;
unsigned int i, j;
for (c = 0; c < MAX_MODE_CLASS; c++)
max_n_modes = MAX (max_n_modes, n_modes[c]);
sortbuf = (struct mode_data **) alloca ((max_n_modes + 1) * sizeof (struct mode_data *));
for (c = 0; c < MAX_MODE_CLASS; c++)
{
if (c == MODE_RANDOM || c == MODE_CC)
{
struct mode_data *prev, *next;
for (prev = 0, m = modes[c]; m; m = next)
{
m->wider = void_mode;
m->wider_2x = void_mode;
next = m->next;
m->next = prev;
prev = m;
}
modes[c] = prev;
}
else
{
if (!modes[c])
continue;
for (i = 0, m = modes[c]; m; i++, m = m->next)
sortbuf[i] = m;
qsort (sortbuf, i, sizeof (struct mode_data *), cmp_modes);
sortbuf[i] = 0;
for (j = 0; j < i; j++)
sortbuf[j]->next = sortbuf[j]->wider = sortbuf[j + 1];
modes[c] = sortbuf[0];
}
}
}
#define tagged_printf(FMT, ARG, TAG) do { \
int count_; \
printf (" " FMT ",%n", ARG, &count_); \
printf ("%*s/* %s */\n", 27 - count_, "", TAG); \
} while (0)
#define print_decl(TYPE, NAME, ASIZE) \
puts ("\nconst " TYPE " " NAME "[" ASIZE "] =\n{");
#define print_maybe_const_decl(TYPE, NAME, ASIZE, CATEGORY) \
printf ("\n" TYPE " " NAME "[" ASIZE "] = \n{\n", \
adj_##CATEGORY ? "" : "const ")
#define print_closer() puts ("};")
static void
emit_insn_modes_h (void)
{
int c;
struct mode_data *m, *first, *last;
printf ("/* Generated automatically from machmode.def%s%s\n",
HAVE_EXTRA_MODES ? " and " : "",
EXTRA_MODES_FILE);
puts ("\
by genmodes. */\n\
\n\
#ifndef GCC_INSN_MODES_H\n\
#define GCC_INSN_MODES_H\n\
\n\
enum machine_mode\n{");
for (c = 0; c < MAX_MODE_CLASS; c++)
for (m = modes[c]; m; m = m->next)
{
int count_;
printf (" %smode,%n", m->name, &count_);
printf ("%*s/* %s:%d */\n", 27 - count_, "",
trim_filename (m->file), m->line);
}
puts (" MAX_MACHINE_MODE,\n");
for (c = 0; c < MAX_MODE_CLASS; c++)
{
first = modes[c];
last = 0;
for (m = first; m; last = m, m = m->next)
;
if (first && first->precision == 1)
first = first->next;
if (first && last)
printf (" MIN_%s = %smode,\n MAX_%s = %smode,\n\n",
mode_class_names[c], first->name,
mode_class_names[c], last->name);
else
printf (" MIN_%s = %smode,\n MAX_%s = %smode,\n\n",
mode_class_names[c], void_mode->name,
mode_class_names[c], void_mode->name);
}
puts ("\
NUM_MACHINE_MODES = MAX_MACHINE_MODE\n\
};\n");
printf ("#define CONST_MODE_SIZE%s\n", adj_bytesize ? "" : " const");
printf ("#define CONST_MODE_BASE_ALIGN%s\n", adj_alignment ? "" : " const");
#if 0
printf ("#define CONST_REAL_FORMAT_FOR_MODE%s\n", adj_format ? "" :" const");
#endif
puts ("\
\n\
#endif /* insn-modes.h */");
}
static void
emit_insn_modes_c_header (void)
{
printf ("/* Generated automatically from machmode.def%s%s\n",
HAVE_EXTRA_MODES ? " and " : "",
EXTRA_MODES_FILE);
puts ("\
by genmodes. */\n\
\n\
#include \"config.h\"\n\
#include \"system.h\"\n\
#include \"coretypes.h\"\n\
#include \"tm.h\"\n\
#include \"machmode.h\"\n\
#include \"real.h\"");
}
static void
emit_min_insn_modes_c_header (void)
{
printf ("/* Generated automatically from machmode.def%s%s\n",
HAVE_EXTRA_MODES ? " and " : "",
EXTRA_MODES_FILE);
puts ("\
by genmodes. */\n\
\n\
#include \"bconfig.h\"\n\
#include \"system.h\"\n\
#include \"machmode.h\"");
}
static void
emit_mode_name (void)
{
int c;
struct mode_data *m;
print_decl ("char *const", "mode_name", "NUM_MACHINE_MODES");
for_all_modes (c, m)
printf (" \"%s\",\n", m->name);
print_closer ();
}
static void
emit_mode_class (void)
{
int c;
struct mode_data *m;
print_decl ("unsigned char", "mode_class", "NUM_MACHINE_MODES");
for_all_modes (c, m)
tagged_printf ("%s", mode_class_names[m->cl], m->name);
print_closer ();
}
static void
emit_mode_precision (void)
{
int c;
struct mode_data *m;
print_decl ("unsigned short", "mode_precision", "NUM_MACHINE_MODES");
for_all_modes (c, m)
if (m->precision != (unsigned int)-1)
tagged_printf ("%u", m->precision, m->name);
else
tagged_printf ("%u*BITS_PER_UNIT", m->bytesize, m->name);
print_closer ();
}
static void
emit_mode_size (void)
{
int c;
struct mode_data *m;
print_maybe_const_decl ("%sunsigned char", "mode_size",
"NUM_MACHINE_MODES", bytesize);
for_all_modes (c, m)
tagged_printf ("%u", m->bytesize, m->name);
print_closer ();
}
static void
emit_mode_nunits (void)
{
int c;
struct mode_data *m;
print_decl ("unsigned char", "mode_nunits", "NUM_MACHINE_MODES");
for_all_modes (c, m)
tagged_printf ("%u", m->ncomponents, m->name);
print_closer ();
}
static void
emit_mode_wider (void)
{
int c;
struct mode_data *m;
print_decl ("unsigned char", "mode_wider", "NUM_MACHINE_MODES");
for_all_modes (c, m)
tagged_printf ("%smode",
m->wider ? m->wider->name : void_mode->name,
m->name);
print_closer ();
print_decl ("unsigned char", "mode_2xwider", "NUM_MACHINE_MODES");
for_all_modes (c, m)
{
struct mode_data * m2;
for (m2 = m;
m2 && m2 != void_mode;
m2 = m2->wider)
{
if (m2->bytesize < 2 * m->bytesize)
continue;
if (m->precision != (unsigned int) -1)
{
if (m2->precision != 2 * m->precision)
continue;
}
else
{
if (m2->precision != (unsigned int) -1)
continue;
}
break;
}
if (m2 == void_mode)
m2 = 0;
tagged_printf ("%smode",
m2 ? m2->name : void_mode->name,
m->name);
}
print_closer ();
}
static void
emit_mode_mask (void)
{
int c;
struct mode_data *m;
print_decl ("unsigned HOST_WIDE_INT", "mode_mask_array",
"NUM_MACHINE_MODES");
puts ("\
#define MODE_MASK(m) \\\n\
((m) >= HOST_BITS_PER_WIDE_INT) \\\n\
? ~(unsigned HOST_WIDE_INT) 0 \\\n\
: ((unsigned HOST_WIDE_INT) 1 << (m)) - 1\n");
for_all_modes (c, m)
if (m->precision != (unsigned int)-1)
tagged_printf ("MODE_MASK (%u)", m->precision, m->name);
else
tagged_printf ("MODE_MASK (%u*BITS_PER_UNIT)", m->bytesize, m->name);
puts ("#undef MODE_MASK");
print_closer ();
}
static void
emit_mode_inner (void)
{
int c;
struct mode_data *m;
print_decl ("unsigned char", "mode_inner", "NUM_MACHINE_MODES");
for_all_modes (c, m)
tagged_printf ("%smode",
m->component ? m->component->name : void_mode->name,
m->name);
print_closer ();
}
static void
emit_mode_base_align (void)
{
int c;
struct mode_data *m;
print_maybe_const_decl ("%sunsigned char",
"mode_base_align", "NUM_MACHINE_MODES",
alignment);
for_all_modes (c, m)
tagged_printf ("%u", m->alignment, m->name);
print_closer ();
}
static void
emit_class_narrowest_mode (void)
{
int c;
print_decl ("unsigned char", "class_narrowest_mode", "MAX_MODE_CLASS");
for (c = 0; c < MAX_MODE_CLASS; c++)
tagged_printf ("MIN_%s", mode_class_names[c],
modes[c]
? (modes[c]->precision != 1
? modes[c]->name
: (modes[c]->next
? modes[c]->next->name
: void_mode->name))
: void_mode->name);
print_closer ();
}
static void
emit_real_format_for_mode (void)
{
struct mode_data *m;
#if 0
print_maybe_const_decl ("const struct real_format *%s",
"real_format_for_mode",
"MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1",
format);
#else
print_decl ("struct real_format *\n", "real_format_for_mode",
"MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1 "
"+ MAX_MODE_DECIMAL_FLOAT - MIN_MODE_DECIMAL_FLOAT + 1");
#endif
for (m = modes[MODE_FLOAT]; m; m = m->next)
if (!strcmp (m->format, "0"))
tagged_printf ("%s", m->format, m->name);
else
tagged_printf ("&%s", m->format, m->name);
for (m = modes[MODE_DECIMAL_FLOAT]; m; m = m->next)
if (!strcmp (m->format, "0"))
tagged_printf ("%s", m->format, m->name);
else
tagged_printf ("&%s", m->format, m->name);
print_closer ();
}
static void
emit_mode_adjustments (void)
{
struct mode_adjust *a;
struct mode_data *m;
puts ("\
\nvoid\
\ninit_adjust_machine_modes (void)\
\n{\
\n size_t s ATTRIBUTE_UNUSED;");
for (a = adj_bytesize; a; a = a->next)
{
printf ("\n /* %s:%d */\n s = %s;\n",
a->file, a->line, a->adjustment);
printf (" mode_size[%smode] = s;\n", a->mode->name);
printf (" mode_base_align[%smode] = s & (~s + 1);\n",
a->mode->name);
for (m = a->mode->contained; m; m = m->next_cont)
{
switch (m->cl)
{
case MODE_COMPLEX_INT:
case MODE_COMPLEX_FLOAT:
printf (" mode_size[%smode] = 2*s;\n", m->name);
printf (" mode_base_align[%smode] = s & (~s + 1);\n",
m->name);
break;
case MODE_VECTOR_INT:
case MODE_VECTOR_FLOAT:
printf (" mode_size[%smode] = %d*s;\n",
m->name, m->ncomponents);
printf (" mode_base_align[%smode] = (%d*s) & (~(%d*s)+1);\n",
m->name, m->ncomponents, m->ncomponents);
break;
default:
internal_error (
"mode %s is neither vector nor complex but contains %s",
m->name, a->mode->name);
}
}
}
for (a = adj_alignment; a; a = a->next)
{
printf ("\n /* %s:%d */\n s = %s;\n",
a->file, a->line, a->adjustment);
printf (" mode_base_align[%smode] = s;\n", a->mode->name);
for (m = a->mode->contained; m; m = m->next_cont)
{
switch (m->cl)
{
case MODE_COMPLEX_INT:
case MODE_COMPLEX_FLOAT:
printf (" mode_base_align[%smode] = s;\n", m->name);
break;
case MODE_VECTOR_INT:
case MODE_VECTOR_FLOAT:
printf (" mode_base_align[%smode] = %d*s;\n",
m->name, m->ncomponents);
break;
default:
internal_error (
"mode %s is neither vector nor complex but contains %s",
m->name, a->mode->name);
}
}
}
for (a = adj_format; a; a = a->next)
printf ("\n /* %s:%d */\n REAL_MODE_FORMAT (%smode) = %s;\n",
a->file, a->line, a->mode->name, a->adjustment);
puts ("}");
}
static void
emit_insn_modes_c (void)
{
emit_insn_modes_c_header ();
emit_mode_name ();
emit_mode_class ();
emit_mode_precision ();
emit_mode_size ();
emit_mode_nunits ();
emit_mode_wider ();
emit_mode_mask ();
emit_mode_inner ();
emit_mode_base_align ();
emit_class_narrowest_mode ();
emit_real_format_for_mode ();
emit_mode_adjustments ();
}
static void
emit_min_insn_modes_c (void)
{
emit_min_insn_modes_c_header ();
emit_mode_name ();
emit_mode_class ();
emit_mode_wider ();
emit_class_narrowest_mode ();
}
int
main(int argc, char **argv)
{
bool gen_header = false, gen_min = false;
progname = argv[0];
if (argc == 1)
;
else if (argc == 2 && !strcmp (argv[1], "-h"))
gen_header = true;
else if (argc == 2 && !strcmp (argv[1], "-m"))
gen_min = true;
else
{
error ("usage: %s [-h|-m] > file", progname);
return FATAL_EXIT_CODE;
}
modes_by_name = htab_create_alloc (64, hash_mode, eq_mode, 0, xcalloc, free);
create_modes ();
complete_all_modes ();
if (have_error)
return FATAL_EXIT_CODE;
calc_wider_mode ();
if (gen_header)
emit_insn_modes_h ();
else if (gen_min)
emit_min_insn_modes_c ();
else
emit_insn_modes_c ();
if (fflush (stdout) || fclose (stdout))
return FATAL_EXIT_CODE;
return SUCCESS_EXIT_CODE;
}