genemit.c 23.2 KB
Newer Older
Richard Kenner committed
1
/* Generate code from machine description to emit insns as rtl.
2
   Copyright (C) 1987, 1988, 1991, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
3
   2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
Richard Kenner committed
4

5
This file is part of GCC.
Richard Kenner committed
6

7 8
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
9
Software Foundation; either version 3, or (at your option) any later
10
version.
Richard Kenner committed
11

12 13 14 15
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.
Richard Kenner committed
16 17

You should have received a copy of the GNU General Public License
18 19
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */
Richard Kenner committed
20 21


22
#include "bconfig.h"
23
#include "system.h"
24 25
#include "coretypes.h"
#include "tm.h"
Richard Kenner committed
26
#include "rtl.h"
Zack Weinberg committed
27
#include "errors.h"
28
#include "read-md.h"
Clinton Popetz committed
29
#include "gensupport.h"
Richard Kenner committed
30 31 32 33 34 35


static int insn_code_number;
static int insn_index_number;

/* Data structure for recording the patterns of insns that have CLOBBERs.
36
   We use this to output a function that adds these CLOBBERs to a
Richard Kenner committed
37 38 39 40
   previously-allocated PARALLEL expression.  */

struct clobber_pat
{
41
  struct clobber_ent *insns;
Richard Kenner committed
42 43 44
  rtx pattern;
  int first_clobber;
  struct clobber_pat *next;
45
  int has_hard_reg;
Richard Kenner committed
46 47
} *clobber_list;

48 49 50 51 52 53 54 55
/* Records one insn that uses the clobber list.  */

struct clobber_ent
{
  int code_number;		/* Counts only insns.  */
  struct clobber_ent *next;
};

56 57 58 59 60 61 62 63 64
static void print_code			(RTX_CODE);
static void gen_exp			(rtx, enum rtx_code, char *);
static void gen_insn			(rtx, int);
static void gen_expand			(rtx);
static void gen_split			(rtx);
static void output_add_clobbers		(void);
static void output_added_clobbers_hard_reg_p (void);
static void gen_rtx_scratch		(rtx, enum rtx_code);
static void output_peephole2_scratches	(rtx);
65 66


Richard Kenner committed
67
static void
68
print_code (RTX_CODE code)
Richard Kenner committed
69
{
70
  const char *p1;
Richard Kenner committed
71
  for (p1 = GET_RTX_NAME (code); *p1; p1++)
72
    putchar (TOUPPER(*p1));
Richard Kenner committed
73 74
}

75
static void
76
gen_rtx_scratch (rtx x, enum rtx_code subroutine_type)
77 78 79 80 81 82 83 84 85 86 87
{
  if (subroutine_type == DEFINE_PEEPHOLE2)
    {
      printf ("operand%d", XINT (x, 0));
    }
  else
    {
      printf ("gen_rtx_SCRATCH (%smode)", GET_MODE_NAME (GET_MODE (x)));
    }
}

Richard Kenner committed
88 89 90 91
/* Print a C expression to construct an RTX just like X,
   substituting any operand references appearing within.  */

