BSD 4_4_Lite2 development
[unix-history] / usr / src / contrib / gcc-2.3.3 / rtl.c
CommitLineData
0d6b6ab3
C
1/* Allocate and read RTL for GNU C Compiler.
2 Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21#include "config.h"
22#include <ctype.h>
23#include <stdio.h>
24#include "rtl.h"
25
26#include "obstack.h"
27#define obstack_chunk_alloc xmalloc
28#define obstack_chunk_free free
29
30/* Obstack used for allocating RTL objects.
31 Between functions, this is the permanent_obstack.
32 While parsing and expanding a function, this is maybepermanent_obstack
33 so we can save it if it is an inline function.
34 During optimization and output, this is function_obstack. */
35
36extern struct obstack *rtl_obstack;
37
38#if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT
39extern long atol();
40#endif
41\f
42/* Indexed by rtx code, gives number of operands for an rtx with that code.
43 Does NOT include rtx header data (code and links).
44 This array is initialized in init_rtl. */
45
46int rtx_length[NUM_RTX_CODE + 1];
47
48/* Indexed by rtx code, gives the name of that kind of rtx, as a C string. */
49
50#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) NAME ,
51
52char *rtx_name[] = {
53#include "rtl.def" /* rtl expressions are documented here */
54};
55
56#undef DEF_RTL_EXPR
57
58/* Indexed by machine mode, gives the name of that machine mode.
59 This name does not include the letters "mode". */
60
61#define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER) NAME,
62
63char *mode_name[(int) MAX_MACHINE_MODE] = {
64#include "machmode.def"
65
66#ifdef EXTRA_CC_MODES
67 EXTRA_CC_NAMES
68#endif
69
70};
71
72#undef DEF_MACHMODE
73
74/* Indexed by machine mode, gives the length of the mode, in bytes.
75 GET_MODE_CLASS uses this. */
76
77#define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER) CLASS,
78
79enum mode_class mode_class[(int) MAX_MACHINE_MODE] = {
80#include "machmode.def"
81};
82
83#undef DEF_MACHMODE
84
85/* Indexed by machine mode, gives the length of the mode, in bytes.
86 GET_MODE_SIZE uses this. */
87
88#define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER) SIZE,
89
90int mode_size[(int) MAX_MACHINE_MODE] = {
91#include "machmode.def"
92};
93
94#undef DEF_MACHMODE
95
96/* Indexed by machine mode, gives the length of the mode's subunit.
97 GET_MODE_UNIT_SIZE uses this. */
98
99#define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER) UNIT,
100
101int mode_unit_size[(int) MAX_MACHINE_MODE] = {
102#include "machmode.def" /* machine modes are documented here */
103};
104
105#undef DEF_MACHMODE
106
107/* Indexed by machine mode, gives next wider natural mode
108 (QI -> HI -> SI -> DI, etc.) Widening multiply instructions
109 use this. */
110
111#define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER) \
112 (enum machine_mode) WIDER,
113
114enum machine_mode mode_wider_mode[(int) MAX_MACHINE_MODE] = {
115#include "machmode.def" /* machine modes are documented here */
116};
117
118#undef DEF_MACHMODE
119
120/* Indexed by mode class, gives the narrowest mode for each class. */
121
122enum machine_mode class_narrowest_mode[(int) MAX_MODE_CLASS];
123
124/* Commonly used modes. */
125
126enum machine_mode byte_mode; /* Mode whose width is BITS_PER_UNIT */
127enum machine_mode word_mode; /* Mode whose width is BITS_PER_WORD */
128
129/* Indexed by rtx code, gives a sequence of operand-types for
130 rtx's of that code. The sequence is a C string in which
131 each character describes one operand. */
132
133char *rtx_format[] = {
134 /* "*" undefined.
135 can cause a warning message
136 "0" field is unused (or used in a phase-dependent manner)
137 prints nothing
138 "i" an integer
139 prints the integer
140 "n" like "i", but prints entries from `note_insn_name'
141 "w" an integer of width HOST_BITS_PER_WIDE_INT
142 prints the integer
143 "s" a pointer to a string
144 prints the string
145 "S" like "s", but optional:
146 the containing rtx may end before this operand
147 "e" a pointer to an rtl expression
148 prints the expression
149 "E" a pointer to a vector that points to a number of rtl expressions
150 prints a list of the rtl expressions
151 "V" like "E", but optional:
152 the containing rtx may end before this operand
153 "u" a pointer to another insn
154 prints the uid of the insn. */
155
156#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) FORMAT ,
157#include "rtl.def" /* rtl expressions are defined here */
158#undef DEF_RTL_EXPR
159};
160
161/* Indexed by rtx code, gives a character representing the "class" of
162 that rtx code. See rtl.def for documentation on the defined classes. */
163
164char rtx_class[] = {
165#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) CLASS,
166#include "rtl.def" /* rtl expressions are defined here */
167#undef DEF_RTL_EXPR
168};
169
170/* Names for kinds of NOTEs and REG_NOTEs. */
171
172char *note_insn_name[] = { "NOTE_INSN_FUNCTION_BEG", "NOTE_INSN_DELETED",
173 "NOTE_INSN_BLOCK_BEG", "NOTE_INSN_BLOCK_END",
174 "NOTE_INSN_LOOP_BEG", "NOTE_INSN_LOOP_END",
175 "NOTE_INSN_FUNCTION_END", "NOTE_INSN_SETJMP",
176 "NOTE_INSN_LOOP_CONT", "NOTE_INSN_LOOP_VTOP",
177 "NOTE_INSN_PROLOGUE_END", "NOTE_INSN_EPILOGUE_BEG",
178 "NOTE_INSN_DELETED_LABEL"};
179
180char *reg_note_name[] = { "", "REG_DEAD", "REG_INC", "REG_EQUIV", "REG_WAS_0",
181 "REG_EQUAL", "REG_RETVAL", "REG_LIBCALL",
182 "REG_NONNEG", "REG_NO_CONFLICT", "REG_UNUSED",
183 "REG_CC_SETTER", "REG_CC_USER", "REG_LABEL",
184 "REG_DEP_ANTI", "REG_DEP_OUTPUT" };
185
186/* Allocate an rtx vector of N elements.
187 Store the length, and initialize all elements to zero. */
188
189rtvec
190rtvec_alloc (n)
191 int n;
192{
193 rtvec rt;
194 int i;
195
196 rt = (rtvec) obstack_alloc (rtl_obstack,
197 sizeof (struct rtvec_def)
198 + (( n - 1) * sizeof (rtunion)));
199
200 /* clear out the vector */
201 PUT_NUM_ELEM(rt, n);
202 for (i=0; i < n; i++)
203 rt->elem[i].rtvec = NULL; /* @@ not portable due to rtunion */
204
205 return rt;
206}
207
208/* Allocate an rtx of code CODE. The CODE is stored in the rtx;
209 all the rest is initialized to zero. */
210
211rtx
212rtx_alloc (code)
213 RTX_CODE code;
214{
215 rtx rt;
216 register struct obstack *ob = rtl_obstack;
217 register int nelts = GET_RTX_LENGTH (code);
218 register int length = sizeof (struct rtx_def)
219 + (nelts - 1) * sizeof (rtunion);
220
221 /* This function is called more than any other in GCC,
222 so we manipulate the obstack directly.
223
224 Even though rtx objects are word aligned, we may be sharing an obstack
225 with tree nodes, which may have to be double-word aligned. So align
226 our length to the alignment mask in the obstack. */
227
228 length = (length + ob->alignment_mask) & ~ ob->alignment_mask;
229
230 if (ob->chunk_limit - ob->next_free < length)
231 _obstack_newchunk (ob, length);
232 rt = (rtx)ob->object_base;
233 ob->next_free += length;
234 ob->object_base = ob->next_free;
235
236 * (int *) rt = 0;
237 PUT_CODE (rt, code);
238
239 return rt;
240}
241\f
242/* Create a new copy of an rtx.
243 Recursively copies the operands of the rtx,
244 except for those few rtx codes that are sharable. */
245
246rtx
247copy_rtx (orig)
248 register rtx orig;
249{
250 register rtx copy;
251 register int i, j;
252 register RTX_CODE code;
253 register char *format_ptr;
254
255 code = GET_CODE (orig);
256
257 switch (code)
258 {
259 case REG:
260 case QUEUED:
261 case CONST_INT:
262 case CONST_DOUBLE:
263 case SYMBOL_REF:
264 case CODE_LABEL:
265 case PC:
266 case CC0:
267 return orig;
268 }
269
270 copy = rtx_alloc (code);
271 PUT_MODE (copy, GET_MODE (orig));
272 copy->in_struct = orig->in_struct;
273 copy->volatil = orig->volatil;
274 copy->unchanging = orig->unchanging;
275 copy->integrated = orig->integrated;
276
277 format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
278
279 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
280 {
281 switch (*format_ptr++)
282 {
283 case 'e':
284 XEXP (copy, i) = XEXP (orig, i);
285 if (XEXP (orig, i) != NULL)
286 XEXP (copy, i) = copy_rtx (XEXP (orig, i));
287 break;
288
289 case '0':
290 case 'u':
291 XEXP (copy, i) = XEXP (orig, i);
292 break;
293
294 case 'E':
295 case 'V':
296 XVEC (copy, i) = XVEC (orig, i);
297 if (XVEC (orig, i) != NULL)
298 {
299 XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
300 for (j = 0; j < XVECLEN (copy, i); j++)
301 XVECEXP (copy, i, j) = copy_rtx (XVECEXP (orig, i, j));
302 }
303 break;
304
305 case 'w':
306 XWINT (copy, i) = XWINT (orig, i);
307 break;
308
309 case 'i':
310 XINT (copy, i) = XINT (orig, i);
311 break;
312
313 case 's':
314 case 'S':
315 XSTR (copy, i) = XSTR (orig, i);
316 break;
317
318 default:
319 abort ();
320 }
321 }
322 return copy;
323}
324
325/* Similar to `copy_rtx' except that if MAY_SHARE is present, it is
326 placed in the result directly, rather than being copied. */
327
328rtx
329copy_most_rtx (orig, may_share)
330 register rtx orig;
331 register rtx may_share;
332{
333 register rtx copy;
334 register int i, j;
335 register RTX_CODE code;
336 register char *format_ptr;
337
338 if (orig == may_share)
339 return orig;
340
341 code = GET_CODE (orig);
342
343 switch (code)
344 {
345 case REG:
346 case QUEUED:
347 case CONST_INT:
348 case CONST_DOUBLE:
349 case SYMBOL_REF:
350 case CODE_LABEL:
351 case PC:
352 case CC0:
353 return orig;
354 }
355
356 copy = rtx_alloc (code);
357 PUT_MODE (copy, GET_MODE (orig));
358 copy->in_struct = orig->in_struct;
359 copy->volatil = orig->volatil;
360 copy->unchanging = orig->unchanging;
361 copy->integrated = orig->integrated;
362
363 format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
364
365 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
366 {
367 switch (*format_ptr++)
368 {
369 case 'e':
370 XEXP (copy, i) = XEXP (orig, i);
371 if (XEXP (orig, i) != NULL && XEXP (orig, i) != may_share)
372 XEXP (copy, i) = copy_most_rtx (XEXP (orig, i), may_share);
373 break;
374
375 case '0':
376 case 'u':
377 XEXP (copy, i) = XEXP (orig, i);
378 break;
379
380 case 'E':
381 case 'V':
382 XVEC (copy, i) = XVEC (orig, i);
383 if (XVEC (orig, i) != NULL)
384 {
385 XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
386 for (j = 0; j < XVECLEN (copy, i); j++)
387 XVECEXP (copy, i, j)
388 = copy_most_rtx (XVECEXP (orig, i, j), may_share);
389 }
390 break;
391
392 case 'w':
393 XWINT (copy, i) = XWINT (orig, i);
394 break;
395
396 case 'n':
397 case 'i':
398 XINT (copy, i) = XINT (orig, i);
399 break;
400
401 case 's':
402 case 'S':
403 XSTR (copy, i) = XSTR (orig, i);
404 break;
405
406 default:
407 abort ();
408 }
409 }
410 return copy;
411}
412\f
413/* Subroutines of read_rtx. */
414
415/* Dump code after printing a message. Used when read_rtx finds
416 invalid data. */
417
418static void
419dump_and_abort (expected_c, actual_c, infile)
420 int expected_c, actual_c;
421 FILE *infile;
422{
423 int c, i;
424
425 if (expected_c >= 0)
426 fprintf (stderr,
427 "Expected character %c. Found character %c.",
428 expected_c, actual_c);
429 fprintf (stderr, " At file position: %ld\n", ftell (infile));
430 fprintf (stderr, "Following characters are:\n\t");
431 for (i = 0; i < 200; i++)
432 {
433 c = getc (infile);
434 if (EOF == c) break;
435 putc (c, stderr);
436 }
437 fprintf (stderr, "Aborting.\n");
438 abort ();
439}
440
441/* Read chars from INFILE until a non-whitespace char
442 and return that. Comments, both Lisp style and C style,
443 are treated as whitespace.
444 Tools such as genflags use this function. */
445
446int
447read_skip_spaces (infile)
448 FILE *infile;
449{
450 register int c;
451 while (c = getc (infile))
452 {
453 if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
454 ;
455 else if (c == ';')
456 {
457 while ((c = getc (infile)) && c != '\n') ;
458 }
459 else if (c == '/')
460 {
461 register int prevc;
462 c = getc (infile);
463 if (c != '*')
464 dump_and_abort ('*', c, infile);
465
466 prevc = 0;
467 while (c = getc (infile))
468 {
469 if (prevc == '*' && c == '/')
470 break;
471 prevc = c;
472 }
473 }
474 else break;
475 }
476 return c;
477}
478
479/* Read an rtx code name into the buffer STR[].
480 It is terminated by any of the punctuation chars of rtx printed syntax. */
481
482static void
483read_name (str, infile)
484 char *str;
485 FILE *infile;
486{
487 register char *p;
488 register int c;
489
490 c = read_skip_spaces(infile);
491
492 p = str;
493 while (1)
494 {
495 if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
496 break;
497 if (c == ':' || c == ')' || c == ']' || c == '"' || c == '/'
498 || c == '(' || c == '[')
499 {
500 ungetc (c, infile);
501 break;
502 }
503 *p++ = c;
504 c = getc (infile);
505 }
506 if (p == str)
507 {
508 fprintf (stderr, "missing name or number");
509 dump_and_abort (-1, -1, infile);
510 }
511
512 *p = 0;
513}
514\f
515/* Read an rtx in printed representation from INFILE
516 and return an actual rtx in core constructed accordingly.
517 read_rtx is not used in the compiler proper, but rather in
518 the utilities gen*.c that construct C code from machine descriptions. */
519
520rtx
521read_rtx (infile)
522 FILE *infile;
523{
524 register int i, j, list_counter;
525 RTX_CODE tmp_code;
526 register char *format_ptr;
527 /* tmp_char is a buffer used for reading decimal integers
528 and names of rtx types and machine modes.
529 Therefore, 256 must be enough. */
530 char tmp_char[256];
531 rtx return_rtx;
532 register int c;
533 int tmp_int;
534 HOST_WIDE_INT tmp_wide;
535
536 /* Linked list structure for making RTXs: */
537 struct rtx_list
538 {
539 struct rtx_list *next;
540 rtx value; /* Value of this node... */
541 };
542
543 c = read_skip_spaces (infile); /* Should be open paren. */
544 if (c != '(')
545 dump_and_abort ('(', c, infile);
546
547 read_name (tmp_char, infile);
548
549 tmp_code = UNKNOWN;
550
551 for (i=0; i < NUM_RTX_CODE; i++) /* @@ might speed this search up */
552 {
553 if (!(strcmp (tmp_char, GET_RTX_NAME (i))))
554 {
555 tmp_code = (RTX_CODE) i; /* get value for name */
556 break;
557 }
558 }
559 if (tmp_code == UNKNOWN)
560 {
561 fprintf (stderr,
562 "Unknown rtx read in rtl.read_rtx(). Code name was %s .",
563 tmp_char);
564 }
565 /* (NIL) stands for an expression that isn't there. */
566 if (tmp_code == NIL)
567 {
568 /* Discard the closeparen. */
569 while ((c = getc (infile)) && c != ')');
570 return 0;
571 }
572
573 return_rtx = rtx_alloc (tmp_code); /* if we end up with an insn expression
574 then we free this space below. */
575 format_ptr = GET_RTX_FORMAT (GET_CODE (return_rtx));
576
577 /* If what follows is `: mode ', read it and
578 store the mode in the rtx. */
579
580 i = read_skip_spaces (infile);
581 if (i == ':')
582 {
583 register int k;
584 read_name (tmp_char, infile);
585 for (k = 0; k < NUM_MACHINE_MODES; k++)
586 if (!strcmp (GET_MODE_NAME (k), tmp_char))
587 break;
588
589 PUT_MODE (return_rtx, (enum machine_mode) k );
590 }
591 else
592 ungetc (i, infile);
593
594 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (return_rtx)); i++)
595 switch (*format_ptr++)
596 {
597 /* 0 means a field for internal use only.
598 Don't expect it to be present in the input. */
599 case '0':
600 break;
601
602 case 'e':
603 case 'u':
604 XEXP (return_rtx, i) = read_rtx (infile);
605 break;
606
607 case 'V':
608 /* 'V' is an optional vector: if a closeparen follows,
609 just store NULL for this element. */
610 c = read_skip_spaces (infile);
611 ungetc (c, infile);
612 if (c == ')')
613 {
614 XVEC (return_rtx, i) = 0;
615 break;
616 }
617 /* Now process the vector. */
618
619 case 'E':
620 {
621 register struct rtx_list *next_rtx, *rtx_list_link;
622 struct rtx_list *list_rtx;
623
624 c = read_skip_spaces (infile);
625 if (c != '[')
626 dump_and_abort ('[', c, infile);
627
628 /* add expressions to a list, while keeping a count */
629 next_rtx = NULL;
630 list_counter = 0;
631 while ((c = read_skip_spaces (infile)) && c != ']')
632 {
633 ungetc (c, infile);
634 list_counter++;
635 rtx_list_link = (struct rtx_list *)
636 alloca (sizeof (struct rtx_list));
637 rtx_list_link->value = read_rtx (infile);
638 if (next_rtx == 0)
639 list_rtx = rtx_list_link;
640 else
641 next_rtx->next = rtx_list_link;
642 next_rtx = rtx_list_link;
643 rtx_list_link->next = 0;
644 }
645 /* get vector length and allocate it */
646 XVEC (return_rtx, i) = (list_counter
647 ? rtvec_alloc (list_counter) : NULL_RTVEC);
648 if (list_counter > 0)
649 {
650 next_rtx = list_rtx;
651 for (j = 0; j < list_counter; j++,
652 next_rtx = next_rtx->next)
653 XVECEXP (return_rtx, i, j) = next_rtx->value;
654 }
655 /* close bracket gotten */
656 }
657 break;
658
659 case 'S':
660 /* 'S' is an optional string: if a closeparen follows,
661 just store NULL for this element. */
662 c = read_skip_spaces (infile);
663 ungetc (c, infile);
664 if (c == ')')
665 {
666 XSTR (return_rtx, i) = 0;
667 break;
668 }
669
670 case 's':
671 {
672 int saw_paren = 0;
673 register char *stringbuf;
674 int stringbufsize;
675
676 c = read_skip_spaces (infile);
677 if (c == '(')
678 {
679 saw_paren = 1;
680 c = read_skip_spaces (infile);
681 }
682 if (c != '"')
683 dump_and_abort ('"', c, infile);
684
685 while (1)
686 {
687 c = getc (infile); /* Read the string */
688 if (c == '\\')
689 {
690 c = getc (infile); /* Read the string */
691 /* \; makes stuff for a C string constant containing
692 newline and tab. */
693 if (c == ';')
694 {
695 obstack_grow (rtl_obstack, "\\n\\t", 4);
696 continue;
697 }
698 }
699 else if (c == '"')
700 break;
701
702 obstack_1grow (rtl_obstack, c);
703 }
704
705 obstack_1grow (rtl_obstack, 0);
706 stringbuf = (char *) obstack_finish (rtl_obstack);
707
708 if (saw_paren)
709 {
710 c = read_skip_spaces (infile);
711 if (c != ')')
712 dump_and_abort (')', c, infile);
713 }
714 XSTR (return_rtx, i) = stringbuf;
715 }
716 break;
717
718 case 'w':
719 read_name (tmp_char, infile);
720#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
721 tmp_wide = atoi (tmp_char);
722#else
723 tmp_wide = atol (tmp_char);
724#endif
725 XWINT (return_rtx, i) = tmp_wide;
726 break;
727
728 case 'i':
729 case 'n':
730 read_name (tmp_char, infile);
731 tmp_int = atoi (tmp_char);
732 XINT (return_rtx, i) = tmp_int;
733 break;
734
735 default:
736 fprintf (stderr,
737 "switch format wrong in rtl.read_rtx(). format was: %c.\n",
738 format_ptr[-1]);
739 fprintf (stderr, "\tfile position: %ld\n", ftell (infile));
740 abort ();
741 }
742
743 c = read_skip_spaces (infile);
744 if (c != ')')
745 dump_and_abort (')', c, infile);
746
747 return return_rtx;
748}
749\f
750/* This is called once per compilation, before any rtx's are constructed.
751 It initializes the vector `rtx_length', the extra CC modes, if any,
752 and computes certain commonly-used modes. */
753
754void
755init_rtl ()
756{
757 int min_class_size[(int) MAX_MODE_CLASS];
758 enum machine_mode mode;
759 int i;
760
761 for (i = 0; i < NUM_RTX_CODE; i++)
762 rtx_length[i] = strlen (rtx_format[i]);
763
764 /* Make CONST_DOUBLE bigger, if real values are bigger than
765 it normally expects to have room for.
766 Note that REAL_VALUE_TYPE is not defined by default,
767 since tree.h is not included. But the default dfn as `double'
768 would do no harm. */
769#ifdef REAL_VALUE_TYPE
770 i = sizeof (REAL_VALUE_TYPE) / sizeof (rtunion) + 2;
771 if (rtx_length[(int) CONST_DOUBLE] < i)
772 {
773 char *s = (char *) xmalloc (i + 1);
774 rtx_length[(int) CONST_DOUBLE] = i;
775 rtx_format[(int) CONST_DOUBLE] = s;
776 *s++ = 'e';
777 *s++ = '0';
778 /* Set the GET_RTX_FORMAT of CONST_DOUBLE to a string
779 of as many `i's as we now have elements. */
780 for (i = 0; i < rtx_length[(int) CONST_DOUBLE]; i++)
781 *s++ = 'w';
782 *s++ = 0;
783 }
784#endif
785
786#ifdef EXTRA_CC_MODES
787 for (i = (int) CCmode + 1; i < (int) MAX_MACHINE_MODE; i++)
788 {
789 mode_class[i] = MODE_CC;
790 mode_size[i] = mode_size[(int) CCmode];
791 mode_unit_size[i] = mode_unit_size[(int) CCmode];
792 mode_wider_mode[i - 1] = (enum machine_mode) i;
793 mode_wider_mode[i] = VOIDmode;
794 }
795#endif
796
797 /* Find the narrowest mode for each class and compute the word and byte
798 modes. */
799
800 for (i = 0; i < (int) MAX_MODE_CLASS; i++)
801 min_class_size[i] = 1000;
802
803 byte_mode = VOIDmode;
804 word_mode = VOIDmode;
805
806 for (mode = VOIDmode; (int) mode < (int) MAX_MACHINE_MODE;
807 mode = (enum machine_mode) ((int) mode + 1))
808 {
809 if (GET_MODE_SIZE (mode) < min_class_size[(int) GET_MODE_CLASS (mode)])
810 {
811 class_narrowest_mode[(int) GET_MODE_CLASS (mode)] = mode;
812 min_class_size[(int) GET_MODE_CLASS (mode)] = GET_MODE_SIZE (mode);
813 }
814 if (GET_MODE_CLASS (mode) == MODE_INT
815 && GET_MODE_BITSIZE (mode) == BITS_PER_UNIT
816 && byte_mode == VOIDmode)
817 byte_mode = mode;
818
819 if (GET_MODE_CLASS (mode) == MODE_INT
820 && GET_MODE_BITSIZE (mode) == BITS_PER_WORD
821 && word_mode == VOIDmode)
822 word_mode = mode;
823 }
824}
825\f
826#ifdef memset
827gcc_memset (dest, value, len)
828 char *dest;
829 int value;
830 int len;
831{
832 while (len-- > 0)
833 *dest++ = value;
834}
835#endif /* memset */