| 1 |
684 |
jeremybenn |
/* 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.
|
| 4 |
|
|
|
| 5 |
|
|
This file is part of GCC.
|
| 6 |
|
|
|
| 7 |
|
|
GCC is free software; you can redistribute it and/or modify it under
|
| 8 |
|
|
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.
|
| 11 |
|
|
|
| 12 |
|
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
| 13 |
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
| 14 |
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
| 15 |
|
|
for more details.
|
| 16 |
|
|
|
| 17 |
|
|
You should have received a copy of the GNU General Public License
|
| 18 |
|
|
along with GCC; see the file COPYING3. If not see
|
| 19 |
|
|
<http://www.gnu.org/licenses/>. */
|
| 20 |
|
|
|
| 21 |
|
|
|
| 22 |
|
|
#include "bconfig.h"
|
| 23 |
|
|
#include "system.h"
|
| 24 |
|
|
#include "coretypes.h"
|
| 25 |
|
|
#include "tm.h"
|
| 26 |
|
|
#include "rtl.h"
|
| 27 |
|
|
#include "errors.h"
|
| 28 |
|
|
#include "read-md.h"
|
| 29 |
|
|
#include "gensupport.h"
|
| 30 |
|
|
|
| 31 |
|
|
|
| 32 |
|
|
static int insn_code_number;
|
| 33 |
|
|
static int insn_index_number;
|
| 34 |
|
|
|
| 35 |
|
|
/* 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
|
| 37 |
|
|
previously-allocated PARALLEL expression. */
|
| 38 |
|
|
|
| 39 |
|
|
struct clobber_pat
|
| 40 |
|
|
{
|
| 41 |
|
|
struct clobber_ent *insns;
|
| 42 |
|
|
rtx pattern;
|
| 43 |
|
|
int first_clobber;
|
| 44 |
|
|
struct clobber_pat *next;
|
| 45 |
|
|
int has_hard_reg;
|
| 46 |
|
|
} *clobber_list;
|
| 47 |
|
|
|
| 48 |
|
|
/* Records one insn that uses the clobber list. */
|
| 49 |
|
|
|
| 50 |
|
|
struct clobber_ent
|
| 51 |
|
|
{
|
| 52 |
|
|
int code_number; /* Counts only insns. */
|
| 53 |
|
|
struct clobber_ent *next;
|
| 54 |
|
|
};
|
| 55 |
|
|
|
| 56 |
|
|
static void print_code (RTX_CODE);
|
| 57 |
|
|
static void gen_exp (rtx, enum rtx_code, char *);
|
| 58 |
|
|
static void gen_insn (rtx, int);
|
| 59 |
|
|
static void gen_expand (rtx);
|
| 60 |
|
|
static void gen_split (rtx);
|
| 61 |
|
|
static void output_add_clobbers (void);
|
| 62 |
|
|
static void output_added_clobbers_hard_reg_p (void);
|
| 63 |
|
|
static void gen_rtx_scratch (rtx, enum rtx_code);
|
| 64 |
|
|
static void output_peephole2_scratches (rtx);
|
| 65 |
|
|
|
| 66 |
|
|
|
| 67 |
|
|
static void
|
| 68 |
|
|
print_code (RTX_CODE code)
|
| 69 |
|
|
{
|
| 70 |
|
|
const char *p1;
|
| 71 |
|
|
for (p1 = GET_RTX_NAME (code); *p1; p1++)
|
| 72 |
|
|
putchar (TOUPPER(*p1));
|
| 73 |
|
|
}
|
| 74 |
|
|
|
| 75 |
|
|
static void
|
| 76 |
|
|
gen_rtx_scratch (rtx x, enum rtx_code subroutine_type)
|
| 77 |
|
|
{
|
| 78 |
|
|
if (subroutine_type == DEFINE_PEEPHOLE2)
|
| 79 |
|
|
{
|
| 80 |
|
|
printf ("operand%d", XINT (x, 0));
|
| 81 |
|
|
}
|
| 82 |
|
|
else
|
| 83 |
|
|
{
|
| 84 |
|
|
printf ("gen_rtx_SCRATCH (%smode)", GET_MODE_NAME (GET_MODE (x)));
|
| 85 |
|
|
}
|
| 86 |
|
|
}
|
| 87 |
|
|
|
| 88 |
|
|
/* Print a C expression to construct an RTX just like X,
|
| 89 |
|
|
substituting any operand references appearing within. */
|
| 90 |
|
|
|
| 91 |
|
|
static void
|
| 92 |
|
|
gen_exp (rtx x, enum rtx_code subroutine_type, char *used)
|
| 93 |
|
|
{
|
| 94 |
|
|
RTX_CODE code;
|
| 95 |
|
|
int i;
|
| 96 |
|
|
int len;
|
| 97 |
|
|
const char *fmt;
|
| 98 |
|
|
|
| 99 |
|
|
if (x == 0)
|
| 100 |
|
|
{
|
| 101 |
|
|
printf ("NULL_RTX");
|
| 102 |
|
|
return;
|
| 103 |
|
|
}
|
| 104 |
|
|
|
| 105 |
|
|
code = GET_CODE (x);
|
| 106 |
|
|
|
| 107 |
|
|
switch (code)
|
| 108 |
|
|
{
|
| 109 |
|
|
case MATCH_OPERAND:
|
| 110 |
|
|
case MATCH_DUP:
|
| 111 |
|
|
if (used)
|
| 112 |
|
|
{
|
| 113 |
|
|
if (used[XINT (x, 0)])
|
| 114 |
|
|
{
|
| 115 |
|
|
printf ("copy_rtx (operand%d)", XINT (x, 0));
|
| 116 |
|
|
return;
|
| 117 |
|
|
}
|
| 118 |
|
|
used[XINT (x, 0)] = 1;
|
| 119 |
|
|
}
|
| 120 |
|
|
printf ("operand%d", XINT (x, 0));
|
| 121 |
|
|
return;
|
| 122 |
|
|
|
| 123 |
|
|
case MATCH_OP_DUP:
|
| 124 |
|
|
printf ("gen_rtx_fmt_");
|
| 125 |
|
|
for (i = 0; i < XVECLEN (x, 1); i++)
|
| 126 |
|
|
printf ("e");
|
| 127 |
|
|
printf (" (GET_CODE (operand%d), ", XINT (x, 0));
|
| 128 |
|
|
if (GET_MODE (x) == VOIDmode)
|
| 129 |
|
|
printf ("GET_MODE (operand%d)", XINT (x, 0));
|
| 130 |
|
|
else
|
| 131 |
|
|
printf ("%smode", GET_MODE_NAME (GET_MODE (x)));
|
| 132 |
|
|
for (i = 0; i < XVECLEN (x, 1); i++)
|
| 133 |
|
|
{
|
| 134 |
|
|
printf (",\n\t\t");
|
| 135 |
|
|
gen_exp (XVECEXP (x, 1, i), subroutine_type, used);
|
| 136 |
|
|
}
|
| 137 |
|
|
printf (")");
|
| 138 |
|
|
return;
|
| 139 |
|
|
|
| 140 |
|
|
case MATCH_OPERATOR:
|
| 141 |
|
|
printf ("gen_rtx_fmt_");
|
| 142 |
|
|
for (i = 0; i < XVECLEN (x, 2); i++)
|
| 143 |
|
|
printf ("e");
|
| 144 |
|
|
printf (" (GET_CODE (operand%d)", XINT (x, 0));
|
| 145 |
|
|
printf (", %smode", GET_MODE_NAME (GET_MODE (x)));
|
| 146 |
|
|
for (i = 0; i < XVECLEN (x, 2); i++)
|
| 147 |
|
|
{
|
| 148 |
|
|
printf (",\n\t\t");
|
| 149 |
|
|
gen_exp (XVECEXP (x, 2, i), subroutine_type, used);
|
| 150 |
|
|
}
|
| 151 |
|
|
printf (")");
|
| 152 |
|
|
return;
|
| 153 |
|
|
|
| 154 |
|
|
case MATCH_PARALLEL:
|
| 155 |
|
|
case MATCH_PAR_DUP:
|
| 156 |
|
|
printf ("operand%d", XINT (x, 0));
|
| 157 |
|
|
return;
|
| 158 |
|
|
|
| 159 |
|
|
case MATCH_SCRATCH:
|
| 160 |
|
|
gen_rtx_scratch (x, subroutine_type);
|
| 161 |
|
|
return;
|
| 162 |
|
|
|
| 163 |
|
|
case ADDRESS:
|
| 164 |
|
|
fatal ("ADDRESS expression code used in named instruction pattern");
|
| 165 |
|
|
|
| 166 |
|
|
case PC:
|
| 167 |
|
|
printf ("pc_rtx");
|
| 168 |
|
|
return;
|
| 169 |
|
|
case RETURN:
|
| 170 |
|
|
printf ("ret_rtx");
|
| 171 |
|
|
return;
|
| 172 |
|
|
case SIMPLE_RETURN:
|
| 173 |
|
|
printf ("simple_return_rtx");
|
| 174 |
|
|
return;
|
| 175 |
|
|
case CLOBBER:
|
| 176 |
|
|
if (REG_P (XEXP (x, 0)))
|
| 177 |
|
|
{
|
| 178 |
|
|
printf ("gen_hard_reg_clobber (%smode, %i)", GET_MODE_NAME (GET_MODE (XEXP (x, 0))),
|
| 179 |
|
|
REGNO (XEXP (x, 0)));
|
| 180 |
|
|
return;
|
| 181 |
|
|
}
|
| 182 |
|
|
break;
|
| 183 |
|
|
|
| 184 |
|
|
case CC0:
|
| 185 |
|
|
printf ("cc0_rtx");
|
| 186 |
|
|
return;
|
| 187 |
|
|
|
| 188 |
|
|
case CONST_INT:
|
| 189 |
|
|
if (INTVAL (x) == 0)
|
| 190 |
|
|
printf ("const0_rtx");
|
| 191 |
|
|
else if (INTVAL (x) == 1)
|
| 192 |
|
|
printf ("const1_rtx");
|
| 193 |
|
|
else if (INTVAL (x) == -1)
|
| 194 |
|
|
printf ("constm1_rtx");
|
| 195 |
|
|
else if (-MAX_SAVED_CONST_INT <= INTVAL (x)
|
| 196 |
|
|
&& INTVAL (x) <= MAX_SAVED_CONST_INT)
|
| 197 |
|
|
printf ("const_int_rtx[MAX_SAVED_CONST_INT + (%d)]",
|
| 198 |
|
|
(int) INTVAL (x));
|
| 199 |
|
|
else if (INTVAL (x) == STORE_FLAG_VALUE)
|
| 200 |
|
|
printf ("const_true_rtx");
|
| 201 |
|
|
else
|
| 202 |
|
|
{
|
| 203 |
|
|
printf ("GEN_INT (");
|
| 204 |
|
|
printf (HOST_WIDE_INT_PRINT_DEC_C, INTVAL (x));
|
| 205 |
|
|
printf (")");
|
| 206 |
|
|
}
|
| 207 |
|
|
return;
|
| 208 |
|
|
|
| 209 |
|
|
case CONST_DOUBLE:
|
| 210 |
|
|
case CONST_FIXED:
|
| 211 |
|
|
/* These shouldn't be written in MD files. Instead, the appropriate
|
| 212 |
|
|
routines in varasm.c should be called. */
|
| 213 |
|
|
gcc_unreachable ();
|
| 214 |
|
|
|
| 215 |
|
|
default:
|
| 216 |
|
|
break;
|
| 217 |
|
|
}
|
| 218 |
|
|
|
| 219 |
|
|
printf ("gen_rtx_");
|
| 220 |
|
|
print_code (code);
|
| 221 |
|
|
printf (" (%smode", GET_MODE_NAME (GET_MODE (x)));
|
| 222 |
|
|
|
| 223 |
|
|
fmt = GET_RTX_FORMAT (code);
|
| 224 |
|
|
len = GET_RTX_LENGTH (code);
|
| 225 |
|
|
for (i = 0; i < len; i++)
|
| 226 |
|
|
{
|
| 227 |
|
|
if (fmt[i] == '0')
|
| 228 |
|
|
break;
|
| 229 |
|
|
printf (",\n\t");
|
| 230 |
|
|
switch (fmt[i])
|
| 231 |
|
|
{
|
| 232 |
|
|
case 'e': case 'u':
|
| 233 |
|
|
gen_exp (XEXP (x, i), subroutine_type, used);
|
| 234 |
|
|
break;
|
| 235 |
|
|
|
| 236 |
|
|
case 'i':
|
| 237 |
|
|
printf ("%u", XINT (x, i));
|
| 238 |
|
|
break;
|
| 239 |
|
|
|
| 240 |
|
|
case 's':
|
| 241 |
|
|
printf ("\"%s\"", XSTR (x, i));
|
| 242 |
|
|
break;
|
| 243 |
|
|
|
| 244 |
|
|
case 'E':
|
| 245 |
|
|
{
|
| 246 |
|
|
int j;
|
| 247 |
|
|
printf ("gen_rtvec (%d", XVECLEN (x, i));
|
| 248 |
|
|
for (j = 0; j < XVECLEN (x, i); j++)
|
| 249 |
|
|
{
|
| 250 |
|
|
printf (",\n\t\t");
|
| 251 |
|
|
gen_exp (XVECEXP (x, i, j), subroutine_type, used);
|
| 252 |
|
|
}
|
| 253 |
|
|
printf (")");
|
| 254 |
|
|
break;
|
| 255 |
|
|
}
|
| 256 |
|
|
|
| 257 |
|
|
default:
|
| 258 |
|
|
gcc_unreachable ();
|
| 259 |
|
|
}
|
| 260 |
|
|
}
|
| 261 |
|
|
printf (")");
|
| 262 |
|
|
}
|
| 263 |
|
|
|
| 264 |
|
|
/* Generate the `gen_...' function for a DEFINE_INSN. */
|
| 265 |
|
|
|
| 266 |
|
|
static void
|
| 267 |
|
|
gen_insn (rtx insn, int lineno)
|
| 268 |
|
|
{
|
| 269 |
|
|
struct pattern_stats stats;
|
| 270 |
|
|
int i;
|
| 271 |
|
|
|
| 272 |
|
|
/* See if the pattern for this insn ends with a group of CLOBBERs of (hard)
|
| 273 |
|
|
registers or MATCH_SCRATCHes. If so, store away the information for
|
| 274 |
|
|
later. */
|
| 275 |
|
|
|
| 276 |
|
|
if (XVEC (insn, 1))
|
| 277 |
|
|
{
|
| 278 |
|
|
int has_hard_reg = 0;
|
| 279 |
|
|
|
| 280 |
|
|
for (i = XVECLEN (insn, 1) - 1; i > 0; i--)
|
| 281 |
|
|
{
|
| 282 |
|
|
if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER)
|
| 283 |
|
|
break;
|
| 284 |
|
|
|
| 285 |
|
|
if (REG_P (XEXP (XVECEXP (insn, 1, i), 0)))
|
| 286 |
|
|
has_hard_reg = 1;
|
| 287 |
|
|
else if (GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != MATCH_SCRATCH)
|
| 288 |
|
|
break;
|
| 289 |
|
|
}
|
| 290 |
|
|
|
| 291 |
|
|
if (i != XVECLEN (insn, 1) - 1)
|
| 292 |
|
|
{
|
| 293 |
|
|
struct clobber_pat *p;
|
| 294 |
|
|
struct clobber_ent *link = XNEW (struct clobber_ent);
|
| 295 |
|
|
int j;
|
| 296 |
|
|
|
| 297 |
|
|
link->code_number = insn_code_number;
|
| 298 |
|
|
|
| 299 |
|
|
/* See if any previous CLOBBER_LIST entry is the same as this
|
| 300 |
|
|
one. */
|
| 301 |
|
|
|
| 302 |
|
|
for (p = clobber_list; p; p = p->next)
|
| 303 |
|
|
{
|
| 304 |
|
|
if (p->first_clobber != i + 1
|
| 305 |
|
|
|| XVECLEN (p->pattern, 1) != XVECLEN (insn, 1))
|
| 306 |
|
|
continue;
|
| 307 |
|
|
|
| 308 |
|
|
for (j = i + 1; j < XVECLEN (insn, 1); j++)
|
| 309 |
|
|
{
|
| 310 |
|
|
rtx old_rtx = XEXP (XVECEXP (p->pattern, 1, j), 0);
|
| 311 |
|
|
rtx new_rtx = XEXP (XVECEXP (insn, 1, j), 0);
|
| 312 |
|
|
|
| 313 |
|
|
/* OLD and NEW_INSN are the same if both are to be a SCRATCH
|
| 314 |
|
|
of the same mode,
|
| 315 |
|
|
or if both are registers of the same mode and number. */
|
| 316 |
|
|
if (! (GET_MODE (old_rtx) == GET_MODE (new_rtx)
|
| 317 |
|
|
&& ((GET_CODE (old_rtx) == MATCH_SCRATCH
|
| 318 |
|
|
&& GET_CODE (new_rtx) == MATCH_SCRATCH)
|
| 319 |
|
|
|| (REG_P (old_rtx) && REG_P (new_rtx)
|
| 320 |
|
|
&& REGNO (old_rtx) == REGNO (new_rtx)))))
|
| 321 |
|
|
break;
|
| 322 |
|
|
}
|
| 323 |
|
|
|
| 324 |
|
|
if (j == XVECLEN (insn, 1))
|
| 325 |
|
|
break;
|
| 326 |
|
|
}
|
| 327 |
|
|
|
| 328 |
|
|
if (p == 0)
|
| 329 |
|
|
{
|
| 330 |
|
|
p = XNEW (struct clobber_pat);
|
| 331 |
|
|
|
| 332 |
|
|
p->insns = 0;
|
| 333 |
|
|
p->pattern = insn;
|
| 334 |
|
|
p->first_clobber = i + 1;
|
| 335 |
|
|
p->next = clobber_list;
|
| 336 |
|
|
p->has_hard_reg = has_hard_reg;
|
| 337 |
|
|
clobber_list = p;
|
| 338 |
|
|
}
|
| 339 |
|
|
|
| 340 |
|
|
link->next = p->insns;
|
| 341 |
|
|
p->insns = link;
|
| 342 |
|
|
}
|
| 343 |
|
|
}
|
| 344 |
|
|
|
| 345 |
|
|
/* Don't mention instructions whose names are the null string
|
| 346 |
|
|
or begin with '*'. They are in the machine description just
|
| 347 |
|
|
to be recognized. */
|
| 348 |
|
|
if (XSTR (insn, 0)[0] == 0 || XSTR (insn, 0)[0] == '*')
|
| 349 |
|
|
return;
|
| 350 |
|
|
|
| 351 |
|
|
printf ("/* %s:%d */\n", read_md_filename, lineno);
|
| 352 |
|
|
|
| 353 |
|
|
/* Find out how many operands this function has. */
|
| 354 |
|
|
get_pattern_stats (&stats, XVEC (insn, 1));
|
| 355 |
|
|
if (stats.max_dup_opno > stats.max_opno)
|
| 356 |
|
|
fatal ("match_dup operand number has no match_operand");
|
| 357 |
|
|
|
| 358 |
|
|
/* Output the function name and argument declarations. */
|
| 359 |
|
|
printf ("rtx\ngen_%s (", XSTR (insn, 0));
|
| 360 |
|
|
if (stats.num_generator_args)
|
| 361 |
|
|
for (i = 0; i < stats.num_generator_args; i++)
|
| 362 |
|
|
if (i)
|
| 363 |
|
|
printf (",\n\trtx operand%d ATTRIBUTE_UNUSED", i);
|
| 364 |
|
|
else
|
| 365 |
|
|
printf ("rtx operand%d ATTRIBUTE_UNUSED", i);
|
| 366 |
|
|
else
|
| 367 |
|
|
printf ("void");
|
| 368 |
|
|
printf (")\n");
|
| 369 |
|
|
printf ("{\n");
|
| 370 |
|
|
|
| 371 |
|
|
/* Output code to construct and return the rtl for the instruction body. */
|
| 372 |
|
|
|
| 373 |
|
|
if (XVECLEN (insn, 1) == 1)
|
| 374 |
|
|
{
|
| 375 |
|
|
printf (" return ");
|
| 376 |
|
|
gen_exp (XVECEXP (insn, 1, 0), DEFINE_INSN, NULL);
|
| 377 |
|
|
printf (";\n}\n\n");
|
| 378 |
|
|
}
|
| 379 |
|
|
else
|
| 380 |
|
|
{
|
| 381 |
|
|
char *used = XCNEWVEC (char, stats.num_generator_args);
|
| 382 |
|
|
|
| 383 |
|
|
printf (" return gen_rtx_PARALLEL (VOIDmode, gen_rtvec (%d",
|
| 384 |
|
|
XVECLEN (insn, 1));
|
| 385 |
|
|
|
| 386 |
|
|
for (i = 0; i < XVECLEN (insn, 1); i++)
|
| 387 |
|
|
{
|
| 388 |
|
|
printf (",\n\t\t");
|
| 389 |
|
|
gen_exp (XVECEXP (insn, 1, i), DEFINE_INSN, used);
|
| 390 |
|
|
}
|
| 391 |
|
|
printf ("));\n}\n\n");
|
| 392 |
|
|
XDELETEVEC (used);
|
| 393 |
|
|
}
|
| 394 |
|
|
}
|
| 395 |
|
|
|
| 396 |
|
|
/* Generate the `gen_...' function for a DEFINE_EXPAND. */
|
| 397 |
|
|
|
| 398 |
|
|
static void
|
| 399 |
|
|
gen_expand (rtx expand)
|
| 400 |
|
|
{
|
| 401 |
|
|
struct pattern_stats stats;
|
| 402 |
|
|
int i;
|
| 403 |
|
|
char *used;
|
| 404 |
|
|
|
| 405 |
|
|
if (strlen (XSTR (expand, 0)) == 0)
|
| 406 |
|
|
fatal ("define_expand lacks a name");
|
| 407 |
|
|
if (XVEC (expand, 1) == 0)
|
| 408 |
|
|
fatal ("define_expand for %s lacks a pattern", XSTR (expand, 0));
|
| 409 |
|
|
|
| 410 |
|
|
/* Find out how many operands this function has. */
|
| 411 |
|
|
get_pattern_stats (&stats, XVEC (expand, 1));
|
| 412 |
|
|
|
| 413 |
|
|
/* Output the function name and argument declarations. */
|
| 414 |
|
|
printf ("rtx\ngen_%s (", XSTR (expand, 0));
|
| 415 |
|
|
if (stats.num_generator_args)
|
| 416 |
|
|
for (i = 0; i < stats.num_generator_args; i++)
|
| 417 |
|
|
if (i)
|
| 418 |
|
|
printf (",\n\trtx operand%d", i);
|
| 419 |
|
|
else
|
| 420 |
|
|
printf ("rtx operand%d", i);
|
| 421 |
|
|
else
|
| 422 |
|
|
printf ("void");
|
| 423 |
|
|
printf (")\n");
|
| 424 |
|
|
printf ("{\n");
|
| 425 |
|
|
|
| 426 |
|
|
/* If we don't have any C code to write, only one insn is being written,
|
| 427 |
|
|
and no MATCH_DUPs are present, we can just return the desired insn
|
| 428 |
|
|
like we do for a DEFINE_INSN. This saves memory. */
|
| 429 |
|
|
if ((XSTR (expand, 3) == 0 || *XSTR (expand, 3) == '\0')
|
| 430 |
|
|
&& stats.max_opno >= stats.max_dup_opno
|
| 431 |
|
|
&& XVECLEN (expand, 1) == 1)
|
| 432 |
|
|
{
|
| 433 |
|
|
printf (" return ");
|
| 434 |
|
|
gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL);
|
| 435 |
|
|
printf (";\n}\n\n");
|
| 436 |
|
|
return;
|
| 437 |
|
|
}
|
| 438 |
|
|
|
| 439 |
|
|
/* For each operand referred to only with MATCH_DUPs,
|
| 440 |
|
|
make a local variable. */
|
| 441 |
|
|
for (i = stats.num_generator_args; i <= stats.max_dup_opno; i++)
|
| 442 |
|
|
printf (" rtx operand%d;\n", i);
|
| 443 |
|
|
for (; i <= stats.max_scratch_opno; i++)
|
| 444 |
|
|
printf (" rtx operand%d ATTRIBUTE_UNUSED;\n", i);
|
| 445 |
|
|
printf (" rtx _val = 0;\n");
|
| 446 |
|
|
printf (" start_sequence ();\n");
|
| 447 |
|
|
|
| 448 |
|
|
/* The fourth operand of DEFINE_EXPAND is some code to be executed
|
| 449 |
|
|
before the actual construction.
|
| 450 |
|
|
This code expects to refer to `operands'
|
| 451 |
|
|
just as the output-code in a DEFINE_INSN does,
|
| 452 |
|
|
but here `operands' is an automatic array.
|
| 453 |
|
|
So copy the operand values there before executing it. */
|
| 454 |
|
|
if (XSTR (expand, 3) && *XSTR (expand, 3))
|
| 455 |
|
|
{
|
| 456 |
|
|
printf (" {\n");
|
| 457 |
|
|
if (stats.num_operand_vars > 0)
|
| 458 |
|
|
printf (" rtx operands[%d];\n", stats.num_operand_vars);
|
| 459 |
|
|
|
| 460 |
|
|
/* Output code to copy the arguments into `operands'. */
|
| 461 |
|
|
for (i = 0; i < stats.num_generator_args; i++)
|
| 462 |
|
|
printf (" operands[%d] = operand%d;\n", i, i);
|
| 463 |
|
|
|
| 464 |
|
|
/* Output the special code to be executed before the sequence
|
| 465 |
|
|
is generated. */
|
| 466 |
|
|
print_md_ptr_loc (XSTR (expand, 3));
|
| 467 |
|
|
printf ("%s\n", XSTR (expand, 3));
|
| 468 |
|
|
|
| 469 |
|
|
/* Output code to copy the arguments back out of `operands'
|
| 470 |
|
|
(unless we aren't going to use them at all). */
|
| 471 |
|
|
if (XVEC (expand, 1) != 0)
|
| 472 |
|
|
{
|
| 473 |
|
|
for (i = 0; i < stats.num_operand_vars; i++)
|
| 474 |
|
|
{
|
| 475 |
|
|
printf (" operand%d = operands[%d];\n", i, i);
|
| 476 |
|
|
printf (" (void) operand%d;\n", i);
|
| 477 |
|
|
}
|
| 478 |
|
|
}
|
| 479 |
|
|
printf (" }\n");
|
| 480 |
|
|
}
|
| 481 |
|
|
|
| 482 |
|
|
/* Output code to construct the rtl for the instruction bodies.
|
| 483 |
|
|
Use emit_insn to add them to the sequence being accumulated.
|
| 484 |
|
|
But don't do this if the user's code has set `no_more' nonzero. */
|
| 485 |
|
|
|
| 486 |
|
|
used = XCNEWVEC (char, stats.num_operand_vars);
|
| 487 |
|
|
|
| 488 |
|
|
for (i = 0; i < XVECLEN (expand, 1); i++)
|
| 489 |
|
|
{
|
| 490 |
|
|
rtx next = XVECEXP (expand, 1, i);
|
| 491 |
|
|
if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC)
|
| 492 |
|
|
|| (GET_CODE (next) == PARALLEL
|
| 493 |
|
|
&& ((GET_CODE (XVECEXP (next, 0, 0)) == SET
|
| 494 |
|
|
&& GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
|
| 495 |
|
|
|| ANY_RETURN_P (XVECEXP (next, 0, 0))))
|
| 496 |
|
|
|| ANY_RETURN_P (next))
|
| 497 |
|
|
printf (" emit_jump_insn (");
|
| 498 |
|
|
else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
|
| 499 |
|
|
|| GET_CODE (next) == CALL
|
| 500 |
|
|
|| (GET_CODE (next) == PARALLEL
|
| 501 |
|
|
&& GET_CODE (XVECEXP (next, 0, 0)) == SET
|
| 502 |
|
|
&& GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL)
|
| 503 |
|
|
|| (GET_CODE (next) == PARALLEL
|
| 504 |
|
|
&& GET_CODE (XVECEXP (next, 0, 0)) == CALL))
|
| 505 |
|
|
printf (" emit_call_insn (");
|
| 506 |
|
|
else if (LABEL_P (next))
|
| 507 |
|
|
printf (" emit_label (");
|
| 508 |
|
|
else if (GET_CODE (next) == MATCH_OPERAND
|
| 509 |
|
|
|| GET_CODE (next) == MATCH_DUP
|
| 510 |
|
|
|| GET_CODE (next) == MATCH_OPERATOR
|
| 511 |
|
|
|| GET_CODE (next) == MATCH_OP_DUP
|
| 512 |
|
|
|| GET_CODE (next) == MATCH_PARALLEL
|
| 513 |
|
|
|| GET_CODE (next) == MATCH_PAR_DUP
|
| 514 |
|
|
|| GET_CODE (next) == PARALLEL)
|
| 515 |
|
|
printf (" emit (");
|
| 516 |
|
|
else
|
| 517 |
|
|
printf (" emit_insn (");
|
| 518 |
|
|
gen_exp (next, DEFINE_EXPAND, used);
|
| 519 |
|
|
printf (");\n");
|
| 520 |
|
|
if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC
|
| 521 |
|
|
&& GET_CODE (SET_SRC (next)) == LABEL_REF)
|
| 522 |
|
|
printf (" emit_barrier ();");
|
| 523 |
|
|
}
|
| 524 |
|
|
|
| 525 |
|
|
XDELETEVEC (used);
|
| 526 |
|
|
|
| 527 |
|
|
/* Call `get_insns' to extract the list of all the
|
| 528 |
|
|
insns emitted within this gen_... function. */
|
| 529 |
|
|
|
| 530 |
|
|
printf (" _val = get_insns ();\n");
|
| 531 |
|
|
printf (" end_sequence ();\n");
|
| 532 |
|
|
printf (" return _val;\n}\n\n");
|
| 533 |
|
|
}
|
| 534 |
|
|
|
| 535 |
|
|
/* Like gen_expand, but generates insns resulting from splitting SPLIT. */
|
| 536 |
|
|
|
| 537 |
|
|
static void
|
| 538 |
|
|
gen_split (rtx split)
|
| 539 |
|
|
{
|
| 540 |
|
|
struct pattern_stats stats;
|
| 541 |
|
|
int i;
|
| 542 |
|
|
const char *const name =
|
| 543 |
|
|
((GET_CODE (split) == DEFINE_PEEPHOLE2) ? "peephole2" : "split");
|
| 544 |
|
|
const char *unused;
|
| 545 |
|
|
char *used;
|
| 546 |
|
|
|
| 547 |
|
|
if (XVEC (split, 0) == 0)
|
| 548 |
|
|
fatal ("define_%s (definition %d) lacks a pattern", name,
|
| 549 |
|
|
insn_index_number);
|
| 550 |
|
|
else if (XVEC (split, 2) == 0)
|
| 551 |
|
|
fatal ("define_%s (definition %d) lacks a replacement pattern", name,
|
| 552 |
|
|
insn_index_number);
|
| 553 |
|
|
|
| 554 |
|
|
/* Find out how many operands this function has. */
|
| 555 |
|
|
|
| 556 |
|
|
get_pattern_stats (&stats, XVEC (split, 2));
|
| 557 |
|
|
unused = (stats.num_operand_vars == 0 ? " ATTRIBUTE_UNUSED" : "");
|
| 558 |
|
|
used = XCNEWVEC (char, stats.num_operand_vars);
|
| 559 |
|
|
|
| 560 |
|
|
/* Output the prototype, function name and argument declarations. */
|
| 561 |
|
|
if (GET_CODE (split) == DEFINE_PEEPHOLE2)
|
| 562 |
|
|
{
|
| 563 |
|
|
printf ("extern rtx gen_%s_%d (rtx, rtx *);\n",
|
| 564 |
|
|
name, insn_code_number);
|
| 565 |
|
|
printf ("rtx\ngen_%s_%d (rtx curr_insn ATTRIBUTE_UNUSED, rtx *operands%s)\n",
|
| 566 |
|
|
name, insn_code_number, unused);
|
| 567 |
|
|
}
|
| 568 |
|
|
else
|
| 569 |
|
|
{
|
| 570 |
|
|
printf ("extern rtx gen_split_%d (rtx, rtx *);\n", insn_code_number);
|
| 571 |
|
|
printf ("rtx\ngen_split_%d (rtx curr_insn ATTRIBUTE_UNUSED, rtx *operands%s)\n",
|
| 572 |
|
|
insn_code_number, unused);
|
| 573 |
|
|
}
|
| 574 |
|
|
printf ("{\n");
|
| 575 |
|
|
|
| 576 |
|
|
/* Declare all local variables. */
|
| 577 |
|
|
for (i = 0; i < stats.num_operand_vars; i++)
|
| 578 |
|
|
printf (" rtx operand%d;\n", i);
|
| 579 |
|
|
printf (" rtx _val = 0;\n");
|
| 580 |
|
|
|
| 581 |
|
|
if (GET_CODE (split) == DEFINE_PEEPHOLE2)
|
| 582 |
|
|
output_peephole2_scratches (split);
|
| 583 |
|
|
|
| 584 |
|
|
printf (" start_sequence ();\n");
|
| 585 |
|
|
|
| 586 |
|
|
/* The fourth operand of DEFINE_SPLIT is some code to be executed
|
| 587 |
|
|
before the actual construction. */
|
| 588 |
|
|
|
| 589 |
|
|
if (XSTR (split, 3))
|
| 590 |
|
|
{
|
| 591 |
|
|
print_md_ptr_loc (XSTR (split, 3));
|
| 592 |
|
|
printf ("%s\n", XSTR (split, 3));
|
| 593 |
|
|
}
|
| 594 |
|
|
|
| 595 |
|
|
/* Output code to copy the arguments back out of `operands' */
|
| 596 |
|
|
for (i = 0; i < stats.num_operand_vars; i++)
|
| 597 |
|
|
{
|
| 598 |
|
|
printf (" operand%d = operands[%d];\n", i, i);
|
| 599 |
|
|
printf (" (void) operand%d;\n", i);
|
| 600 |
|
|
}
|
| 601 |
|
|
|
| 602 |
|
|
/* Output code to construct the rtl for the instruction bodies.
|
| 603 |
|
|
Use emit_insn to add them to the sequence being accumulated.
|
| 604 |
|
|
But don't do this if the user's code has set `no_more' nonzero. */
|
| 605 |
|
|
|
| 606 |
|
|
for (i = 0; i < XVECLEN (split, 2); i++)
|
| 607 |
|
|
{
|
| 608 |
|
|
rtx next = XVECEXP (split, 2, i);
|
| 609 |
|
|
if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC)
|
| 610 |
|
|
|| (GET_CODE (next) == PARALLEL
|
| 611 |
|
|
&& GET_CODE (XVECEXP (next, 0, 0)) == SET
|
| 612 |
|
|
&& GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
|
| 613 |
|
|
|| ANY_RETURN_P (next))
|
| 614 |
|
|
printf (" emit_jump_insn (");
|
| 615 |
|
|
else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
|
| 616 |
|
|
|| GET_CODE (next) == CALL
|
| 617 |
|
|
|| (GET_CODE (next) == PARALLEL
|
| 618 |
|
|
&& GET_CODE (XVECEXP (next, 0, 0)) == SET
|
| 619 |
|
|
&& GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL)
|
| 620 |
|
|
|| (GET_CODE (next) == PARALLEL
|
| 621 |
|
|
&& GET_CODE (XVECEXP (next, 0, 0)) == CALL))
|
| 622 |
|
|
printf (" emit_call_insn (");
|
| 623 |
|
|
else if (LABEL_P (next))
|
| 624 |
|
|
printf (" emit_label (");
|
| 625 |
|
|
else if (GET_CODE (next) == MATCH_OPERAND
|
| 626 |
|
|
|| GET_CODE (next) == MATCH_OPERATOR
|
| 627 |
|
|
|| GET_CODE (next) == MATCH_PARALLEL
|
| 628 |
|
|
|| GET_CODE (next) == MATCH_OP_DUP
|
| 629 |
|
|
|| GET_CODE (next) == MATCH_DUP
|
| 630 |
|
|
|| GET_CODE (next) == PARALLEL)
|
| 631 |
|
|
printf (" emit (");
|
| 632 |
|
|
else
|
| 633 |
|
|
printf (" emit_insn (");
|
| 634 |
|
|
gen_exp (next, GET_CODE (split), used);
|
| 635 |
|
|
printf (");\n");
|
| 636 |
|
|
if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC
|
| 637 |
|
|
&& GET_CODE (SET_SRC (next)) == LABEL_REF)
|
| 638 |
|
|
printf (" emit_barrier ();");
|
| 639 |
|
|
}
|
| 640 |
|
|
|
| 641 |
|
|
/* Call `get_insns' to make a list of all the
|
| 642 |
|
|
insns emitted within this gen_... function. */
|
| 643 |
|
|
|
| 644 |
|
|
printf (" _val = get_insns ();\n");
|
| 645 |
|
|
printf (" end_sequence ();\n");
|
| 646 |
|
|
printf (" return _val;\n}\n\n");
|
| 647 |
|
|
|
| 648 |
|
|
free (used);
|
| 649 |
|
|
}
|
| 650 |
|
|
|
| 651 |
|
|
/* Write a function, `add_clobbers', that is given a PARALLEL of sufficient
|
| 652 |
|
|
size for the insn and an INSN_CODE, and inserts the required CLOBBERs at
|
| 653 |
|
|
the end of the vector. */
|
| 654 |
|
|
|
| 655 |
|
|
static void
|
| 656 |
|
|
output_add_clobbers (void)
|
| 657 |
|
|
{
|
| 658 |
|
|
struct clobber_pat *clobber;
|
| 659 |
|
|
struct clobber_ent *ent;
|
| 660 |
|
|
int i;
|
| 661 |
|
|
|
| 662 |
|
|
printf ("\n\nvoid\nadd_clobbers (rtx pattern ATTRIBUTE_UNUSED, int insn_code_number)\n");
|
| 663 |
|
|
printf ("{\n");
|
| 664 |
|
|
printf (" switch (insn_code_number)\n");
|
| 665 |
|
|
printf (" {\n");
|
| 666 |
|
|
|
| 667 |
|
|
for (clobber = clobber_list; clobber; clobber = clobber->next)
|
| 668 |
|
|
{
|
| 669 |
|
|
for (ent = clobber->insns; ent; ent = ent->next)
|
| 670 |
|
|
printf (" case %d:\n", ent->code_number);
|
| 671 |
|
|
|
| 672 |
|
|
for (i = clobber->first_clobber; i < XVECLEN (clobber->pattern, 1); i++)
|
| 673 |
|
|
{
|
| 674 |
|
|
printf (" XVECEXP (pattern, 0, %d) = ", i);
|
| 675 |
|
|
gen_exp (XVECEXP (clobber->pattern, 1, i),
|
| 676 |
|
|
GET_CODE (clobber->pattern), NULL);
|
| 677 |
|
|
printf (";\n");
|
| 678 |
|
|
}
|
| 679 |
|
|
|
| 680 |
|
|
printf (" break;\n\n");
|
| 681 |
|
|
}
|
| 682 |
|
|
|
| 683 |
|
|
printf (" default:\n");
|
| 684 |
|
|
printf (" gcc_unreachable ();\n");
|
| 685 |
|
|
printf (" }\n");
|
| 686 |
|
|
printf ("}\n");
|
| 687 |
|
|
}
|
| 688 |
|
|
|
| 689 |
|
|
/* Write a function, `added_clobbers_hard_reg_p' that is given an insn_code
|
| 690 |
|
|
number that will have clobbers added (as indicated by `recog') and returns
|
| 691 |
|
|
1 if those include a clobber of a hard reg or 0 if all of them just clobber
|
| 692 |
|
|
SCRATCH. */
|
| 693 |
|
|
|
| 694 |
|
|
static void
|
| 695 |
|
|
output_added_clobbers_hard_reg_p (void)
|
| 696 |
|
|
{
|
| 697 |
|
|
struct clobber_pat *clobber;
|
| 698 |
|
|
struct clobber_ent *ent;
|
| 699 |
|
|
int clobber_p, used;
|
| 700 |
|
|
|
| 701 |
|
|
printf ("\n\nint\nadded_clobbers_hard_reg_p (int insn_code_number)\n");
|
| 702 |
|
|
printf ("{\n");
|
| 703 |
|
|
printf (" switch (insn_code_number)\n");
|
| 704 |
|
|
printf (" {\n");
|
| 705 |
|
|
|
| 706 |
|
|
for (clobber_p = 0; clobber_p <= 1; clobber_p++)
|
| 707 |
|
|
{
|
| 708 |
|
|
used = 0;
|
| 709 |
|
|
for (clobber = clobber_list; clobber; clobber = clobber->next)
|
| 710 |
|
|
if (clobber->has_hard_reg == clobber_p)
|
| 711 |
|
|
for (ent = clobber->insns; ent; ent = ent->next)
|
| 712 |
|
|
{
|
| 713 |
|
|
printf (" case %d:\n", ent->code_number);
|
| 714 |
|
|
used++;
|
| 715 |
|
|
}
|
| 716 |
|
|
|
| 717 |
|
|
if (used)
|
| 718 |
|
|
printf (" return %d;\n\n", clobber_p);
|
| 719 |
|
|
}
|
| 720 |
|
|
|
| 721 |
|
|
printf (" default:\n");
|
| 722 |
|
|
printf (" gcc_unreachable ();\n");
|
| 723 |
|
|
printf (" }\n");
|
| 724 |
|
|
printf ("}\n");
|
| 725 |
|
|
}
|
| 726 |
|
|
|
| 727 |
|
|
/* Generate code to invoke find_free_register () as needed for the
|
| 728 |
|
|
scratch registers used by the peephole2 pattern in SPLIT. */
|
| 729 |
|
|
|
| 730 |
|
|
static void
|
| 731 |
|
|
output_peephole2_scratches (rtx split)
|
| 732 |
|
|
{
|
| 733 |
|
|
int i;
|
| 734 |
|
|
int insn_nr = 0;
|
| 735 |
|
|
bool first = true;
|
| 736 |
|
|
|
| 737 |
|
|
for (i = 0; i < XVECLEN (split, 0); i++)
|
| 738 |
|
|
{
|
| 739 |
|
|
rtx elt = XVECEXP (split, 0, i);
|
| 740 |
|
|
if (GET_CODE (elt) == MATCH_SCRATCH)
|
| 741 |
|
|
{
|
| 742 |
|
|
int last_insn_nr = insn_nr;
|
| 743 |
|
|
int cur_insn_nr = insn_nr;
|
| 744 |
|
|
int j;
|
| 745 |
|
|
for (j = i + 1; j < XVECLEN (split, 0); j++)
|
| 746 |
|
|
if (GET_CODE (XVECEXP (split, 0, j)) == MATCH_DUP)
|
| 747 |
|
|
{
|
| 748 |
|
|
if (XINT (XVECEXP (split, 0, j), 0) == XINT (elt, 0))
|
| 749 |
|
|
last_insn_nr = cur_insn_nr;
|
| 750 |
|
|
}
|
| 751 |
|
|
else if (GET_CODE (XVECEXP (split, 0, j)) != MATCH_SCRATCH)
|
| 752 |
|
|
cur_insn_nr++;
|
| 753 |
|
|
|
| 754 |
|
|
if (first)
|
| 755 |
|
|
{
|
| 756 |
|
|
printf (" HARD_REG_SET _regs_allocated;\n");
|
| 757 |
|
|
printf (" CLEAR_HARD_REG_SET (_regs_allocated);\n");
|
| 758 |
|
|
first = false;
|
| 759 |
|
|
}
|
| 760 |
|
|
|
| 761 |
|
|
printf (" if ((operands[%d] = peep2_find_free_register (%d, %d, \"%s\", %smode, &_regs_allocated)) == NULL_RTX)\n\
|
| 762 |
|
|
return NULL;\n",
|
| 763 |
|
|
XINT (elt, 0),
|
| 764 |
|
|
insn_nr, last_insn_nr,
|
| 765 |
|
|
XSTR (elt, 1),
|
| 766 |
|
|
GET_MODE_NAME (GET_MODE (elt)));
|
| 767 |
|
|
|
| 768 |
|
|
}
|
| 769 |
|
|
else if (GET_CODE (elt) != MATCH_DUP)
|
| 770 |
|
|
insn_nr++;
|
| 771 |
|
|
}
|
| 772 |
|
|
}
|
| 773 |
|
|
|
| 774 |
|
|
int
|
| 775 |
|
|
main (int argc, char **argv)
|
| 776 |
|
|
{
|
| 777 |
|
|
rtx desc;
|
| 778 |
|
|
|
| 779 |
|
|
progname = "genemit";
|
| 780 |
|
|
|
| 781 |
|
|
if (!init_rtx_reader_args (argc, argv))
|
| 782 |
|
|
return (FATAL_EXIT_CODE);
|
| 783 |
|
|
|
| 784 |
|
|
/* Assign sequential codes to all entries in the machine description
|
| 785 |
|
|
in parallel with the tables in insn-output.c. */
|
| 786 |
|
|
|
| 787 |
|
|
insn_code_number = 0;
|
| 788 |
|
|
insn_index_number = 0;
|
| 789 |
|
|
|
| 790 |
|
|
printf ("/* Generated automatically by the program `genemit'\n\
|
| 791 |
|
|
from the machine description file `md'. */\n\n");
|
| 792 |
|
|
|
| 793 |
|
|
printf ("#include \"config.h\"\n");
|
| 794 |
|
|
printf ("#include \"system.h\"\n");
|
| 795 |
|
|
printf ("#include \"coretypes.h\"\n");
|
| 796 |
|
|
printf ("#include \"tm.h\"\n");
|
| 797 |
|
|
printf ("#include \"rtl.h\"\n");
|
| 798 |
|
|
printf ("#include \"tm_p.h\"\n");
|
| 799 |
|
|
printf ("#include \"function.h\"\n");
|
| 800 |
|
|
printf ("#include \"expr.h\"\n");
|
| 801 |
|
|
printf ("#include \"optabs.h\"\n");
|
| 802 |
|
|
printf ("#include \"dfp.h\"\n");
|
| 803 |
|
|
printf ("#include \"flags.h\"\n");
|
| 804 |
|
|
printf ("#include \"output.h\"\n");
|
| 805 |
|
|
printf ("#include \"insn-config.h\"\n");
|
| 806 |
|
|
printf ("#include \"hard-reg-set.h\"\n");
|
| 807 |
|
|
printf ("#include \"recog.h\"\n");
|
| 808 |
|
|
printf ("#include \"resource.h\"\n");
|
| 809 |
|
|
printf ("#include \"reload.h\"\n");
|
| 810 |
|
|
printf ("#include \"diagnostic-core.h\"\n");
|
| 811 |
|
|
printf ("#include \"regs.h\"\n");
|
| 812 |
|
|
printf ("#include \"tm-constrs.h\"\n");
|
| 813 |
|
|
printf ("#include \"ggc.h\"\n");
|
| 814 |
|
|
printf ("#include \"basic-block.h\"\n");
|
| 815 |
|
|
printf ("#include \"integrate.h\"\n\n");
|
| 816 |
|
|
printf ("#define FAIL return (end_sequence (), _val)\n");
|
| 817 |
|
|
printf ("#define DONE return (_val = get_insns (), end_sequence (), _val)\n\n");
|
| 818 |
|
|
|
| 819 |
|
|
/* Read the machine description. */
|
| 820 |
|
|
|
| 821 |
|
|
while (1)
|
| 822 |
|
|
{
|
| 823 |
|
|
int line_no;
|
| 824 |
|
|
|
| 825 |
|
|
desc = read_md_rtx (&line_no, &insn_code_number);
|
| 826 |
|
|
if (desc == NULL)
|
| 827 |
|
|
break;
|
| 828 |
|
|
|
| 829 |
|
|
switch (GET_CODE (desc))
|
| 830 |
|
|
{
|
| 831 |
|
|
case DEFINE_INSN:
|
| 832 |
|
|
gen_insn (desc, line_no);
|
| 833 |
|
|
break;
|
| 834 |
|
|
|
| 835 |
|
|
case DEFINE_EXPAND:
|
| 836 |
|
|
printf ("/* %s:%d */\n", read_md_filename, line_no);
|
| 837 |
|
|
gen_expand (desc);
|
| 838 |
|
|
break;
|
| 839 |
|
|
|
| 840 |
|
|
case DEFINE_SPLIT:
|
| 841 |
|
|
printf ("/* %s:%d */\n", read_md_filename, line_no);
|
| 842 |
|
|
gen_split (desc);
|
| 843 |
|
|
break;
|
| 844 |
|
|
|
| 845 |
|
|
case DEFINE_PEEPHOLE2:
|
| 846 |
|
|
printf ("/* %s:%d */\n", read_md_filename, line_no);
|
| 847 |
|
|
gen_split (desc);
|
| 848 |
|
|
break;
|
| 849 |
|
|
|
| 850 |
|
|
default:
|
| 851 |
|
|
break;
|
| 852 |
|
|
}
|
| 853 |
|
|
++insn_index_number;
|
| 854 |
|
|
}
|
| 855 |
|
|
|
| 856 |
|
|
/* Write out the routines to add CLOBBERs to a pattern and say whether they
|
| 857 |
|
|
clobber a hard reg. */
|
| 858 |
|
|
output_add_clobbers ();
|
| 859 |
|
|
output_added_clobbers_hard_reg_p ();
|
| 860 |
|
|
|
| 861 |
|
|
fflush (stdout);
|
| 862 |
|
|
return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
|
| 863 |
|
|
}
|