static void
92
gen_exp (rtx x, enum rtx_code subroutine_type, char *used)
Richard Kenner committed
93
{
94 95 96 97
  RTX_CODE code;
  int i;
  int len;
  const char *fmt;
Richard Kenner committed
98 99 100

  if (x == 0)
    {
Richard Stallman committed
101
      printf ("NULL_RTX");
Richard Kenner committed
102 103 104 105 106 107 108 109 110
      return;
    }

  code = GET_CODE (x);

  switch (code)
    {
    case MATCH_OPERAND:
    case MATCH_DUP:
111 112 113 114 115 116 117 118 119
      if (used)
	{
	  if (used[XINT (x, 0)])
	    {
	      printf ("copy_rtx (operand%d)", XINT (x, 0));
	      return;
	    }
	  used[XINT (x, 0)] = 1;
	}
Richard Kenner committed
120 121 122 123
      printf ("operand%d", XINT (x, 0));
      return;

    case MATCH_OP_DUP:
124 125 126 127
      printf ("gen_rtx_fmt_");
      for (i = 0; i < XVECLEN (x, 1); i++)
	printf ("e");
      printf (" (GET_CODE (operand%d), ", XINT (x, 0));
128 129 130 131
      if (GET_MODE (x) == VOIDmode)
	printf ("GET_MODE (operand%d)", XINT (x, 0));
      else
	printf ("%smode", GET_MODE_NAME (GET_MODE (x)));
Richard Kenner committed
132 133 134
      for (i = 0; i < XVECLEN (x, 1); i++)
	{
	  printf (",\n\t\t");
135
	  gen_exp (XVECEXP (x, 1, i), subroutine_type, used);
Richard Kenner committed
136 137 138 139 140
	}
      printf (")");
      return;

    case MATCH_OPERATOR:
141 142 143 144
      printf ("gen_rtx_fmt_");
      for (i = 0; i < XVECLEN (x, 2); i++)
	printf ("e");
      printf (" (GET_CODE (operand%d)", XINT (x, 0));
Richard Kenner committed
145 146 147 148
      printf (", %smode", GET_MODE_NAME (GET_MODE (x)));
      for (i = 0; i < XVECLEN (x, 2); i++)
	{
	  printf (",\n\t\t");
149
	  gen_exp (XVECEXP (x, 2, i), subroutine_type, used);
Richard Kenner committed
150 151 152 153 154
	}
      printf (")");
      return;

    case MATCH_PARALLEL:
155
    case MATCH_PAR_DUP:
Richard Kenner committed
156 157 158 159
      printf ("operand%d", XINT (x, 0));
      return;

    case MATCH_SCRATCH:
160
      gen_rtx_scratch (x, subroutine_type);
Richard Kenner committed
161 162 163 164 165 166 167 168
      return;

    case ADDRESS:
      fatal ("ADDRESS expression code used in named instruction pattern");

    case PC:
      printf ("pc_rtx");
      return;
169 170 171
    case RETURN:
      printf ("ret_rtx");
      return;
172 173 174 175 176 177 178 179
    case CLOBBER:
      if (REG_P (XEXP (x, 0)))
	{
	  printf ("gen_hard_reg_clobber (%smode, %i)", GET_MODE_NAME (GET_MODE (XEXP (x, 0))),
			  			     REGNO (XEXP (x, 0)));
	  return;
	}
      break;
Richard Kenner committed
180 181 182 183 184 185 186

    case CC0:
      printf ("cc0_rtx");
      return;

    case CONST_INT:
      if (INTVAL (x) == 0)
Richard Stallman committed
187 188 189 190 191
	printf ("const0_rtx");
      else if (INTVAL (x) == 1)
	printf ("const1_rtx");
      else if (INTVAL (x) == -1)
	printf ("constm1_rtx");
192 193 194 195
      else if (-MAX_SAVED_CONST_INT <= INTVAL (x)
	  && INTVAL (x) <= MAX_SAVED_CONST_INT)
	printf ("const_int_rtx[MAX_SAVED_CONST_INT + (%d)]",
		(int) INTVAL (x));
Richard Stallman committed
196 197 198
      else if (INTVAL (x) == STORE_FLAG_VALUE)
	printf ("const_true_rtx");
      else
199 200
	{
	  printf ("GEN_INT (");
201
	  printf (HOST_WIDE_INT_PRINT_DEC_C, INTVAL (x));
202 203
	  printf (")");
	}
Richard Stallman committed
204 205 206
      return;

    case CONST_DOUBLE:
207
    case CONST_FIXED:
Richard Stallman committed
208 209
      /* These shouldn't be written in MD files.  Instead, the appropriate
	 routines in varasm.c should be called.  */
210
      gcc_unreachable ();
211 212 213

    default:
      break;
Richard Kenner committed
214 215
    }

216
  printf ("gen_rtx_");
Richard Kenner committed
217
  print_code (code);
218
  printf (" (%smode", GET_MODE_NAME (GET_MODE (x)));
Richard Kenner committed
219 220 221 222 223 224 225

  fmt = GET_RTX_FORMAT (code);
  len = GET_RTX_LENGTH (code);
  for (i = 0; i < len; i++)
    {
      if (fmt[i] == '0')
	break;
226
      printf (",\n\t");
227
      switch (fmt[i])
Richard Kenner committed
228
	{
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
	case 'e': case 'u':
	  gen_exp (XEXP (x, i), subroutine_type, used);
	  break;

	case 'i':
	  printf ("%u", XINT (x, i));
	  break;

	case 's':
	  printf ("\"%s\"", XSTR (x, i));
	  break;

	case 'E':
	  {
	    int j;
	    printf ("gen_rtvec (%d", XVECLEN (x, i));
	    for (j = 0; j < XVECLEN (x, i); j++)
	      {
		printf (",\n\t\t");
		gen_exp (XVECEXP (x, i, j), subroutine_type, used);
	      }
	    printf (")");
	    break;
	  }

	default:
	  gcc_unreachable ();
Richard Kenner committed
256 257 258
	}
    }
  printf (")");
259
}
Richard Kenner committed
260 261 262 263

