1132718Skan/* Generate the machine mode enumeration and associated tables.
2169689Skan   Copyright (C) 2003, 2004
3132718Skan   Free Software Foundation, Inc.
4132718Skan
5132718SkanThis file is part of GCC.
6132718Skan
7132718SkanGCC is free software; you can redistribute it and/or modify it under
8132718Skanthe terms of the GNU General Public License as published by the Free
9132718SkanSoftware Foundation; either version 2, or (at your option) any later
10132718Skanversion.
11132718Skan
12132718SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY
13132718SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or
14132718SkanFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15132718Skanfor more details.
16132718Skan
17132718SkanYou should have received a copy of the GNU General Public License
18132718Skanalong with GCC; see the file COPYING.  If not, write to the Free
19169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20169689Skan02110-1301, USA.  */
21132718Skan
22132718Skan#include "bconfig.h"
23132718Skan#include "system.h"
24132718Skan#include "errors.h"
25132718Skan#include "hashtab.h"
26132718Skan
27132718Skan/* enum mode_class is normally defined by machmode.h but we can't
28132718Skan   include that header here.  */
29132718Skan#include "mode-classes.def"
30132718Skan
31132718Skan#define DEF_MODE_CLASS(M) M
32132718Skanenum mode_class { MODE_CLASSES, MAX_MODE_CLASS };
33132718Skan#undef DEF_MODE_CLASS
34132718Skan
35132718Skan/* Text names of mode classes, for output.  */
36132718Skan#define DEF_MODE_CLASS(M) #M
37132718Skanstatic const char *const mode_class_names[MAX_MODE_CLASS] =
38132718Skan{
39132718Skan  MODE_CLASSES
40132718Skan};
41132718Skan#undef DEF_MODE_CLASS
42132718Skan#undef MODE_CLASSES
43132718Skan
44132718Skan#ifdef EXTRA_MODES_FILE
45132718Skan# define HAVE_EXTRA_MODES 1
46132718Skan#else
47132718Skan# define HAVE_EXTRA_MODES 0
48132718Skan# define EXTRA_MODES_FILE ""
49132718Skan#endif
50132718Skan
51132718Skan/* Data structure for building up what we know about a mode.
52132718Skan   They're clustered by mode class.  */
53132718Skanstruct mode_data
54132718Skan{
55132718Skan  struct mode_data *next;	/* next this class - arbitrary order */
56132718Skan
57132718Skan  const char *name;		/* printable mode name -- SI, not SImode */
58169689Skan  enum mode_class cl;		/* this mode class */
59132718Skan  unsigned int precision;	/* size in bits, equiv to TYPE_PRECISION */
60132718Skan  unsigned int bytesize;	/* storage size in addressable units */
61132718Skan  unsigned int ncomponents;	/* number of subunits */
62132718Skan  unsigned int alignment;	/* mode alignment */
63169689Skan  const char *format;		/* floating point format - float modes only */
64132718Skan
65132718Skan  struct mode_data *component;	/* mode of components */
66132718Skan  struct mode_data *wider;	/* next wider mode */
67169689Skan  struct mode_data *wider_2x;	/* 2x wider mode */
68132718Skan
69132718Skan  struct mode_data *contained;  /* Pointer to list of modes that have
70132718Skan				   this mode as a component.  */
71132718Skan  struct mode_data *next_cont;  /* Next mode in that list.  */
72132718Skan
73132718Skan  const char *file;		/* file and line of definition, */
74132718Skan  unsigned int line;		/* for error reporting */
75169689Skan  unsigned int counter;		/* Rank ordering of modes */
76132718Skan};
77132718Skan
78132718Skanstatic struct mode_data *modes[MAX_MODE_CLASS];
79132718Skanstatic unsigned int n_modes[MAX_MODE_CLASS];
80132718Skanstatic struct mode_data *void_mode;
81132718Skan
82132718Skanstatic const struct mode_data blank_mode = {
83132718Skan  0, "<unknown>", MAX_MODE_CLASS,
84169689Skan  -1U, -1U, -1U, -1U,
85169689Skan  0, 0, 0, 0, 0, 0,
86169689Skan  "<unknown>", 0, 0
87132718Skan};
88132718Skan
89132718Skanstatic htab_t modes_by_name;
90132718Skan
91132718Skan/* Data structure for recording target-specified runtime adjustments
92132718Skan   to a particular mode.  We support varying the byte size, the
93132718Skan   alignment, and the floating point format.  */
94132718Skanstruct mode_adjust
95132718Skan{
96132718Skan  struct mode_adjust *next;
97132718Skan  struct mode_data *mode;
98132718Skan  const char *adjustment;
99132718Skan
100132718Skan  const char *file;
101132718Skan  unsigned int line;
102132718Skan};
103132718Skan
104132718Skanstatic struct mode_adjust *adj_bytesize;
105132718Skanstatic struct mode_adjust *adj_alignment;
106132718Skanstatic struct mode_adjust *adj_format;
107132718Skan
108132718Skan/* Mode class operations.  */
109132718Skanstatic enum mode_class
110169689Skancomplex_class (enum mode_class c)
111132718Skan{
112169689Skan  switch (c)
113132718Skan    {
114132718Skan    case MODE_INT: return MODE_COMPLEX_INT;
115132718Skan    case MODE_FLOAT: return MODE_COMPLEX_FLOAT;
116132718Skan    default:
117169689Skan      error ("no complex class for class %s", mode_class_names[c]);
118132718Skan      return MODE_RANDOM;
119132718Skan    }
120132718Skan}
121132718Skan
122132718Skanstatic enum mode_class
123169689Skanvector_class (enum mode_class cl)
124132718Skan{
125169689Skan  switch (cl)
126132718Skan    {
127132718Skan    case MODE_INT: return MODE_VECTOR_INT;
128132718Skan    case MODE_FLOAT: return MODE_VECTOR_FLOAT;
129132718Skan    default:
130169689Skan      error ("no vector class for class %s", mode_class_names[cl]);
131132718Skan      return MODE_RANDOM;
132132718Skan    }
133132718Skan}
134132718Skan
135132718Skan/* Utility routines.  */
136132718Skanstatic inline struct mode_data *
137132718Skanfind_mode (const char *name)
138132718Skan{
139132718Skan  struct mode_data key;
140132718Skan
141132718Skan  key.name = name;
142169689Skan  return (struct mode_data *) htab_find (modes_by_name, &key);
143132718Skan}
144132718Skan
145132718Skanstatic struct mode_data *
146169689Skannew_mode (enum mode_class cl, const char *name,
147132718Skan	  const char *file, unsigned int line)
148132718Skan{
149132718Skan  struct mode_data *m;
150169689Skan  static unsigned int count = 0;
151132718Skan
152132718Skan  m = find_mode (name);
153132718Skan  if (m)
154132718Skan    {
155132718Skan      error ("%s:%d: duplicate definition of mode \"%s\"",
156132718Skan	     trim_filename (file), line, name);
157132718Skan      error ("%s:%d: previous definition here", m->file, m->line);
158132718Skan      return m;
159132718Skan    }
160132718Skan
161169689Skan  m = XNEW (struct mode_data);
162132718Skan  memcpy (m, &blank_mode, sizeof (struct mode_data));
163169689Skan  m->cl = cl;
164132718Skan  m->name = name;
165132718Skan  if (file)
166132718Skan    m->file = trim_filename (file);
167132718Skan  m->line = line;
168169689Skan  m->counter = count++;
169132718Skan
170169689Skan  m->next = modes[cl];
171169689Skan  modes[cl] = m;
172169689Skan  n_modes[cl]++;
173132718Skan
174132718Skan  *htab_find_slot (modes_by_name, m, INSERT) = m;
175132718Skan
176132718Skan  return m;
177132718Skan}
178132718Skan
179132718Skanstatic hashval_t
180132718Skanhash_mode (const void *p)
181132718Skan{
182132718Skan  const struct mode_data *m = (const struct mode_data *)p;
183132718Skan  return htab_hash_string (m->name);
184132718Skan}
185132718Skan
186132718Skanstatic int
187132718Skaneq_mode (const void *p, const void *q)
188132718Skan{
189132718Skan  const struct mode_data *a = (const struct mode_data *)p;
190132718Skan  const struct mode_data *b = (const struct mode_data *)q;
191132718Skan
192132718Skan  return !strcmp (a->name, b->name);
193132718Skan}
194132718Skan
195132718Skan#define for_all_modes(C, M)			\
196132718Skan  for (C = 0; C < MAX_MODE_CLASS; C++)		\
197132718Skan    for (M = modes[C]; M; M = M->next)
198132718Skan
199132718Skanstatic void ATTRIBUTE_UNUSED
200132718Skannew_adjust (const char *name,
201132718Skan	    struct mode_adjust **category, const char *catname,
202132718Skan	    const char *adjustment,
203132718Skan	    enum mode_class required_class,
204132718Skan	    const char *file, unsigned int line)
205132718Skan{
206132718Skan  struct mode_data *mode = find_mode (name);
207132718Skan  struct mode_adjust *a;
208132718Skan
209132718Skan  file = trim_filename (file);
210132718Skan
211132718Skan  if (!mode)
212132718Skan    {
213132718Skan      error ("%s:%d: no mode \"%s\"", file, line, name);
214132718Skan      return;
215132718Skan    }
216132718Skan
217169689Skan  if (required_class != MODE_RANDOM && mode->cl != required_class)
218132718Skan    {
219132718Skan      error ("%s:%d: mode \"%s\" is not class %s",
220132718Skan	     file, line, name, mode_class_names[required_class] + 5);
221132718Skan      return;
222132718Skan    }
223132718Skan
224132718Skan  for (a = *category; a; a = a->next)
225132718Skan    if (a->mode == mode)
226132718Skan      {
227132718Skan	error ("%s:%d: mode \"%s\" already has a %s adjustment",
228132718Skan	       file, line, name, catname);
229132718Skan	error ("%s:%d: previous adjustment here", a->file, a->line);
230132718Skan	return;
231132718Skan      }
232132718Skan
233169689Skan  a = XNEW (struct mode_adjust);
234132718Skan  a->mode = mode;
235132718Skan  a->adjustment = adjustment;
236132718Skan  a->file = file;
237132718Skan  a->line = line;
238132718Skan
239132718Skan  a->next = *category;
240132718Skan  *category = a;
241132718Skan}
242132718Skan
243132718Skan/* Diagnose failure to meet expectations in a partially filled out
244132718Skan   mode structure.  */
245132718Skanenum requirement { SET, UNSET, OPTIONAL };
246132718Skan
247132718Skan#define validate_field_(mname, fname, req, val, unset, file, line) do {	\
248132718Skan  switch (req)								\
249132718Skan    {									\
250132718Skan    case SET:								\
251132718Skan      if (val == unset)							\
252132718Skan	error ("%s:%d: (%s) field %s must be set",			\
253132718Skan	       file, line, mname, fname);				\
254132718Skan      break;								\
255132718Skan    case UNSET:								\
256132718Skan      if (val != unset)							\
257132718Skan	error ("%s:%d: (%s) field %s must not be set",			\
258132718Skan	       file, line, mname, fname);				\
259132718Skan    case OPTIONAL:							\
260132718Skan      break;								\
261132718Skan    }									\
262132718Skan} while (0)
263132718Skan
264132718Skan#define validate_field(M, F) \
265132718Skan  validate_field_(M->name, #F, r_##F, M->F, blank_mode.F, M->file, M->line)
266132718Skan
267132718Skanstatic void
268132718Skanvalidate_mode (struct mode_data *m,
269132718Skan	       enum requirement r_precision,
270132718Skan	       enum requirement r_bytesize,
271132718Skan	       enum requirement r_component,
272132718Skan	       enum requirement r_ncomponents,
273132718Skan	       enum requirement r_format)
274132718Skan{
275132718Skan  validate_field (m, precision);
276132718Skan  validate_field (m, bytesize);
277132718Skan  validate_field (m, component);
278132718Skan  validate_field (m, ncomponents);
279132718Skan  validate_field (m, format);
280132718Skan}
281132718Skan#undef validate_field
282132718Skan#undef validate_field_
283132718Skan
284132718Skan/* Given a partially-filled-out mode structure, figure out what we can
285132718Skan   and fill the rest of it in; die if it isn't enough.  */
286132718Skanstatic void
287132718Skancomplete_mode (struct mode_data *m)
288132718Skan{
289132718Skan  unsigned int alignment;
290132718Skan
291132718Skan  if (!m->name)
292132718Skan    {
293132718Skan      error ("%s:%d: mode with no name", m->file, m->line);
294132718Skan      return;
295132718Skan    }
296169689Skan  if (m->cl == MAX_MODE_CLASS)
297132718Skan    {
298132718Skan      error ("%s:%d: %smode has no mode class", m->file, m->line, m->name);
299132718Skan      return;
300132718Skan    }
301132718Skan
302169689Skan  switch (m->cl)
303132718Skan    {
304132718Skan    case MODE_RANDOM:
305132718Skan      /* Nothing more need be said.  */
306132718Skan      if (!strcmp (m->name, "VOID"))
307132718Skan	void_mode = m;
308132718Skan
309132718Skan      validate_mode (m, UNSET, UNSET, UNSET, UNSET, UNSET);
310132718Skan
311132718Skan      m->precision = 0;
312132718Skan      m->bytesize = 0;
313132718Skan      m->ncomponents = 0;
314132718Skan      m->component = 0;
315132718Skan      break;
316132718Skan
317132718Skan    case MODE_CC:
318132718Skan      /* Again, nothing more need be said.  For historical reasons,
319132718Skan	 the size of a CC mode is four units.  */
320132718Skan      validate_mode (m, UNSET, UNSET, UNSET, UNSET, UNSET);
321132718Skan
322132718Skan      m->bytesize = 4;
323132718Skan      m->ncomponents = 1;
324132718Skan      m->component = 0;
325132718Skan      break;
326132718Skan
327132718Skan    case MODE_INT:
328132718Skan    case MODE_FLOAT:
329169689Skan    case MODE_DECIMAL_FLOAT:
330132718Skan      /* A scalar mode must have a byte size, may have a bit size,
331132718Skan	 and must not have components.   A float mode must have a
332132718Skan         format.  */
333132718Skan      validate_mode (m, OPTIONAL, SET, UNSET, UNSET,
334169689Skan		     m->cl != MODE_INT ? SET : UNSET);
335132718Skan
336132718Skan      m->ncomponents = 1;
337132718Skan      m->component = 0;
338132718Skan      break;
339132718Skan
340132718Skan    case MODE_PARTIAL_INT:
341132718Skan      /* A partial integer mode uses ->component to say what the
342132718Skan	 corresponding full-size integer mode is, and may also
343132718Skan	 specify a bit size.  */
344132718Skan      validate_mode (m, OPTIONAL, UNSET, SET, UNSET, UNSET);
345132718Skan
346132718Skan      m->bytesize = m->component->bytesize;
347132718Skan
348132718Skan      m->ncomponents = 1;
349132718Skan      m->component = 0;  /* ??? preserve this */
350132718Skan      break;
351132718Skan
352132718Skan    case MODE_COMPLEX_INT:
353132718Skan    case MODE_COMPLEX_FLOAT:
354132718Skan      /* Complex modes should have a component indicated, but no more.  */
355132718Skan      validate_mode (m, UNSET, UNSET, SET, UNSET, UNSET);
356132718Skan      m->ncomponents = 2;
357132718Skan      if (m->component->precision != (unsigned int)-1)
358132718Skan	m->precision = 2 * m->component->precision;
359132718Skan      m->bytesize = 2 * m->component->bytesize;
360132718Skan      break;
361132718Skan
362132718Skan    case MODE_VECTOR_INT:
363132718Skan    case MODE_VECTOR_FLOAT:
364132718Skan      /* Vector modes should have a component and a number of components.  */
365132718Skan      validate_mode (m, UNSET, UNSET, SET, SET, UNSET);
366132718Skan      if (m->component->precision != (unsigned int)-1)
367132718Skan	m->precision = m->ncomponents * m->component->precision;
368132718Skan      m->bytesize = m->ncomponents * m->component->bytesize;
369132718Skan      break;
370132718Skan
371132718Skan    default:
372169689Skan      gcc_unreachable ();
373132718Skan    }
374132718Skan
375132718Skan  /* If not already specified, the mode alignment defaults to the largest
376132718Skan     power of two that divides the size of the object.  Complex types are
377132718Skan     not more aligned than their contents.  */
378169689Skan  if (m->cl == MODE_COMPLEX_INT || m->cl == MODE_COMPLEX_FLOAT)
379132718Skan    alignment = m->component->bytesize;
380132718Skan  else
381132718Skan    alignment = m->bytesize;
382132718Skan
383132718Skan  m->alignment = alignment & (~alignment + 1);
384132718Skan
385132718Skan  /* If this mode has components, make the component mode point back
386132718Skan     to this mode, for the sake of adjustments.  */
387132718Skan  if (m->component)
388132718Skan    {
389132718Skan      m->next_cont = m->component->contained;
390132718Skan      m->component->contained = m;
391132718Skan    }
392132718Skan}
393132718Skan
394132718Skanstatic void
395132718Skancomplete_all_modes (void)
396132718Skan{
397132718Skan  struct mode_data *m;
398169689Skan  int cl;
399169689Skan
400169689Skan  for_all_modes (cl, m)
401132718Skan    complete_mode (m);
402132718Skan}
403132718Skan
404132718Skan/* For each mode in class CLASS, construct a corresponding complex mode.  */
405132718Skan#define COMPLEX_MODES(C) make_complex_modes(MODE_##C, __FILE__, __LINE__)
406132718Skanstatic void
407169689Skanmake_complex_modes (enum mode_class cl,
408132718Skan		    const char *file, unsigned int line)
409132718Skan{
410132718Skan  struct mode_data *m;
411132718Skan  struct mode_data *c;
412132718Skan  char buf[8];
413169689Skan  enum mode_class cclass = complex_class (cl);
414132718Skan
415132718Skan  if (cclass == MODE_RANDOM)
416132718Skan    return;
417169689Skan
418169689Skan  for (m = modes[cl]; m; m = m->next)
419132718Skan    {
420132718Skan      /* Skip BImode.  FIXME: BImode probably shouldn't be MODE_INT.  */
421132718Skan      if (m->precision == 1)
422132718Skan	continue;
423132718Skan
424132718Skan      if (strlen (m->name) >= sizeof buf)
425132718Skan	{
426132718Skan	  error ("%s:%d:mode name \"%s\" is too long",
427132718Skan		 m->file, m->line, m->name);
428132718Skan	  continue;
429132718Skan	}
430132718Skan
431132718Skan      /* Float complex modes are named SCmode, etc.
432132718Skan	 Int complex modes are named CSImode, etc.
433132718Skan         This inconsistency should be eliminated.  */
434169689Skan      if (cl == MODE_FLOAT)
435132718Skan	{
436169689Skan	  char *p, *q = 0;
437132718Skan	  strncpy (buf, m->name, sizeof buf);
438132718Skan	  p = strchr (buf, 'F');
439132718Skan	  if (p == 0)
440169689Skan	    q = strchr (buf, 'D');
441169689Skan	  if (p == 0 && q == 0)
442132718Skan	    {
443169689Skan	      error ("%s:%d: float mode \"%s\" has no 'F' or 'D'",
444132718Skan		     m->file, m->line, m->name);
445132718Skan	      continue;
446132718Skan	    }
447132718Skan
448169689Skan	  if (p != 0)
449169689Skan	    *p = 'C';
450169689Skan	  else
451169689Skan	    snprintf (buf, sizeof buf, "C%s", m->name);
452132718Skan	}
453132718Skan      else
454132718Skan	snprintf (buf, sizeof buf, "C%s", m->name);
455132718Skan
456132718Skan      c = new_mode (cclass, xstrdup (buf), file, line);
457132718Skan      c->component = m;
458132718Skan    }
459132718Skan}
460132718Skan
461169689Skan/* For all modes in class CL, construct vector modes of width
462132718Skan   WIDTH, having as many components as necessary.  */
463132718Skan#define VECTOR_MODES(C, W) make_vector_modes(MODE_##C, W, __FILE__, __LINE__)
464169689Skanstatic void ATTRIBUTE_UNUSED
465169689Skanmake_vector_modes (enum mode_class cl, unsigned int width,
466132718Skan		   const char *file, unsigned int line)
467132718Skan{
468132718Skan  struct mode_data *m;
469132718Skan  struct mode_data *v;
470132718Skan  char buf[8];
471132718Skan  unsigned int ncomponents;
472169689Skan  enum mode_class vclass = vector_class (cl);
473132718Skan
474132718Skan  if (vclass == MODE_RANDOM)
475132718Skan    return;
476132718Skan
477169689Skan  for (m = modes[cl]; m; m = m->next)
478132718Skan    {
479132718Skan      /* Do not construct vector modes with only one element, or
480132718Skan	 vector modes where the element size doesn't divide the full
481132718Skan	 size evenly.  */
482132718Skan      ncomponents = width / m->bytesize;
483132718Skan      if (ncomponents < 2)
484132718Skan	continue;
485132718Skan      if (width % m->bytesize)
486132718Skan	continue;
487132718Skan
488132718Skan      /* Skip QFmode and BImode.  FIXME: this special case should
489132718Skan	 not be necessary.  */
490169689Skan      if (cl == MODE_FLOAT && m->bytesize == 1)
491132718Skan	continue;
492169689Skan      if (cl == MODE_INT && m->precision == 1)
493132718Skan	continue;
494132718Skan
495132718Skan      if ((size_t)snprintf (buf, sizeof buf, "V%u%s", ncomponents, m->name)
496132718Skan	  >= sizeof buf)
497132718Skan	{
498132718Skan	  error ("%s:%d: mode name \"%s\" is too long",
499132718Skan		 m->file, m->line, m->name);
500132718Skan	  continue;
501132718Skan	}
502132718Skan
503132718Skan      v = new_mode (vclass, xstrdup (buf), file, line);
504132718Skan      v->component = m;
505132718Skan      v->ncomponents = ncomponents;
506132718Skan    }
507132718Skan}
508132718Skan
509132718Skan/* Input.  */
510132718Skan
511132718Skan#define _SPECIAL_MODE(C, N) make_special_mode(MODE_##C, #N, __FILE__, __LINE__)
512132718Skan#define RANDOM_MODE(N) _SPECIAL_MODE (RANDOM, N)
513132718Skan#define CC_MODE(N) _SPECIAL_MODE (CC, N)
514132718Skan
515132718Skanstatic void
516169689Skanmake_special_mode (enum mode_class cl, const char *name,
517132718Skan		   const char *file, unsigned int line)
518132718Skan{
519169689Skan  new_mode (cl, name, file, line);
520132718Skan}
521132718Skan
522169689Skan#define INT_MODE(N, Y) FRACTIONAL_INT_MODE (N, -1U, Y)
523132718Skan#define FRACTIONAL_INT_MODE(N, B, Y) \
524132718Skan  make_int_mode (#N, B, Y, __FILE__, __LINE__)
525132718Skan
526132718Skanstatic void
527132718Skanmake_int_mode (const char *name,
528132718Skan	       unsigned int precision, unsigned int bytesize,
529132718Skan	       const char *file, unsigned int line)
530132718Skan{
531132718Skan  struct mode_data *m = new_mode (MODE_INT, name, file, line);
532132718Skan  m->bytesize = bytesize;
533132718Skan  m->precision = precision;
534132718Skan}
535132718Skan
536169689Skan#define FLOAT_MODE(N, Y, F)             FRACTIONAL_FLOAT_MODE (N, -1U, Y, F)
537132718Skan#define FRACTIONAL_FLOAT_MODE(N, B, Y, F) \
538132718Skan  make_float_mode (#N, B, Y, #F, __FILE__, __LINE__)
539132718Skan
540132718Skanstatic void
541132718Skanmake_float_mode (const char *name,
542132718Skan		 unsigned int precision, unsigned int bytesize,
543132718Skan		 const char *format,
544132718Skan		 const char *file, unsigned int line)
545132718Skan{
546132718Skan  struct mode_data *m = new_mode (MODE_FLOAT, name, file, line);
547132718Skan  m->bytesize = bytesize;
548132718Skan  m->precision = precision;
549132718Skan  m->format = format;
550132718Skan}
551132718Skan
552169689Skan#define DECIMAL_FLOAT_MODE(N, Y, F)	\
553169689Skan	FRACTIONAL_DECIMAL_FLOAT_MODE (N, -1U, Y, F)
554169689Skan#define FRACTIONAL_DECIMAL_FLOAT_MODE(N, B, Y, F)	\
555169689Skan  make_decimal_float_mode (#N, B, Y, #F, __FILE__, __LINE__)
556169689Skan
557169689Skanstatic void
558169689Skanmake_decimal_float_mode (const char *name,
559169689Skan			 unsigned int precision, unsigned int bytesize,
560169689Skan			 const char *format,
561169689Skan			 const char *file, unsigned int line)
562169689Skan{
563169689Skan  struct mode_data *m = new_mode (MODE_DECIMAL_FLOAT, name, file, line);
564169689Skan  m->bytesize = bytesize;
565169689Skan  m->precision = precision;
566169689Skan  m->format = format;
567169689Skan}
568169689Skan
569132718Skan#define RESET_FLOAT_FORMAT(N, F) \
570132718Skan  reset_float_format (#N, #F, __FILE__, __LINE__)
571132718Skanstatic void ATTRIBUTE_UNUSED
572132718Skanreset_float_format (const char *name, const char *format,
573132718Skan		    const char *file, unsigned int line)
574132718Skan{
575132718Skan  struct mode_data *m = find_mode (name);
576132718Skan  if (!m)
577132718Skan    {
578132718Skan      error ("%s:%d: no mode \"%s\"", file, line, name);
579132718Skan      return;
580132718Skan    }
581169689Skan  if (m->cl != MODE_FLOAT && m->cl != MODE_DECIMAL_FLOAT)
582132718Skan    {
583169689Skan      error ("%s:%d: mode \"%s\" is not a FLOAT class", file, line, name);
584132718Skan      return;
585132718Skan    }
586132718Skan  m->format = format;
587132718Skan}
588132718Skan
589132718Skan/* Partial integer modes are specified by relation to a full integer mode.
590132718Skan   For now, we do not attempt to narrow down their bit sizes.  */
591132718Skan#define PARTIAL_INT_MODE(M) \
592169689Skan  make_partial_integer_mode (#M, "P" #M, -1U, __FILE__, __LINE__)
593132718Skanstatic void ATTRIBUTE_UNUSED
594132718Skanmake_partial_integer_mode (const char *base, const char *name,
595132718Skan			   unsigned int precision,
596132718Skan			   const char *file, unsigned int line)
597132718Skan{
598132718Skan  struct mode_data *m;
599132718Skan  struct mode_data *component = find_mode (base);
600132718Skan  if (!component)
601132718Skan    {
602132718Skan      error ("%s:%d: no mode \"%s\"", file, line, name);
603132718Skan      return;
604132718Skan    }
605169689Skan  if (component->cl != MODE_INT)
606132718Skan    {
607132718Skan      error ("%s:%d: mode \"%s\" is not class INT", file, line, name);
608132718Skan      return;
609132718Skan    }
610169689Skan
611132718Skan  m = new_mode (MODE_PARTIAL_INT, name, file, line);
612132718Skan  m->precision = precision;
613132718Skan  m->component = component;
614132718Skan}
615132718Skan
616132718Skan/* A single vector mode can be specified by naming its component
617132718Skan   mode and the number of components.  */
618132718Skan#define VECTOR_MODE(C, M, N) \
619132718Skan  make_vector_mode (MODE_##C, #M, N, __FILE__, __LINE__);
620132718Skanstatic void ATTRIBUTE_UNUSED
621132718Skanmake_vector_mode (enum mode_class bclass,
622132718Skan		  const char *base,
623132718Skan		  unsigned int ncomponents,
624132718Skan		  const char *file, unsigned int line)
625132718Skan{
626132718Skan  struct mode_data *v;
627132718Skan  enum mode_class vclass = vector_class (bclass);
628132718Skan  struct mode_data *component = find_mode (base);
629132718Skan  char namebuf[8];
630132718Skan
631132718Skan  if (vclass == MODE_RANDOM)
632132718Skan    return;
633132718Skan  if (component == 0)
634132718Skan    {
635132718Skan      error ("%s:%d: no mode \"%s\"", file, line, base);
636132718Skan      return;
637132718Skan    }
638169689Skan  if (component->cl != bclass
639169689Skan      && (component->cl != MODE_PARTIAL_INT
640169689Skan	  || bclass != MODE_INT))
641132718Skan    {
642132718Skan      error ("%s:%d: mode \"%s\" is not class %s",
643132718Skan	     file, line, base, mode_class_names[bclass] + 5);
644132718Skan      return;
645132718Skan    }
646132718Skan
647132718Skan  if ((size_t)snprintf (namebuf, sizeof namebuf, "V%u%s",
648132718Skan			ncomponents, base) >= sizeof namebuf)
649132718Skan    {
650132718Skan      error ("%s:%d: mode name \"%s\" is too long",
651169689Skan	     file, line, base);
652132718Skan      return;
653132718Skan    }
654132718Skan
655132718Skan  v = new_mode (vclass, xstrdup (namebuf), file, line);
656132718Skan  v->ncomponents = ncomponents;
657132718Skan  v->component = component;
658132718Skan}
659132718Skan
660132718Skan/* Adjustability.  */
661132718Skan#define _ADD_ADJUST(A, M, X, C) \
662132718Skan  new_adjust (#M, &adj_##A, #A, #X, MODE_##C, __FILE__, __LINE__)
663132718Skan
664132718Skan#define ADJUST_BYTESIZE(M, X)  _ADD_ADJUST(bytesize, M, X, RANDOM)
665132718Skan#define ADJUST_ALIGNMENT(M, X) _ADD_ADJUST(alignment, M, X, RANDOM)
666132718Skan#define ADJUST_FLOAT_FORMAT(M, X)    _ADD_ADJUST(format, M, X, FLOAT)
667132718Skan
668132718Skanstatic void
669132718Skancreate_modes (void)
670132718Skan{
671132718Skan#include "machmode.def"
672132718Skan}
673132718Skan
674132718Skan/* Processing.  */
675132718Skan
676132718Skan/* Sort a list of modes into the order needed for the WIDER field:
677132718Skan   major sort by precision, minor sort by component precision.
678132718Skan
679132718Skan   For instance:
680132718Skan     QI < HI < SI < DI < TI
681132718Skan     V4QI < V2HI < V8QI < V4HI < V2SI.
682132718Skan
683132718Skan   If the precision is not set, sort by the bytesize.  A mode with
684132718Skan   precision set gets sorted before a mode without precision set, if
685132718Skan   they have the same bytesize; this is the right thing because
686132718Skan   the precision must always be smaller than the bytesize * BITS_PER_UNIT.
687132718Skan   We don't have to do anything special to get this done -- an unset
688132718Skan   precision shows up as (unsigned int)-1, i.e. UINT_MAX.  */
689132718Skanstatic int
690132718Skancmp_modes (const void *a, const void *b)
691132718Skan{
692132718Skan  struct mode_data *m = *(struct mode_data **)a;
693132718Skan  struct mode_data *n = *(struct mode_data **)b;
694132718Skan
695132718Skan  if (m->bytesize > n->bytesize)
696132718Skan    return 1;
697132718Skan  else if (m->bytesize < n->bytesize)
698132718Skan    return -1;
699132718Skan
700132718Skan  if (m->precision > n->precision)
701132718Skan    return 1;
702132718Skan  else if (m->precision < n->precision)
703132718Skan    return -1;
704132718Skan
705132718Skan  if (!m->component && !n->component)
706169689Skan    {
707169689Skan      if (m->counter < n->counter)
708169689Skan	return -1;
709169689Skan      else
710169689Skan	return 1;
711169689Skan    }
712132718Skan
713132718Skan  if (m->component->bytesize > n->component->bytesize)
714132718Skan    return 1;
715132718Skan  else if (m->component->bytesize < n->component->bytesize)
716132718Skan    return -1;
717132718Skan
718132718Skan  if (m->component->precision > n->component->precision)
719132718Skan    return 1;
720132718Skan  else if (m->component->precision < n->component->precision)
721132718Skan    return -1;
722132718Skan
723169689Skan  if (m->counter < n->counter)
724169689Skan    return -1;
725169689Skan  else
726169689Skan    return 1;
727132718Skan}
728132718Skan
729132718Skanstatic void
730132718Skancalc_wider_mode (void)
731132718Skan{
732169689Skan  int c;
733132718Skan  struct mode_data *m;
734132718Skan  struct mode_data **sortbuf;
735132718Skan  unsigned int max_n_modes = 0;
736132718Skan  unsigned int i, j;
737132718Skan
738132718Skan  for (c = 0; c < MAX_MODE_CLASS; c++)
739132718Skan    max_n_modes = MAX (max_n_modes, n_modes[c]);
740132718Skan
741132718Skan  /* Allocate max_n_modes + 1 entries to leave room for the extra null
742132718Skan     pointer assigned after the qsort call below.  */
743169689Skan  sortbuf = (struct mode_data **) alloca ((max_n_modes + 1) * sizeof (struct mode_data *));
744132718Skan
745132718Skan  for (c = 0; c < MAX_MODE_CLASS; c++)
746132718Skan    {
747132718Skan      /* "wider" is not meaningful for MODE_RANDOM and MODE_CC.
748132718Skan	 However, we want these in textual order, and we have
749132718Skan	 precisely the reverse.  */
750132718Skan      if (c == MODE_RANDOM || c == MODE_CC)
751132718Skan	{
752132718Skan	  struct mode_data *prev, *next;
753132718Skan
754132718Skan	  for (prev = 0, m = modes[c]; m; m = next)
755132718Skan	    {
756132718Skan	      m->wider = void_mode;
757169689Skan	      m->wider_2x = void_mode;
758132718Skan
759132718Skan	      /* this is nreverse */
760132718Skan	      next = m->next;
761132718Skan	      m->next = prev;
762132718Skan	      prev = m;
763132718Skan	    }
764132718Skan	  modes[c] = prev;
765132718Skan	}
766132718Skan      else
767132718Skan	{
768132718Skan	  if (!modes[c])
769132718Skan	    continue;
770132718Skan
771132718Skan	  for (i = 0, m = modes[c]; m; i++, m = m->next)
772132718Skan	    sortbuf[i] = m;
773132718Skan
774132718Skan	  qsort (sortbuf, i, sizeof (struct mode_data *), cmp_modes);
775132718Skan
776132718Skan	  sortbuf[i] = 0;
777132718Skan	  for (j = 0; j < i; j++)
778132718Skan	    sortbuf[j]->next = sortbuf[j]->wider = sortbuf[j + 1];
779132718Skan
780132718Skan
781132718Skan	  modes[c] = sortbuf[0];
782132718Skan	}
783132718Skan    }
784132718Skan}
785132718Skan
786132718Skan/* Output routines.  */
787132718Skan
788132718Skan#define tagged_printf(FMT, ARG, TAG) do {		\
789132718Skan  int count_;						\
790222082Sbenl  count_ = printf ("  " FMT ",", ARG);			\
791132718Skan  printf ("%*s/* %s */\n", 27 - count_, "", TAG);	\
792132718Skan} while (0)
793132718Skan
794132718Skan#define print_decl(TYPE, NAME, ASIZE) \
795132718Skan  puts ("\nconst " TYPE " " NAME "[" ASIZE "] =\n{");
796132718Skan
797132718Skan#define print_maybe_const_decl(TYPE, NAME, ASIZE, CATEGORY)	\
798132718Skan  printf ("\n" TYPE " " NAME "[" ASIZE "] = \n{\n",		\
799132718Skan	  adj_##CATEGORY ? "" : "const ")
800132718Skan
801132718Skan#define print_closer() puts ("};")
802132718Skan
803132718Skanstatic void
804132718Skanemit_insn_modes_h (void)
805132718Skan{
806169689Skan  int c;
807132718Skan  struct mode_data *m, *first, *last;
808132718Skan
809132718Skan  printf ("/* Generated automatically from machmode.def%s%s\n",
810132718Skan	   HAVE_EXTRA_MODES ? " and " : "",
811132718Skan	   EXTRA_MODES_FILE);
812132718Skan
813132718Skan  puts ("\
814132718Skan   by genmodes.  */\n\
815132718Skan\n\
816132718Skan#ifndef GCC_INSN_MODES_H\n\
817132718Skan#define GCC_INSN_MODES_H\n\
818132718Skan\n\
819132718Skanenum machine_mode\n{");
820132718Skan
821132718Skan  for (c = 0; c < MAX_MODE_CLASS; c++)
822132718Skan    for (m = modes[c]; m; m = m->next)
823132718Skan      {
824132718Skan	int count_;
825222082Sbenl	count_ = printf ("  %smode,", m->name);
826132718Skan	printf ("%*s/* %s:%d */\n", 27 - count_, "",
827132718Skan		 trim_filename (m->file), m->line);
828132718Skan      }
829132718Skan
830132718Skan  puts ("  MAX_MACHINE_MODE,\n");
831132718Skan
832132718Skan  for (c = 0; c < MAX_MODE_CLASS; c++)
833132718Skan    {
834132718Skan      first = modes[c];
835132718Skan      last = 0;
836132718Skan      for (m = first; m; last = m, m = m->next)
837132718Skan	;
838132718Skan
839132718Skan      /* Don't use BImode for MIN_MODE_INT, since otherwise the middle
840132718Skan	 end will try to use it for bitfields in structures and the
841132718Skan	 like, which we do not want.  Only the target md file should
842132718Skan	 generate BImode widgets.  */
843132718Skan      if (first && first->precision == 1)
844132718Skan	first = first->next;
845132718Skan
846132718Skan      if (first && last)
847132718Skan	printf ("  MIN_%s = %smode,\n  MAX_%s = %smode,\n\n",
848132718Skan		 mode_class_names[c], first->name,
849132718Skan		 mode_class_names[c], last->name);
850132718Skan      else
851132718Skan	printf ("  MIN_%s = %smode,\n  MAX_%s = %smode,\n\n",
852132718Skan		 mode_class_names[c], void_mode->name,
853132718Skan		 mode_class_names[c], void_mode->name);
854132718Skan    }
855132718Skan
856132718Skan  puts ("\
857132718Skan  NUM_MACHINE_MODES = MAX_MACHINE_MODE\n\
858132718Skan};\n");
859132718Skan
860132718Skan  /* I can't think of a better idea, can you?  */
861132718Skan  printf ("#define CONST_MODE_SIZE%s\n", adj_bytesize ? "" : " const");
862132718Skan  printf ("#define CONST_MODE_BASE_ALIGN%s\n", adj_alignment ? "" : " const");
863132718Skan#if 0 /* disabled for backward compatibility, temporary */
864132718Skan  printf ("#define CONST_REAL_FORMAT_FOR_MODE%s\n", adj_format ? "" :" const");
865132718Skan#endif
866132718Skan  puts ("\
867132718Skan\n\
868132718Skan#endif /* insn-modes.h */");
869132718Skan}
870132718Skan
871132718Skanstatic void
872132718Skanemit_insn_modes_c_header (void)
873132718Skan{
874132718Skan  printf ("/* Generated automatically from machmode.def%s%s\n",
875132718Skan	   HAVE_EXTRA_MODES ? " and " : "",
876132718Skan	   EXTRA_MODES_FILE);
877132718Skan
878132718Skan  puts ("\
879132718Skan   by genmodes.  */\n\
880132718Skan\n\
881132718Skan#include \"config.h\"\n\
882132718Skan#include \"system.h\"\n\
883132718Skan#include \"coretypes.h\"\n\
884132718Skan#include \"tm.h\"\n\
885132718Skan#include \"machmode.h\"\n\
886132718Skan#include \"real.h\"");
887132718Skan}
888132718Skan
889132718Skanstatic void
890132718Skanemit_min_insn_modes_c_header (void)
891132718Skan{
892132718Skan  printf ("/* Generated automatically from machmode.def%s%s\n",
893132718Skan	   HAVE_EXTRA_MODES ? " and " : "",
894132718Skan	   EXTRA_MODES_FILE);
895132718Skan
896132718Skan  puts ("\
897132718Skan   by genmodes.  */\n\
898132718Skan\n\
899132718Skan#include \"bconfig.h\"\n\
900132718Skan#include \"system.h\"\n\
901132718Skan#include \"machmode.h\"");
902132718Skan}
903132718Skan
904132718Skanstatic void
905132718Skanemit_mode_name (void)
906132718Skan{
907169689Skan  int c;
908132718Skan  struct mode_data *m;
909132718Skan
910132718Skan  print_decl ("char *const", "mode_name", "NUM_MACHINE_MODES");
911132718Skan
912132718Skan  for_all_modes (c, m)
913132718Skan    printf ("  \"%s\",\n", m->name);
914132718Skan
915132718Skan  print_closer ();
916132718Skan}
917132718Skan
918132718Skanstatic void
919132718Skanemit_mode_class (void)
920132718Skan{
921169689Skan  int c;
922132718Skan  struct mode_data *m;
923132718Skan
924132718Skan  print_decl ("unsigned char", "mode_class", "NUM_MACHINE_MODES");
925132718Skan
926132718Skan  for_all_modes (c, m)
927169689Skan    tagged_printf ("%s", mode_class_names[m->cl], m->name);
928132718Skan
929132718Skan  print_closer ();
930132718Skan}
931132718Skan
932132718Skanstatic void
933132718Skanemit_mode_precision (void)
934132718Skan{
935169689Skan  int c;
936132718Skan  struct mode_data *m;
937132718Skan
938132718Skan  print_decl ("unsigned short", "mode_precision", "NUM_MACHINE_MODES");
939132718Skan
940132718Skan  for_all_modes (c, m)
941132718Skan    if (m->precision != (unsigned int)-1)
942132718Skan      tagged_printf ("%u", m->precision, m->name);
943132718Skan    else
944132718Skan      tagged_printf ("%u*BITS_PER_UNIT", m->bytesize, m->name);
945132718Skan
946132718Skan  print_closer ();
947132718Skan}
948132718Skan
949132718Skanstatic void
950132718Skanemit_mode_size (void)
951132718Skan{
952169689Skan  int c;
953132718Skan  struct mode_data *m;
954132718Skan
955132718Skan  print_maybe_const_decl ("%sunsigned char", "mode_size",
956132718Skan			  "NUM_MACHINE_MODES", bytesize);
957132718Skan
958132718Skan  for_all_modes (c, m)
959132718Skan    tagged_printf ("%u", m->bytesize, m->name);
960132718Skan
961132718Skan  print_closer ();
962132718Skan}
963132718Skan
964132718Skanstatic void
965132718Skanemit_mode_nunits (void)
966132718Skan{
967169689Skan  int c;
968132718Skan  struct mode_data *m;
969132718Skan
970132718Skan  print_decl ("unsigned char", "mode_nunits", "NUM_MACHINE_MODES");
971132718Skan
972132718Skan  for_all_modes (c, m)
973132718Skan    tagged_printf ("%u", m->ncomponents, m->name);
974132718Skan
975132718Skan  print_closer ();
976132718Skan}
977132718Skan
978132718Skanstatic void
979132718Skanemit_mode_wider (void)
980132718Skan{
981169689Skan  int c;
982132718Skan  struct mode_data *m;
983132718Skan
984132718Skan  print_decl ("unsigned char", "mode_wider", "NUM_MACHINE_MODES");
985132718Skan
986132718Skan  for_all_modes (c, m)
987132718Skan    tagged_printf ("%smode",
988132718Skan		   m->wider ? m->wider->name : void_mode->name,
989132718Skan		   m->name);
990132718Skan
991132718Skan  print_closer ();
992169689Skan  print_decl ("unsigned char", "mode_2xwider", "NUM_MACHINE_MODES");
993169689Skan
994169689Skan  for_all_modes (c, m)
995169689Skan    {
996169689Skan      struct mode_data * m2;
997169689Skan
998169689Skan      for (m2 = m;
999169689Skan	   m2 && m2 != void_mode;
1000169689Skan	   m2 = m2->wider)
1001169689Skan	{
1002169689Skan	  if (m2->bytesize < 2 * m->bytesize)
1003169689Skan	    continue;
1004169689Skan	  if (m->precision != (unsigned int) -1)
1005169689Skan	    {
1006169689Skan	      if (m2->precision != 2 * m->precision)
1007169689Skan		continue;
1008169689Skan	    }
1009169689Skan	  else
1010169689Skan	    {
1011169689Skan	      if (m2->precision != (unsigned int) -1)
1012169689Skan		continue;
1013169689Skan	    }
1014169689Skan
1015169689Skan	  break;
1016169689Skan	}
1017169689Skan      if (m2 == void_mode)
1018169689Skan	m2 = 0;
1019169689Skan      tagged_printf ("%smode",
1020169689Skan		     m2 ? m2->name : void_mode->name,
1021169689Skan		     m->name);
1022169689Skan    }
1023169689Skan
1024169689Skan  print_closer ();
1025132718Skan}
1026132718Skan
1027132718Skanstatic void
1028132718Skanemit_mode_mask (void)
1029132718Skan{
1030169689Skan  int c;
1031132718Skan  struct mode_data *m;
1032132718Skan
1033132718Skan  print_decl ("unsigned HOST_WIDE_INT", "mode_mask_array",
1034132718Skan	      "NUM_MACHINE_MODES");
1035132718Skan  puts ("\
1036132718Skan#define MODE_MASK(m)                          \\\n\
1037132718Skan  ((m) >= HOST_BITS_PER_WIDE_INT)             \\\n\
1038132718Skan   ? ~(unsigned HOST_WIDE_INT) 0              \\\n\
1039132718Skan   : ((unsigned HOST_WIDE_INT) 1 << (m)) - 1\n");
1040132718Skan
1041132718Skan  for_all_modes (c, m)
1042132718Skan    if (m->precision != (unsigned int)-1)
1043132718Skan      tagged_printf ("MODE_MASK (%u)", m->precision, m->name);
1044132718Skan    else
1045132718Skan      tagged_printf ("MODE_MASK (%u*BITS_PER_UNIT)", m->bytesize, m->name);
1046132718Skan
1047132718Skan  puts ("#undef MODE_MASK");
1048132718Skan  print_closer ();
1049132718Skan}
1050132718Skan
1051132718Skanstatic void
1052132718Skanemit_mode_inner (void)
1053132718Skan{
1054169689Skan  int c;
1055132718Skan  struct mode_data *m;
1056132718Skan
1057132718Skan  print_decl ("unsigned char", "mode_inner", "NUM_MACHINE_MODES");
1058132718Skan
1059132718Skan  for_all_modes (c, m)
1060132718Skan    tagged_printf ("%smode",
1061132718Skan		   m->component ? m->component->name : void_mode->name,
1062132718Skan		   m->name);
1063132718Skan
1064132718Skan  print_closer ();
1065132718Skan}
1066132718Skan
1067132718Skanstatic void
1068132718Skanemit_mode_base_align (void)
1069132718Skan{
1070169689Skan  int c;
1071132718Skan  struct mode_data *m;
1072132718Skan
1073132718Skan  print_maybe_const_decl ("%sunsigned char",
1074132718Skan			  "mode_base_align", "NUM_MACHINE_MODES",
1075132718Skan			  alignment);
1076132718Skan
1077132718Skan  for_all_modes (c, m)
1078132718Skan    tagged_printf ("%u", m->alignment, m->name);
1079132718Skan
1080132718Skan  print_closer ();
1081132718Skan}
1082132718Skan
1083132718Skanstatic void
1084132718Skanemit_class_narrowest_mode (void)
1085132718Skan{
1086169689Skan  int c;
1087132718Skan
1088132718Skan  print_decl ("unsigned char", "class_narrowest_mode", "MAX_MODE_CLASS");
1089132718Skan
1090132718Skan  for (c = 0; c < MAX_MODE_CLASS; c++)
1091132718Skan    /* Bleah, all this to get the comment right for MIN_MODE_INT.  */
1092132718Skan    tagged_printf ("MIN_%s", mode_class_names[c],
1093132718Skan		   modes[c]
1094132718Skan		   ? (modes[c]->precision != 1
1095132718Skan		      ? modes[c]->name
1096132718Skan		      : (modes[c]->next
1097132718Skan			 ? modes[c]->next->name
1098132718Skan			 : void_mode->name))
1099132718Skan		   : void_mode->name);
1100132718Skan
1101132718Skan  print_closer ();
1102132718Skan}
1103132718Skan
1104132718Skanstatic void
1105132718Skanemit_real_format_for_mode (void)
1106132718Skan{
1107132718Skan  struct mode_data *m;
1108132718Skan
1109132718Skan  /* The entities pointed to by this table are constant, whether
1110132718Skan     or not the table itself is constant.
1111132718Skan
1112132718Skan     For backward compatibility this table is always writable
1113132718Skan     (several targets modify it in OVERRIDE_OPTIONS).   FIXME:
1114132718Skan     convert all said targets to use ADJUST_FORMAT instead.  */
1115132718Skan#if 0
1116132718Skan  print_maybe_const_decl ("const struct real_format *%s",
1117132718Skan			  "real_format_for_mode",
1118132718Skan			  "MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1",
1119132718Skan			  format);
1120132718Skan#else
1121132718Skan  print_decl ("struct real_format *\n", "real_format_for_mode",
1122169689Skan	      "MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1 "
1123169689Skan	      "+ MAX_MODE_DECIMAL_FLOAT - MIN_MODE_DECIMAL_FLOAT + 1");
1124132718Skan#endif
1125132718Skan
1126169689Skan  /* The beginning of the table is entries for float modes.  */
1127132718Skan  for (m = modes[MODE_FLOAT]; m; m = m->next)
1128132718Skan    if (!strcmp (m->format, "0"))
1129132718Skan      tagged_printf ("%s", m->format, m->name);
1130132718Skan    else
1131132718Skan      tagged_printf ("&%s", m->format, m->name);
1132132718Skan
1133169689Skan  /* The end of the table is entries for decimal float modes.  */
1134169689Skan  for (m = modes[MODE_DECIMAL_FLOAT]; m; m = m->next)
1135169689Skan    if (!strcmp (m->format, "0"))
1136169689Skan      tagged_printf ("%s", m->format, m->name);
1137169689Skan    else
1138169689Skan      tagged_printf ("&%s", m->format, m->name);
1139169689Skan
1140132718Skan  print_closer ();
1141132718Skan}
1142132718Skan
1143132718Skanstatic void
1144132718Skanemit_mode_adjustments (void)
1145132718Skan{
1146132718Skan  struct mode_adjust *a;
1147132718Skan  struct mode_data *m;
1148132718Skan
1149132718Skan  puts ("\
1150132718Skan\nvoid\
1151132718Skan\ninit_adjust_machine_modes (void)\
1152132718Skan\n{\
1153132718Skan\n  size_t s ATTRIBUTE_UNUSED;");
1154132718Skan
1155132718Skan  /* Size adjustments must be propagated to all containing modes.
1156132718Skan     A size adjustment forces us to recalculate the alignment too.  */
1157132718Skan  for (a = adj_bytesize; a; a = a->next)
1158132718Skan    {
1159132718Skan      printf ("\n  /* %s:%d */\n  s = %s;\n",
1160132718Skan	      a->file, a->line, a->adjustment);
1161132718Skan      printf ("  mode_size[%smode] = s;\n", a->mode->name);
1162132718Skan      printf ("  mode_base_align[%smode] = s & (~s + 1);\n",
1163132718Skan	      a->mode->name);
1164132718Skan
1165132718Skan      for (m = a->mode->contained; m; m = m->next_cont)
1166132718Skan	{
1167169689Skan	  switch (m->cl)
1168132718Skan	    {
1169132718Skan	    case MODE_COMPLEX_INT:
1170132718Skan	    case MODE_COMPLEX_FLOAT:
1171132718Skan	      printf ("  mode_size[%smode] = 2*s;\n", m->name);
1172132718Skan	      printf ("  mode_base_align[%smode] = s & (~s + 1);\n",
1173132718Skan		      m->name);
1174132718Skan	      break;
1175132718Skan
1176132718Skan	    case MODE_VECTOR_INT:
1177132718Skan	    case MODE_VECTOR_FLOAT:
1178132718Skan	      printf ("  mode_size[%smode] = %d*s;\n",
1179132718Skan		      m->name, m->ncomponents);
1180132718Skan	      printf ("  mode_base_align[%smode] = (%d*s) & (~(%d*s)+1);\n",
1181132718Skan		      m->name, m->ncomponents, m->ncomponents);
1182132718Skan	      break;
1183132718Skan
1184132718Skan	    default:
1185132718Skan	      internal_error (
1186132718Skan	      "mode %s is neither vector nor complex but contains %s",
1187132718Skan	      m->name, a->mode->name);
1188132718Skan	      /* NOTREACHED */
1189132718Skan	    }
1190132718Skan	}
1191132718Skan    }
1192132718Skan
1193132718Skan  /* Alignment adjustments propagate too.
1194132718Skan     ??? This may not be the right thing for vector modes.  */
1195132718Skan  for (a = adj_alignment; a; a = a->next)
1196132718Skan    {
1197132718Skan      printf ("\n  /* %s:%d */\n  s = %s;\n",
1198132718Skan	      a->file, a->line, a->adjustment);
1199132718Skan      printf ("  mode_base_align[%smode] = s;\n", a->mode->name);
1200132718Skan
1201132718Skan      for (m = a->mode->contained; m; m = m->next_cont)
1202132718Skan	{
1203169689Skan	  switch (m->cl)
1204132718Skan	    {
1205132718Skan	    case MODE_COMPLEX_INT:
1206132718Skan	    case MODE_COMPLEX_FLOAT:
1207132718Skan	      printf ("  mode_base_align[%smode] = s;\n", m->name);
1208132718Skan	      break;
1209132718Skan
1210132718Skan	    case MODE_VECTOR_INT:
1211132718Skan	    case MODE_VECTOR_FLOAT:
1212132718Skan	      printf ("  mode_base_align[%smode] = %d*s;\n",
1213132718Skan		      m->name, m->ncomponents);
1214132718Skan	      break;
1215132718Skan
1216132718Skan	    default:
1217132718Skan	      internal_error (
1218132718Skan	      "mode %s is neither vector nor complex but contains %s",
1219132718Skan	      m->name, a->mode->name);
1220132718Skan	      /* NOTREACHED */
1221132718Skan	    }
1222132718Skan	}
1223132718Skan    }
1224132718Skan
1225132718Skan  /* Real mode formats don't have to propagate anywhere.  */
1226132718Skan  for (a = adj_format; a; a = a->next)
1227132718Skan    printf ("\n  /* %s:%d */\n  REAL_MODE_FORMAT (%smode) = %s;\n",
1228132718Skan	    a->file, a->line, a->mode->name, a->adjustment);
1229132718Skan
1230132718Skan  puts ("}");
1231132718Skan}
1232132718Skan
1233132718Skanstatic void
1234132718Skanemit_insn_modes_c (void)
1235132718Skan{
1236132718Skan  emit_insn_modes_c_header ();
1237132718Skan  emit_mode_name ();
1238132718Skan  emit_mode_class ();
1239132718Skan  emit_mode_precision ();
1240132718Skan  emit_mode_size ();
1241132718Skan  emit_mode_nunits ();
1242132718Skan  emit_mode_wider ();
1243132718Skan  emit_mode_mask ();
1244132718Skan  emit_mode_inner ();
1245132718Skan  emit_mode_base_align ();
1246132718Skan  emit_class_narrowest_mode ();
1247132718Skan  emit_real_format_for_mode ();
1248132718Skan  emit_mode_adjustments ();
1249132718Skan}
1250132718Skan
1251132718Skanstatic void
1252132718Skanemit_min_insn_modes_c (void)
1253132718Skan{
1254132718Skan  emit_min_insn_modes_c_header ();
1255132718Skan  emit_mode_name ();
1256132718Skan  emit_mode_class ();
1257132718Skan  emit_mode_wider ();
1258132718Skan  emit_class_narrowest_mode ();
1259132718Skan}
1260132718Skan
1261132718Skan/* Master control.  */
1262132718Skanint
1263132718Skanmain(int argc, char **argv)
1264132718Skan{
1265132718Skan  bool gen_header = false, gen_min = false;
1266132718Skan  progname = argv[0];
1267132718Skan
1268132718Skan  if (argc == 1)
1269132718Skan    ;
1270132718Skan  else if (argc == 2 && !strcmp (argv[1], "-h"))
1271132718Skan    gen_header = true;
1272132718Skan  else if (argc == 2 && !strcmp (argv[1], "-m"))
1273132718Skan    gen_min = true;
1274132718Skan  else
1275132718Skan    {
1276132718Skan      error ("usage: %s [-h|-m] > file", progname);
1277132718Skan      return FATAL_EXIT_CODE;
1278132718Skan    }
1279132718Skan
1280132718Skan  modes_by_name = htab_create_alloc (64, hash_mode, eq_mode, 0, xcalloc, free);
1281132718Skan
1282132718Skan  create_modes ();
1283132718Skan  complete_all_modes ();
1284132718Skan
1285132718Skan  if (have_error)
1286132718Skan    return FATAL_EXIT_CODE;
1287132718Skan
1288132718Skan  calc_wider_mode ();
1289132718Skan
1290132718Skan  if (gen_header)
1291132718Skan    emit_insn_modes_h ();
1292132718Skan  else if (gen_min)
1293132718Skan    emit_min_insn_modes_c ();
1294132718Skan  else
1295132718Skan    emit_insn_modes_c ();
1296132718Skan
1297132718Skan  if (fflush (stdout) || fclose (stdout))
1298132718Skan    return FATAL_EXIT_CODE;
1299132718Skan  return SUCCESS_EXIT_CODE;
1300132718Skan}
1301