genemit



/
genemit.c
/

static void
max_operand_1 (x)
     rtx x;
{
register RTX_CODE code;
register int i;
register int len;
register char fmt;

if (x == 0)
    return;

code = GET_CODE (x);

if (code == MATCH_OPERAND && XSTR (x, 2) != 0 &&
XSTR (x, 2) != ‘’)
    register_constraints = 1;
if (code == MATCH_SCRATCH && XSTR (x, 1) != 0 && XSTR (x, 1) != ‘’)
    register_constraints = 1;
if (code == MATCH_OPERAND || code == MATCH_OPERATOR
      || code == MATCH_PARALLEL)
    max_opno = MAX (max_opno, XINT (x, 0));
if (code == MATCH_DUP || code == MATCH_OP_DUP || code == MATCH_PAR_DUP)
    max_dup_opno = MAX (max_dup_opno, XINT (x, 0));

fmt = GET_RTX_FORMAT (code);
len = GET_RTX_LENGTH (code);
for (i = 0; i < len; i++)
    {
      if (fmt[i] == ‘e’ || fmt[i] == ‘u’)
    max_operand_1 (XEXP (x, i));
      else if (fmt[i] == ‘E’)
    {
    int j;
    for (j = 0; j < XVECLEN (x, i); j++)
        max_operand_1 (XVECEXP (x, i, j));
    }
    }
}

static int
max_operand_vec (insn, arg)
     rtx insn;
     int arg;
{
register int len = XVECLEN (insn, arg);
register int i;

max_opno = -1;
max_dup_opno = -1;

for (i = 0; i < len; i++)
    max_operand_1 (XVECEXP (insn, arg, i));

return max_opno + 1;
}

/
Print a C expression to construct an RTX just like X,
   substituting any operand references appearing within. /

static void
gen_exp (x)
     rtx x;
{
register RTX_CODE code;
register int i;
register int len;
register char
fmt;

if (x == 0)
    {
      printf ("NULL_RTX");
      return;
    }

code = GET_CODE (x);

switch (code)
    {
    case MATCH_OPERAND:
    case MATCH_DUP:
      printf ("operand%d", XINT (x, 0));
      return;

    case MATCH_OP_DUP:
      printf ("gen_rtx (GET_CODE (operand%d), GET_MODE (operand%d)",
          XINT (x, 0), XINT (x, 0));
      for (i = 0; i < XVECLEN (x, 1); i++)
    {
    printf (",ntt");
    gen_exp (XVECEXP (x, 1, i));
    }
      printf (")");
      return;

    case MATCH_OPERATOR:
      printf ("gen_rtx (GET_CODE (operand%d)", XINT (x, 0));
      printf (", %smode", GET_MODE_NAME (GET_MODE (x)));
      for (i = 0; i < XVECLEN (x, 2); i++)
    {
    printf (",ntt");
    gen_exp (XVECEXP (x, 2, i));
    }
      printf (")");
      return;

    case MATCH_PARALLEL:
    case MATCH_PAR_DUP:
      printf ("operand%d", XINT (x, 0));
      return;

    case MATCH_SCRATCH:
      printf ("gen_rtx (SCRATCH, %smode, 0)", GET_MODE_NAME (GET_MODE (x)));
      return;

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

    case PC:
      printf ("pc_rtx");
      return;

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

    case CONST_INT:
      if (INTVAL (x) == 0)
    printf ("const0_rtx");
      else if (INTVAL (x) == 1)
    printf ("const1_rtx");
      else if (INTVAL (x) == -1)
    printf ("constm1_rtx");
      else if (INTVAL (x) == STORE_FLAG_VALUE)
    printf ("const_true_rtx");
      else
    printf (
#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT        
        "GEN_INT (%d)",
#else
        "GEN_INT (%ld)",
#endif
        INTVAL (x));
      return;

    case CONST_DOUBLE:
      / These shouldn’t be written in MD files. Instead, the appropriate
    routines in varasm.c should be called.
/
      abort ();
    }

printf ("gen_rtx (");
print_code (code);
printf (", %smode", GET_MODE_NAME (GET_MODE (x)));

fmt = GET_RTX_FORMAT (code);
len = GET_RTX_LENGTH (code);
for (i = 0; i < len; i++)
    {
      if (fmt[i] == ‘0’)
    break;
      printf (",nt");
      if (fmt[i] == ‘e’ || fmt[i] == ‘u’)
    gen_exp (XEXP (x, i));
      else if (fmt[i] == ‘i’)
    printf ("%u", XINT (x, i));
      else if (fmt[i] == ‘s’)
    printf (""%s"", XSTR (x, i));
      else if (fmt[i] == ‘E’)
    {
    int j;
    printf ("gen_rtvec (%d", XVECLEN (x, i));
    for (j = 0; j < XVECLEN (x, i); j++)
        {
          printf (",ntt");
          genexp (XVECEXP (x, i, j));
        }
    printf (")");
    }
      else
    abort ();
    }
printf (")");
}