/* Generate the `gen_...' function for a DEFINE_INSN.  */

static void
264
gen_insn (rtx insn, int lineno)
Richard Kenner committed
265
{
266
  struct pattern_stats stats;
267
  int i;
Richard Kenner committed
268 269 270

  /* See if the pattern for this insn ends with a group of CLOBBERs of (hard)
     registers or MATCH_SCRATCHes.  If so, store away the information for
Mike Stump committed
271
     later.  */
Richard Kenner committed
272 273 274

  if (XVEC (insn, 1))
    {
275 276
      int has_hard_reg = 0;

Richard Kenner committed
277
      for (i = XVECLEN (insn, 1) - 1; i > 0; i--)
278 279 280 281
	{
	  if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER)
	    break;

282
	  if (REG_P (XEXP (XVECEXP (insn, 1, i), 0)))
283 284 285 286
	    has_hard_reg = 1;
	  else if (GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != MATCH_SCRATCH)
	    break;
	}
Richard Kenner committed
287 288 289

      if (i != XVECLEN (insn, 1) - 1)
	{
290
	  struct clobber_pat *p;
291
	  struct clobber_ent *link = XNEW (struct clobber_ent);
292
	  int j;
293 294 295 296 297 298 299 300 301 302 303 304 305 306

	  link->code_number = insn_code_number;

	  /* See if any previous CLOBBER_LIST entry is the same as this
	     one.  */

	  for (p = clobber_list; p; p = p->next)
	    {
	      if (p->first_clobber != i + 1
		  || XVECLEN (p->pattern, 1) != XVECLEN (insn, 1))
		continue;

	      for (j = i + 1; j < XVECLEN (insn, 1); j++)
		{
307 308
		  rtx old_rtx = XEXP (XVECEXP (p->pattern, 1, j), 0);
		  rtx new_rtx = XEXP (XVECEXP (insn, 1, j), 0);
309

310
		  /* OLD and NEW_INSN are the same if both are to be a SCRATCH
311
		     of the same mode,
312
		     or if both are registers of the same mode and number.  */
313 314 315 316 317
		  if (! (GET_MODE (old_rtx) == GET_MODE (new_rtx)
			 && ((GET_CODE (old_rtx) == MATCH_SCRATCH
			      && GET_CODE (new_rtx) == MATCH_SCRATCH)
			     || (REG_P (old_rtx) && REG_P (new_rtx)
				 && REGNO (old_rtx) == REGNO (new_rtx)))))
318 319
		    break;
		}
320

321 322 323 324 325 326
	      if (j == XVECLEN (insn, 1))
		break;
	    }

	  if (p == 0)
	    {
327
	      p = XNEW (struct clobber_pat);
328

329 330 331 332
	      p->insns = 0;
	      p->pattern = insn;
	      p->first_clobber = i + 1;
	      p->next = clobber_list;
333
	      p->has_hard_reg = has_hard_reg;
334 335 336 337 338
	      clobber_list = p;
	    }

	  link->next = p->insns;
	  p->insns = link;
Richard Kenner committed
339 340 341
	}
    }

342 343 344 345
  /* Don't mention instructions whose names are the null string
     or begin with '*'.  They are in the machine description just
     to be recognized.  */
  if (XSTR (insn, 0)[0] == 0 || XSTR (insn, 0)[0] == '*')
Richard Kenner committed
346 347
    return;

348
  printf ("/* %s:%d */\n", read_md_filename, lineno);
349

350
  /* Find out how many operands this function has.  */
351 352
  get_pattern_stats (&stats, XVEC (insn, 1));
  if (stats.max_dup_opno > stats.max_opno)
Richard Kenner committed
353 354 355 356
    fatal ("match_dup operand number has no match_operand");

  /* Output the function name and argument declarations.  */
  printf ("rtx\ngen_%s (", XSTR (insn, 0));
357 358
  if (stats.num_generator_args)
    for (i = 0; i < stats.num_generator_args; i++)
