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