/* Generate the `gen
…’ function for a DEFINE_INSN. /

static void
gen_insn (insn)
     rtx insn;
{
int operands;
register int i;

/
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
     later. /

if (XVEC (insn, 1))
    {
      for (i = XVECLEN (insn, 1) - 1; i > 0; i–)
    if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER
        || (GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != REG
        && GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != MATCH_SCRATCH))
    break;

      if (i != XVECLEN (insn, 1) - 1)
    {
    register struct clobber_pat
p;
    register struct clobber_ent link
        = (struct clobber_ent
) xmalloc (sizeof (struct clobber_ent));
    register int j;

    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++)
        {
        rtx old = XEXP (XVECEXP (p->pattern, 1, j), 0);
        rtx new = XEXP (XVECEXP (insn, 1, j), 0);

        / OLD and NEW are the same if both are to be a SCRATCH
             of the same mode,
             or if both are registers of the same mode and number.
/
        if (! (GET_MODE (old) == GET_MODE (new)
            && ((GET_CODE (old) == MATCH_SCRATCH
                  && GET_CODE (new) == MATCH_SCRATCH)
                 || (GET_CODE (old) == REG && GET_CODE (new) == REG
                && REGNO (old) == REGNO (new)))))
            break;
        }
     
          if (j == XVECLEN (insn, 1))
        break;
        }

    if (p == 0)
        {
          p = (struct clobber_pat ) xmalloc (sizeof (struct clobber_pat));
   
          p->insns = 0;
          p->pattern = insn;
          p->first_clobber = i + 1;
          p->next = clobber_list;
          clobber_list = p;
        }

    link->next = p->insns;
    p->insns = link;
    }
    }

/
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] == ‘‘)
    return;

/
Find out how many operands this function has,
     and also whether any of them have register constraints. /
register_constraints = 0;
operands = max_operand_vec (insn, 1);
if (max_dup_opno >= operands)
    fatal ("match_dup operand number has no match_operand");

/
Output the function name and argument declarations. /
printf ("rtxngen_%s (", XSTR (insn, 0));
for (i = 0; i < operands; i++)
    printf (i ? ", operand%d" : "operand%d", i);
printf (")n");
for (i = 0; i < operands; i++)
    printf ("     rtx operand%d;n", i);
printf ("{n");

/
Output code to construct and return the rtl for the instruction body /

if (XVECLEN (insn, 1) == 1)
    {
      printf (" return ");
      gen_exp (XVECEXP (insn, 1, 0));
      printf (";n}nn");
    }
else
    {
      printf (" return gen_rtx (PARALLEL, VOIDmode, gen_rtvec (%d", XVECLEN (insn, 1));
      for (i = 0; i < XVECLEN (insn, 1); i++)
    {
    printf (",ntt");
    gen_exp (XVECEXP (insn, 1, i));
    }
      printf ("));n}nn");
    }
}

/
Generate the gen_...' function for a DEFINE_EXPAND. */<br /><br />static void<br />gen_expand (expand)<br />&nbsp;&nbsp;&nbsp;&nbsp; rtx expand;<br />{<br />int operands;<br />register int i;<br /><br />if (strlen (XSTR (expand, 0)) == 0)<br />&nbsp;&nbsp;&nbsp; fatal (&quot;define_expand lacks a name&quot;);<br />if (XVEC (expand, 1) == 0)<br />&nbsp;&nbsp;&nbsp; fatal (&quot;define_expand for %s lacks a pattern&quot;, XSTR (expand, 0));<br /><br />/* Find out how many operands this function has,<br />&nbsp;&nbsp;&nbsp;&nbsp; and also whether any of them have register constraints. */<br />register_constraints = 0;<br /><br />operands = max_operand_vec (expand, 1);<br /><br />/* Output the function name and argument declarations. */<br />printf (&quot;rtxngen_%s (&quot;, XSTR (expand, 0));<br />for (i = 0; i &lt; operands; i++)<br />&nbsp;&nbsp;&nbsp; printf (i ? &quot;, operand%d&quot; : &quot;operand%d&quot;, i);<br />printf (&quot;)n&quot;);<br />for (i = 0; i &lt; operands; i++)<br />&nbsp;&nbsp;&nbsp; printf (&quot;&nbsp;&nbsp;&nbsp;&nbsp; rtx operand%d;n&quot;, i);<br />printf (&quot;{n&quot;);<br /><br />/* If we don't have any C code to write, only one insn is being written,<br />&nbsp;&nbsp;&nbsp;&nbsp; and no MATCH_DUPs are present, we can just return the desired insn<br />&nbsp;&nbsp;&nbsp;&nbsp; like we do for a DEFINE_INSN. This saves memory. */<br />if ((XSTR (expand, 3) == 0 || *XSTR (expand, 3) == '')<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&amp; operands &gt; max_dup_opno<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&amp; XVECLEN (expand, 1) == 1)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf (&quot; return &quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gen_exp (XVECEXP (expand, 1, 0));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf (&quot;;n}nn&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br />&nbsp;&nbsp;&nbsp; }<br /><br />/* For each operand referred to only with MATCH_DUPs,<br />&nbsp;&nbsp;&nbsp;&nbsp; make a local variable. */<br />for (i = operands; i &lt;= max_dup_opno; i++)<br />&nbsp;&nbsp;&nbsp; printf (&quot; rtx operand%d;n&quot;, i);<br />if (operands &gt; 0 || max_dup_opno &gt;= 0)<br />&nbsp;&nbsp;&nbsp; printf (&quot; rtx operands[%d];n&quot;, MAX (operands, max_dup_opno + 1));<br />printf (&quot; rtx _val = 0;n&quot;);<br />printf (&quot; start_sequence ();n&quot;);<br /><br />/* The fourth operand of DEFINE_EXPAND is some code to be executed<br />&nbsp;&nbsp;&nbsp;&nbsp; before the actual construction.<br />&nbsp;&nbsp;&nbsp;&nbsp; This code expects to refer tooperands’
     just as the output-code in a DEFINE_INSN does,
     but here operands' is an automatic array.<br />&nbsp;&nbsp;&nbsp;&nbsp; So copy the operand values there before executing it. */<br />if (XSTR (expand, 3) &amp;&amp; *XSTR (expand, 3))<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Output code to copy the arguments intooperands’. /
      for (i = 0; i < operands; i++)
    printf (" operands[%d] = operand%d;n", i, i);

      /
Output the special code to be executed before the sequence
    is generated. /
      printf ("%sn", XSTR (expand, 3));

      /
Output code to copy the arguments back out of operands'<br />&nbsp;&nbsp;&nbsp; (unless we aren't going to use them at all). */<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (XVEC (expand, 1) != 0)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp; for (i = 0; i &lt; operands; i++)<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf (&quot; operand%d = operands[%d];n&quot;, i, i);<br />&nbsp;&nbsp;&nbsp; for (; i &lt;= max_dup_opno; i++)<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf (&quot; operand%d = operands[%d];n&quot;, i, i);<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; }<br /><br />/* Output code to construct the rtl for the instruction bodies.<br />&nbsp;&nbsp;&nbsp;&nbsp; Use emit_insn to add them to the sequence being accumulated.<br />&nbsp;&nbsp;&nbsp;&nbsp; But don't do this if the user's code has setno_more’ nonzero. /

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
          && 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 (");
      else if (GET_CODE (next) == CODE_LABEL)
    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 (");
      gen_exp (next);
      printf (");n");
      if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC
    && GET_CODE (SET_SRC (next)) == LABEL_REF)
    printf (" emit_barrier ();");
    }

/
Call gen_sequence' to make a SEQUENCE out of all the<br />&nbsp;&nbsp;&nbsp;&nbsp; insns emitted within this gen_... function. */<br /><br />printf (&quot; _done:n&quot;);<br />printf (&quot; _val = gen_sequence ();n&quot;);<br />printf (&quot; _fail:n&quot;);<br />printf (&quot; end_sequence ();n&quot;);<br />printf (&quot; return _val;n}nn&quot;);<br />}<br /><br /><br /><br /> <hr /><br />/*<br />&nbsp;&nbsp; insn-emit.c<br />*/<br /><br />/* Generated automatically by the programgenemit’
from the machine description file `md’. /

#include "config.h"
#include "rtl.h"
#include "expr.h"
#include "real.h"
#include "output.h"
#include "insn-config.h"

#include "insn-flags.h"

#include "insn-codes.h"

extern char
insn_operand_constraint[][MAX_RECOG_OPERANDS];

extern rtx recog_operand[];
#define operands emit_operand

#define FAIL goto _fail

#define DONE goto _done

rtx
gen_adddf3 (operand0, operand1, operand2)
     rtx operand0;
     rtx operand1;
     rtx operand2;
{
return gen_rtx (SET, VOIDmode,
    operand0,
    gen_rtx (PLUS, DFmode,
    operand1,
    operand2));
}

rtx
gen_addsf3 (operand0, operand1, operand2)
     rtx operand0;
     rtx operand1;
     rtx operand2;
{
return gen_rtx (SET, VOIDmode,
    operand0,
    gen_rtx (PLUS, SFmode,
    operand1,
    operand2));
}



rtx
gen_adddi3 (operand0, operand1, operand2)
     rtx operand0;
     rtx operand1;
     rtx operand2;
{
rtx operand3;
rtx operands[4];
rtx _val = 0;
start_sequence ();
operands[0] = operand0;
operands[1] = operand1;
operands[2] = operand2;

{
if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == -32768)
    operands[2] = force_reg (DImode, operands[2]);

operands[3] = gen_reg_rtx (SImode);
}
operand0 = operands[0];
operand1 = operands[1];
operand2 = operands[2];
operand3 = operands[3];
emit (gen_rtx (PARALLEL, VOIDmode,
    gen_rtvec (2,
        gen_rtx (SET, VOIDmode,
    operand0,
    gen_rtx (PLUS, DImode,
    operand1,
    operand2)),
        gen_rtx (CLOBBER, VOIDmode,
    operand3))));
_done:
_val = gen_sequence ();
_fail:
end_sequence ();
return _val;
}



rtx
gen_branch_zero (operand0, operand1, operand2, operand3)
     rtx operand0;
     rtx operand1;
     rtx operand2;
     rtx operand3;
{
return gen_rtx (SET, VOIDmode,
    pc_rtx,
    gen_rtx (IF_THEN_ELSE, VOIDmode,
    gen_rtx (GET_CODE (operand0), SImode,
        operand1,
        const0_rtx),
    operand2,
    operand3));
}