359 360 361 362 363 364
      if (i)
	printf (",\n\trtx operand%d ATTRIBUTE_UNUSED", i);
      else
	printf ("rtx operand%d ATTRIBUTE_UNUSED", i);
  else
    printf ("void");
Richard Kenner committed
365 366 367
  printf (")\n");
  printf ("{\n");

368
  /* Output code to construct and return the rtl for the instruction body.  */
Richard Kenner committed
369 370 371 372

  if (XVECLEN (insn, 1) == 1)
    {
      printf ("  return ");
373
      gen_exp (XVECEXP (insn, 1, 0), DEFINE_INSN, NULL);
Richard Kenner committed
374 375 376 377
      printf (";\n}\n\n");
    }
  else
    {
378
      char *used = XCNEWVEC (char, stats.num_generator_args);
379

Jeff Law committed
380 381 382
      printf ("  return gen_rtx_PARALLEL (VOIDmode, gen_rtvec (%d",
	      XVECLEN (insn, 1));

Richard Kenner committed
383 384 385
      for (i = 0; i < XVECLEN (insn, 1); i++)
	{
	  printf (",\n\t\t");
386
	  gen_exp (XVECEXP (insn, 1, i), DEFINE_INSN, used);
Richard Kenner committed
387 388
	}
      printf ("));\n}\n\n");
389
      XDELETEVEC (used);
Richard Kenner committed
390 391 392 393 394 395
    }
}

/* Generate the `gen_...' function for a DEFINE_EXPAND.  */

static void
396
gen_expand (rtx expand)
Richard Kenner committed
397
{
398
  struct pattern_stats stats;
399
  int i;
400
  char *used;
Richard Kenner committed
401 402 403 404 405 406

  if (strlen (XSTR (expand, 0)) == 0)
    fatal ("define_expand lacks a name");
  if (XVEC (expand, 1) == 0)
    fatal ("define_expand for %s lacks a pattern", XSTR (expand, 0));

407
  /* Find out how many operands this function has.  */
408
  get_pattern_stats (&stats, XVEC (expand, 1));
Richard Kenner committed
409 410 411

  /* Output the function name and argument declarations.  */
  printf ("rtx\ngen_%s (", XSTR (expand, 0));
412 413
  if (stats.num_generator_args)
    for (i = 0; i < stats.num_generator_args; i++)
414 415 416 417 418 419
      if (i)
	printf (",\n\trtx operand%d", i);
      else
	printf ("rtx operand%d", i);
  else
    printf ("void");
Richard Kenner committed
420 421 422 423 424 425 426
  printf (")\n");
  printf ("{\n");

  /* If we don't have any C code to write, only one insn is being written,
     and no MATCH_DUPs are present, we can just return the desired insn
     like we do for a DEFINE_INSN.  This saves memory.  */
  if ((XSTR (expand, 3) == 0 || *XSTR (expand, 3) == '\0')
427
      && stats.max_opno >= stats.max_dup_opno
Richard Kenner committed
428 429 430
      && XVECLEN (expand, 1) == 1)
    {
      printf ("  return ");
431
      gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL);
Richard Kenner committed
432 433 434 435 436 437
      printf (";\n}\n\n");
      return;
    }

  /* For each operand referred to only with MATCH_DUPs,
     make a local variable.  */
438
  for (i = stats.num_generator_args; i <= stats.max_dup_opno; i++)
Richard Kenner committed
439
    printf ("  rtx operand%d;\n", i);
440
  for (; i <= stats.max_scratch_opno; i++)
441
    printf ("  rtx operand%d ATTRIBUTE_UNUSED;\n", i);
Richard Kenner committed
442 443 444 445 446 447 448 449 450 451 452
  printf ("  rtx _val = 0;\n");
  printf ("  start_sequence ();\n");

  /* The fourth operand of DEFINE_EXPAND is some code to be executed
     before the actual construction.
     This code expects to refer to `operands'
     just as the output-code in a DEFINE_INSN does,
     but here `operands' is an automatic array.
     So copy the operand values there before executing it.  */
  if (XSTR (expand, 3) && *XSTR (expand, 3))
    {
453
      printf ("  {\n");
454 455 456
      if (stats.num_operand_vars > 0)
	printf ("    rtx operands[%d];\n", stats.num_operand_vars);

Richard Kenner committed
457
      /* Output code to copy the arguments into `operands'.  */
458
      for (i = 0; i < stats.num_generator_args; i++)
459
	printf ("    operands[%d] = operand%d;\n", i, i);
Richard Kenner committed
460 461 462

      /* Output the special code to be executed before the sequence
	 is generated.  */
463
      print_md_ptr_loc (XSTR (expand, 3));
Richard Kenner committed
464 465 466 467 468 469
      printf ("%s\n", XSTR (expand, 3));

      /* Output code to copy the arguments back out of `operands'
	 (unless we aren't going to use them at all).  */
      if (XVEC (expand, 1) != 0)
	{
470
	  for (i = 0; i < stats.num_operand_vars; i++)
471 472 473 474
	    {
	      printf ("    operand%d = operands[%d];\n", i, i);
	      printf ("    (void) operand%d;\n", i);
	    }
Richard Kenner committed
475
	}
476
      printf ("  }\n");
Richard Kenner committed
477 478 479 480 481 482
    }

  /* Output code to construct the rtl for the instruction bodies.
     Use emit_insn to add them to the sequence being accumulated.
     But don't do this if the user's code has set `no_more' nonzero.  */

483
  used = XCNEWVEC (char, stats.num_operand_vars);
484

Richard Kenner committed
485 486 487 488 489
  for (i = 0; i < XVECLEN (expand, 1); i++)
    {
      rtx next = XVECEXP (expand, 1, i);
      if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC)
	  || (GET_CODE (next) == PARALLEL
490 491 492
	      && ((GET_CODE (XVECEXP (next, 0, 0)) == SET
		   && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
		  || GET_CODE (XVECEXP (next, 0, 0)) == RETURN))
Richard Kenner committed
493 494 495 496 497 498 499 500 501 502
	  || GET_CODE (next) == RETURN)
	printf ("  emit_jump_insn (");
      else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
	       || GET_CODE (next) == CALL
	       || (GET_CODE (next) == PARALLEL
		   && GET_CODE (XVECEXP (next, 0, 0)) == SET
		   && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL)
	       || (GET_CODE (next) == PARALLEL
		   && GET_CODE (XVECEXP (next, 0, 0)) == CALL))
	printf ("  emit_call_insn (");
503
      else if (LABEL_P (next))
Richard Kenner committed
504 505
	printf ("  emit_label (");
      else if (GET_CODE (next) == MATCH_OPERAND
506
	       || GET_CODE (next) == MATCH_DUP
Richard Kenner committed
507 508
	       || GET_CODE (next) == MATCH_OPERATOR
	       || GET_CODE (next) == MATCH_OP_DUP
509 510
	       || GET_CODE (next) == MATCH_PARALLEL
	       || GET_CODE (next) == MATCH_PAR_DUP
Richard Kenner committed
511 512 513 514
	       || GET_CODE (next) == PARALLEL)
	printf ("  emit (");
      else
	printf ("  emit_insn (");
515
      gen_exp (next, DEFINE_EXPAND, used);
Richard Kenner committed
516 517 518 519 520 521
      printf (");\n");
      if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC
	  && GET_CODE (SET_SRC (next)) == LABEL_REF)
	printf ("  emit_barrier ();");
    }

522 523
  XDELETEVEC (used);

524
  /* Call `get_insns' to extract the list of all the
Richard Kenner committed
525 526
     insns emitted within this gen_... function.  */

527
  printf ("  _val = get_insns ();\n");
Richard Kenner committed
528 529 530 531
  printf ("  end_sequence ();\n");
  printf ("  return _val;\n}\n\n");
}

532
/* Like gen_expand, but generates insns resulting from splitting SPLIT.  */
Mike Stump committed
533

Richard Kenner committed
534
static void
535
gen_split (rtx split)
Richard Kenner committed
536
{
537
  struct pattern_stats stats;
538
  int i;
539 540
  const char *const name =
    ((GET_CODE (split) == DEFINE_PEEPHOLE2) ? "peephole2" : "split");
541
  const char *unused;
542
  char *used;
543

Richard Kenner committed
544
  if (XVEC (split, 0) == 0)
545 546
    fatal ("define_%s (definition %d) lacks a pattern", name,
	   insn_index_number);
Richard Kenner committed
547
  else if (XVEC (split, 2) == 0)
548
    fatal ("define_%s (definition %d) lacks a replacement pattern", name,
549
	   insn_index_number);
Richard Kenner committed
550 551 552

  /* Find out how many operands this function has.  */

553 554 555
  get_pattern_stats (&stats, XVEC (split, 2));
  unused = (stats.num_operand_vars == 0 ? " ATTRIBUTE_UNUSED" : "");
  used = XCNEWVEC (char, stats.num_operand_vars);
Richard Kenner committed
556

557 558 559
  /* Output the prototype, function name and argument declarations.  */
  if (GET_CODE (split) == DEFINE_PEEPHOLE2)
    {
560
      printf ("extern rtx gen_%s_%d (rtx, rtx *);\n",
561
	      name, insn_code_number);
562 563
      printf ("rtx\ngen_%s_%d (rtx curr_insn ATTRIBUTE_UNUSED, rtx *operands%s)\n",
	      name, insn_code_number, unused);
564 565 566
    }
  else
    {
567
      printf ("extern rtx gen_split_%d (rtx, rtx *);\n", insn_code_number);
568
      printf ("rtx\ngen_split_%d (rtx curr_insn ATTRIBUTE_UNUSED, rtx *operands%s)\n",
569
	      insn_code_number, unused);
570
    }
Richard Kenner committed
571 572 573
  printf ("{\n");

  /* Declare all local variables.  */
574
  for (i = 0; i < stats.num_operand_vars; i++)
Richard Kenner committed
575
    printf ("  rtx operand%d;\n", i);
576
  printf ("  rtx _val = 0;\n");
577 578 579 580

  if (GET_CODE (split) == DEFINE_PEEPHOLE2)
    output_peephole2_scratches (split);

Richard Kenner committed
581 582 583 584 585 586
  printf ("  start_sequence ();\n");

  /* The fourth operand of DEFINE_SPLIT is some code to be executed
     before the actual construction.  */

  if (XSTR (split, 3))
587
    {
588
      print_md_ptr_loc (XSTR (split, 3));
589 590
      printf ("%s\n", XSTR (split, 3));
    }
Richard Kenner committed
591 592

  /* Output code to copy the arguments back out of `operands'  */
593
  for (i = 0; i < stats.num_operand_vars; i++)
594 595 596 597
    {
      printf ("  operand%d = operands[%d];\n", i, i);
      printf ("  (void) operand%d;\n", i);
    }
Richard Kenner committed
598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619

  /* Output code to construct the rtl for the instruction bodies.
     Use emit_insn to add them to the sequence being accumulated.
     But don't do this if the user's code has set `no_more' nonzero.  */

  for (i = 0; i < XVECLEN (split, 2); i++)
    {
      rtx next = XVECEXP (split, 2, i);
      if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC)
	  || (GET_CODE (next) == PARALLEL
	      && GET_CODE (XVECEXP (next, 0, 0)) == SET
	      && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
	  || GET_CODE (next) == RETURN)
	printf ("  emit_jump_insn (");
      else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
	       || GET_CODE (next) == CALL
	       || (GET_CODE (next) == PARALLEL
		   && GET_CODE (XVECEXP (next, 0, 0)) == SET
		   && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL)
	       || (GET_CODE (next) == PARALLEL
		   && GET_CODE (XVECEXP (next, 0, 0)) == CALL))
	printf ("  emit_call_insn (");
620
      else if (LABEL_P (next))
Richard Kenner committed
621 622 623 624 625 626 627 628 629 630
	printf ("  emit_label (");
      else if (GET_CODE (next) == MATCH_OPERAND
	       || GET_CODE (next) == MATCH_OPERATOR
	       || GET_CODE (next) == MATCH_PARALLEL
	       || GET_CODE (next) == MATCH_OP_DUP
	       || GET_CODE (next) == MATCH_DUP
	       || GET_CODE (next) == PARALLEL)
	printf ("  emit (");
      else
	printf ("  emit_insn (");
631
      gen_exp (next, GET_CODE (split), used);
Richard Kenner committed
632 633 634 635 636 637
      printf (");\n");
      if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC
	  && GET_CODE (SET_SRC (next)) == LABEL_REF)
	printf ("  emit_barrier ();");
    }

638
  /* Call `get_insns' to make a list of all the
Richard Kenner committed
639 640
     insns emitted within this gen_... function.  */

641
  printf ("  _val = get_insns ();\n");
Richard Kenner committed
642 643
  printf ("  end_sequence ();\n");
  printf ("  return _val;\n}\n\n");
644 645

  free (used);
Richard Kenner committed
646 647 648 649 650 651 652
}

/* Write a function, `add_clobbers', that is given a PARALLEL of sufficient
   size for the insn and an INSN_CODE, and inserts the required CLOBBERs at
   the end of the vector.  */

static void
653
output_add_clobbers (void)
Richard Kenner committed
654 655
{
  struct clobber_pat *clobber;
656
  struct clobber_ent *ent;
Richard Kenner committed
657 658
  int i;

659
  printf ("\n\nvoid\nadd_clobbers (rtx pattern ATTRIBUTE_UNUSED, int insn_code_number)\n");
Richard Kenner committed
660 661 662 663 664 665
  printf ("{\n");
  printf ("  switch (insn_code_number)\n");
  printf ("    {\n");

  for (clobber = clobber_list; clobber; clobber = clobber->next)
    {
666 667
      for (ent = clobber->insns; ent; ent = ent->next)
	printf ("    case %d:\n", ent->code_number);
Richard Kenner committed
668 669 670 671

      for (i = clobber->first_clobber; i < XVECLEN (clobber->pattern, 1); i++)
	{
	  printf ("      XVECEXP (pattern, 0, %d) = ", i);
672
	  gen_exp (XVECEXP (clobber->pattern, 1, i),
673
		   GET_CODE (clobber->pattern), NULL);
Richard Kenner committed
674 675 676
	  printf (";\n");
	}

677
      printf ("      break;\n\n");
Richard Kenner committed
678 679 680
    }

  printf ("    default:\n");
681
  printf ("      gcc_unreachable ();\n");
Richard Kenner committed
682 683 684 685
  printf ("    }\n");
  printf ("}\n");
}

686 687 688 689
/* Write a function, `added_clobbers_hard_reg_p' that is given an insn_code
   number that will have clobbers added (as indicated by `recog') and returns
   1 if those include a clobber of a hard reg or 0 if all of them just clobber
   SCRATCH.  */
690 691

static void
692
output_added_clobbers_hard_reg_p (void)
693 694 695
{
  struct clobber_pat *clobber;
  struct clobber_ent *ent;
696
  int clobber_p, used;
697

698
  printf ("\n\nint\nadded_clobbers_hard_reg_p (int insn_code_number)\n");
699 700 701 702 703 704
  printf ("{\n");
  printf ("  switch (insn_code_number)\n");
  printf ("    {\n");

  for (clobber_p = 0; clobber_p <= 1; clobber_p++)
    {
705
      used = 0;
706 707 708
      for (clobber = clobber_list; clobber; clobber = clobber->next)
	if (clobber->has_hard_reg == clobber_p)
	  for (ent = clobber->insns; ent; ent = ent->next)
709 710 711 712
	    {
	      printf ("    case %d:\n", ent->code_number);
	      used++;
	    }
713

714 715
      if (used)
	printf ("      return %d;\n\n", clobber_p);
716 717 718
    }

  printf ("    default:\n");
719
  printf ("      gcc_unreachable ();\n");
720 721 722 723
  printf ("    }\n");
  printf ("}\n");
}

724
/* Generate code to invoke find_free_register () as needed for the
725
   scratch registers used by the peephole2 pattern in SPLIT.  */
726 727

static void
728
output_peephole2_scratches (rtx split)
729 730 731
{
  int i;
  int insn_nr = 0;
732
  bool first = true;
733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749

  for (i = 0; i < XVECLEN (split, 0); i++)
    {
      rtx elt = XVECEXP (split, 0, i);
      if (GET_CODE (elt) == MATCH_SCRATCH)
	{
	  int last_insn_nr = insn_nr;
	  int cur_insn_nr = insn_nr;
	  int j;
	  for (j = i + 1; j < XVECLEN (split, 0); j++)
	    if (GET_CODE (XVECEXP (split, 0, j)) == MATCH_DUP)
	      {
		if (XINT (XVECEXP (split, 0, j), 0) == XINT (elt, 0))
		  last_insn_nr = cur_insn_nr;
	      }
	    else if (GET_CODE (XVECEXP (split, 0, j)) != MATCH_SCRATCH)
	      cur_insn_nr++;
750

751 752 753 754 755 756 757
	  if (first)
	    {
	      printf ("  HARD_REG_SET _regs_allocated;\n");
	      printf ("  CLEAR_HARD_REG_SET (_regs_allocated);\n");
	      first = false;
	    }

758
	  printf ("  if ((operands[%d] = peep2_find_free_register (%d, %d, \"%s\", %smode, &_regs_allocated)) == NULL_RTX)\n\
759
    return NULL;\n",
760
		  XINT (elt, 0),
761
		  insn_nr, last_insn_nr,
762 763 764 765 766 767 768 769
		  XSTR (elt, 1),
		  GET_MODE_NAME (GET_MODE (elt)));

	}
      else if (GET_CODE (elt) != MATCH_DUP)
	insn_nr++;
    }
}
Richard Kenner committed
770 771

int
772
main (int argc, char **argv)
Richard Kenner committed
773 774 775
{
  rtx desc;

Zack Weinberg committed
776
  progname = "genemit";
Richard Kenner committed
777

778
  if (!init_rtx_reader_args (argc, argv))
Clinton Popetz committed
779
    return (FATAL_EXIT_CODE);
Richard Kenner committed
780 781 782 783 784 785 786 787 788 789 790

  /* Assign sequential codes to all entries in the machine description
     in parallel with the tables in insn-output.c.  */

  insn_code_number = 0;
  insn_index_number = 0;

  printf ("/* Generated automatically by the program `genemit'\n\
from the machine description file `md'.  */\n\n");

  printf ("#include \"config.h\"\n");
791
  printf ("#include \"system.h\"\n");
792 793
  printf ("#include \"coretypes.h\"\n");
  printf ("#include \"tm.h\"\n");
Richard Kenner committed
794
  printf ("#include \"rtl.h\"\n");
795
  printf ("#include \"tm_p.h\"\n");
796
  printf ("#include \"function.h\"\n");
Richard Kenner committed
797
  printf ("#include \"expr.h\"\n");
798
  printf ("#include \"optabs.h\"\n");
799
  printf ("#include \"dfp.h\"\n");
800
  printf ("#include \"flags.h\"\n");
Richard Kenner committed
801
  printf ("#include \"output.h\"\n");
Kaveh R. Ghazi committed
802
  printf ("#include \"insn-config.h\"\n");
803
  printf ("#include \"hard-reg-set.h\"\n");
804
  printf ("#include \"recog.h\"\n");
805
  printf ("#include \"resource.h\"\n");
806
  printf ("#include \"reload.h\"\n");
807
  printf ("#include \"diagnostic-core.h\"\n");
808
  printf ("#include \"regs.h\"\n");
809
  printf ("#include \"tm-constrs.h\"\n");
810 811
  printf ("#include \"ggc.h\"\n");
  printf ("#include \"basic-block.h\"\n");
812
  printf ("#include \"integrate.h\"\n\n");
813
  printf ("#define FAIL return (end_sequence (), _val)\n");
814
  printf ("#define DONE return (_val = get_insns (), end_sequence (), _val)\n\n");
Richard Kenner committed
815 816 817 818 819

  /* Read the machine description.  */

  while (1)
    {
Clinton Popetz committed
820
      int line_no;
Richard Kenner committed
821

Clinton Popetz committed
822 823 824
      desc = read_md_rtx (&line_no, &insn_code_number);
      if (desc == NULL)
	break;
825

Clinton Popetz committed
826
      switch (GET_CODE (desc))
Richard Kenner committed
827
	{
828 829 830 831 832
	case DEFINE_INSN:
	  gen_insn (desc, line_no);
	  break;

	case DEFINE_EXPAND:
833
	  printf ("/* %s:%d */\n", read_md_filename, line_no);
834 835 836 837
	  gen_expand (desc);
	  break;

	case DEFINE_SPLIT:
838
	  printf ("/* %s:%d */\n", read_md_filename, line_no);
839 840 841 842
	  gen_split (desc);
	  break;

	case DEFINE_PEEPHOLE2:
843
	  printf ("/* %s:%d */\n", read_md_filename, line_no);
844 845 846 847 848 849
	  gen_split (desc);
	  break;

	default:
	  break;
	}
Richard Kenner committed
850 851 852
      ++insn_index_number;
    }

853 854
  /* Write out the routines to add CLOBBERs to a pattern and say whether they
     clobber a hard reg.  */
Richard Kenner committed
855
  output_add_clobbers ();
856
  output_added_clobbers_hard_reg_p ();
Richard Kenner committed
857 858

  fflush (stdout);
859
  return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
Richard Kenner committed
860
}