_, _, _, _, _, _, _, _, _, _, 99, _, _, _, _, _, /* @abcdefghijklmno */
#endif
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
+#ifdef TC_HPPA
+ _,99, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* _!"#$%&'()*+,-./ */
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0123456789:;<=>? */
+#else
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
_, _, _, _, _, _, _, _, _, _, _, 99, _, _, _, _, /* 0123456789:;<=>? */
+#endif
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
register char c;
register char *s; /* string of symbol, '\0' appended */
register int temp;
- /* register struct frag * fragP; JF unused *//* a frag we just made */
pseudo_typeS *pop;
buffer = input_scrub_new_file (name);
register char *name;
register char c;
register char *p;
- register int temp;
+ valueT temp;
register symbolS *symbolP;
name = input_line_pointer;
#ifdef OBJ_COFF
c_dot_file_symbol (s);
#endif /* OBJ_COFF */
-} /* s_app_file() */
+#ifdef OBJ_ELF
+ elf_file_symbol (s);
+#endif
+}
/* Handle the .appline pseudo-op. This is automatically generated by
do_scrub_next_char when a preprocessor # line comment is seen.
void
s_globl ()
{
- register char *name;
- register int c;
- register symbolS *symbolP;
+ char *name;
+ int c;
+ symbolS *symbolP;
do
{
}
while (c == ',');
demand_empty_rest_of_line ();
-} /* s_globl() */
+}
void
s_lcomm (needs_align)
* in the case of a long. Not worth the crocks required to fix it.
*/
+/* Select a parser for cons expressions. */
+
+/* Some targets need to parse the expression in various fancy ways.
+ You can define TC_PARSE_CONS_EXPRESSION to do whatever you like
+ (for example, the HPPA does this). Otherwise, you can define
+ BITFIELD_CONS_EXPRESSIONS to permit bitfields to be specified, or
+ REPEAT_CONS_EXPRESSIONS to permit repeat counts. If none of these
+ are defined, which is the normal case, then only simple expressions
+ are permitted. */
+
+#ifndef TC_PARSE_CONS_EXPRESSION
+#ifdef BITFIELD_CONS_EXPRESSIONS
+#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_bitfield_cons (EXP, NBYTES)
+static void
+parse_bitfield_cons PARAMS ((expressionS *exp, unsigned int nbytes));
+#endif
+#ifdef MRI
+#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_mri_cons (EXP)
+static void
+parse_mri_cons PARAMS ((expressionS *exp));
+#endif
+#ifdef REPEAT_CONS_EXPRESSIONS
+#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_repeat_cons (EXP, NBYTES)
+static void
+parse_repeat_cons PARAMS ((expressionS *exp, unsigned int nbytes));
+#endif
+
+/* If we haven't gotten one yet, just call expression. */
+#ifndef TC_PARSE_CONS_EXPRESSION
+#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) expression (EXP)
+#endif
+#endif
+
/* worker to do .byte etc statements */
/* clobbers input_line_pointer, checks */
/* end-of-line. */
cons (nbytes)
register unsigned int nbytes; /* 1=.byte, 2=.word, 4=.long */
{
- register char c;
- register long mask; /* High-order bits we will left-truncate, */
- /* but includes sign bit also. */
- register long get; /* what we get */
- register long use; /* get after truncation. */
- register long unmask; /* what bits we will store */
- register char *p;
- register segT segment;
expressionS exp;
- /*
- * Input_line_pointer->1st char after pseudo-op-code and could legally
- * be a end-of-line. (Or, less legally an eof - which we cope with.)
- */
- /* JF << of >= number of bits in the object is undefined. In particular
- SPARC (Sun 4) has problems */
-
- if (nbytes >= sizeof (long))
+ if (is_it_end_of_statement ())
{
- mask = 0;
+ demand_empty_rest_of_line ();
+ return;
}
- else
+
+ do
{
- mask = ~0 << (BITS_PER_CHAR * nbytes); /* Don't store these bits. */
- } /* bigger than a long */
+ TC_PARSE_CONS_EXPRESSION (&exp, nbytes);
+ emit_expr (&exp, nbytes);
+ }
+ while (*input_line_pointer++ == ',');
- unmask = ~mask; /* Do store these bits. */
+ input_line_pointer--; /* Put terminator back into stream. */
+ demand_empty_rest_of_line ();
+} /* cons() */
-#ifdef NEVER
- "Do this mod if you want every overflow check to assume SIGNED 2's complement data.";
- mask = ~(unmask >> 1); /* Includes sign bit now. */
-#endif
+/* Put the contents of expression EXP into the object file using
+ NBYTES bytes. If need_pass_2 is 1, this does nothing. */
- /*
- * The following awkward logic is to parse ZERO or more expressions,
- * comma seperated. Recall an expression includes its leading &
- * trailing blanks. We fake a leading ',' if there is (supposed to
- * be) a 1st expression, and keep demanding 1 expression for each ','.
- */
- if (is_it_end_of_statement ())
+void
+emit_expr (exp, nbytes)
+ expressionS *exp;
+ unsigned int nbytes;
+{
+ segT segment;
+ register char *p;
+
+ /* Don't do anything if we are going to make another pass. */
+ if (need_pass_2)
+ return;
+
+ segment = exp->X_seg;
+
+ /* Don't call this if we are going to junk this pass anyway! */
+ know (segment != pass1_section);
+
+ if (segment == diff_section && exp->X_add_symbol == NULL)
{
- c = 0; /* Skip loop. */
- input_line_pointer++; /* Matches end-of-loop 'correction'. */
+ as_bad ("Subtracting symbol \"%s\" (segment \"%s\") is too hard. Absolute segment assumed.",
+ S_GET_NAME (exp->X_subtract_symbol),
+ segment_name (S_GET_SEGMENT (exp->X_subtract_symbol)));
+ segment = absolute_section;
+ /* Leave exp->X_add_number alone. */
}
- else
+ else if (segment == absent_section)
{
- c = ',';
- } /* if the end else fake it */
-
- /* Do loop. */
- while (c == ',')
+ as_warn ("0 assumed for missing expression");
+ exp->X_add_number = 0;
+ know (exp->X_add_symbol == NULL);
+ segment = absolute_section;
+ }
+ else if (segment == big_section)
{
-#ifdef WANT_BITFIELDS
- unsigned int bits_available = BITS_PER_CHAR * nbytes;
- /* used for error messages and rescanning */
- char *hold = input_line_pointer;
-#endif /* WANT_BITFIELDS */
-#ifdef MRI
- if (*input_line_pointer == '\'')
- {
- /* An MRI style string, cut into as many bytes as will fit
- into a nbyte chunk, left justify if necessary, and sepatate
- with commas so we can try again later */
- int scan = 0;
- unsigned int result = 0;
- input_line_pointer++;
- for (scan = 0; scan < nbytes; scan++)
- {
- if (*input_line_pointer == '\'')
- {
- if (input_line_pointer[1] == '\'')
- {
- input_line_pointer++;
- }
- else
- break;
- }
- result = (result << 8) | (*input_line_pointer++);
- }
+ as_bad ("%s number invalid. Absolute 0 assumed.",
+ exp->X_add_number > 0 ? "Bignum" : "Floating-Point");
+ exp->X_add_number = 0;
+ segment = absolute_section;
+ }
- /* Left justify */
- while (scan < nbytes)
- {
- result <<= 8;
- scan++;
- }
- /* Create correct expression */
- exp.X_add_symbol = 0;
- exp.X_add_number = result;
- exp.X_seg = segment = absolute_section;
- /* Fake it so that we can read the next char too */
- if (input_line_pointer[0] != '\'' ||
- (input_line_pointer[0] == '\'' && input_line_pointer[1] == '\''))
- {
- input_line_pointer -= 2;
- input_line_pointer[0] = ',';
- input_line_pointer[1] = '\'';
- }
- else
- input_line_pointer++;
+ p = frag_more (nbytes);
- }
- else
+#ifndef WORKING_DOT_WORD
+ /* If we have the difference of two symbols in a word, save it on
+ the broken_words list. See the code in write.c. */
+ if (segment == diff_section && nbytes == 2)
+ {
+ struct broken_word *x;
+
+ x = (struct broken_word *) xmalloc (sizeof (struct broken_word));
+ x->next_broken_word = broken_words;
+ broken_words = x;
+ x->frag = frag_now;
+ x->word_goes_here = p;
+ x->dispfrag = 0;
+ x->add = exp->X_add_symbol;
+ x->sub = exp->X_subtract_symbol;
+ x->addnum = exp->X_add_number;
+ x->added = 0;
+ new_broken_words++;
+ return;
+ }
#endif
- /* At least scan over the expression. */
- segment = expression (&exp);
-
-#ifdef WANT_BITFIELDS
- /* Some other assemblers, (eg, asm960), allow
- bitfields after ".byte" as w:x,y:z, where w and
- y are bitwidths and x and y are values. They
- then pack them all together. We do a little
- better in that we allow them in words, longs,
- etc. and we'll pack them in target byte order
- for you.
-
- The rules are: pack least significat bit first,
- if a field doesn't entirely fit, put it in the
- next unit. Overflowing the bitfield is
- explicitly *not* even a warning. The bitwidth
- should be considered a "mask".
-
- FIXME-SOMEDAY: If this is considered generally
- useful, this logic should probably be reworked.
- xoxorich. */
-
- if (*input_line_pointer == ':')
- { /* bitfields */
- long value = 0;
-
- for (;;)
- {
- unsigned long width;
- if (*input_line_pointer != ':')
- {
- input_line_pointer = hold;
- break;
- } /* next piece is not a bitfield */
-
- /* In the general case, we can't allow
- full expressions with symbol
- differences and such. The relocation
- entries for symbols not defined in this
- assembly would require arbitrary field
- widths, positions, and masks which most
- of our current object formats don't
- support.
-
- In the specific case where a symbol
- *is* defined in this assembly, we
- *could* build fixups and track it, but
- this could lead to confusion for the
- backends. I'm lazy. I'll take any
- SEG_ABSOLUTE. I think that means that
- you can use a previous .set or
- .equ type symbol. xoxorich. */
-
- if (segment == absent_section)
- {
- as_warn ("Using a bit field width of zero.");
- exp.X_add_number = 0;
- segment = absolute_section;
- } /* implied zero width bitfield */
+ if (segment == absolute_section)
+ {
+ register long get;
+ register long use;
+ register long mask;
+ register long unmask;
- if (segment != absolute_section)
- {
- *input_line_pointer = '\0';
- as_bad ("Field width \"%s\" too complex for a bitfield.\n", hold);
- *input_line_pointer = ':';
- demand_empty_rest_of_line ();
- return;
- } /* too complex */
+ /* JF << of >= number of bits in the object is undefined. In
+ particular SPARC (Sun 4) has problems */
+ if (nbytes >= sizeof (long))
+ mask = 0;
+ else
+ mask = ~0 << (BITS_PER_CHAR * nbytes); /* Don't store these bits. */
- if ((width = exp.X_add_number) > (BITS_PER_CHAR * nbytes))
- {
- as_warn ("Field width %d too big to fit in %d bytes: truncated to %d bits.",
- width, nbytes, (BITS_PER_CHAR * nbytes));
- width = BITS_PER_CHAR * nbytes;
- } /* too big */
+ unmask = ~mask; /* Do store these bits. */
- if (width > bits_available)
- {
- /* FIXME-SOMEDAY: backing up and
- reparsing is wasteful */
- input_line_pointer = hold;
- exp.X_add_number = value;
- break;
- } /* won't fit */
+#ifdef NEVER
+ "Do this mod if you want every overflow check to assume SIGNED 2's complement data.";
+ mask = ~(unmask >> 1); /* Includes sign bit now. */
+#endif
+
+ get = exp->X_add_number;
+ use = get & unmask;
+ if ((get & mask) != 0 && (get & mask) != mask)
+ { /* Leading bits contain both 0s & 1s. */
+ as_warn ("Value 0x%x truncated to 0x%x.", get, use);
+ }
+ md_number_to_chars (p, use, nbytes); /* put bytes in right order. */
+ }
+ else
+ {
+ md_number_to_chars (p, (long) 0, nbytes);
- hold = ++input_line_pointer; /* skip ':' */
+ /* Now we need to generate a fixS to record the symbol value.
+ This is easy for BFD. For other targets it can be more
+ complex. For very complex cases (currently, the HPPA and
+ NS32K), you can define TC_CONS_FIX_NEW to do whatever you
+ want. For simpler cases, you can define TC_CONS_RELOC to be
+ the name of the reloc code that should be stored in the fixS.
+ If neither is defined, the code uses NO_RELOC if it is
+ defined, and otherwise uses 0. */
- if ((segment = expression (&exp)) != absolute_section)
- {
- char cache = *input_line_pointer;
+#ifdef BFD_ASSEMBLER
+ fix_new (frag_now, p - frag_now->fr_literal, nbytes,
+ exp->X_add_symbol, exp->X_subtract_symbol,
+ exp->X_add_number, 0,
+ /* @@ Should look at CPU word size. */
+ BFD_RELOC_32);
+#else
+#ifdef TC_CONS_FIX_NEW
+ TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp);
+#else
+ /* Figure out which reloc number to use. Use TC_CONS_RELOC if
+ it is defined, otherwise use NO_RELOC if it is defined,
+ otherwise use 0. */
+#ifndef TC_CONS_RELOC
+#ifdef NO_RELOC
+#define TC_CONS_RELOC NO_RELOC
+#else
+#define TC_CONS_RELOC 0
+#endif
+#endif
+ fix_new (frag_now, p - frag_now->fr_literal, nbytes,
+ exp->X_add_symbol, exp->X_subtract_symbol,
+ exp->X_add_number, 0, TC_CONS_RELOC);
+#endif /* TC_CONS_FIX_NEW */
+#endif /* BFD_ASSEMBLER */
+ }
+}
+\f
+#ifdef BITFIELD_CONS_EXPRESSIONS
- *input_line_pointer = '\0';
- as_bad ("Field value \"%s\" too complex for a bitfield.\n", hold);
- *input_line_pointer = cache;
- demand_empty_rest_of_line ();
- return;
- } /* too complex */
+/* i960 assemblers, (eg, asm960), allow bitfields after ".byte" as
+ w:x,y:z, where w and y are bitwidths and x and y are values. They
+ then pack them all together. We do a little better in that we allow
+ them in words, longs, etc. and we'll pack them in target byte order
+ for you.
- value |= (~(-1 << width) & exp.X_add_number)
- << ((BITS_PER_CHAR * nbytes) - bits_available);
+ The rules are: pack least significat bit first, if a field doesn't
+ entirely fit, put it in the next unit. Overflowing the bitfield is
+ explicitly *not* even a warning. The bitwidth should be considered
+ a "mask".
- if ((bits_available -= width) == 0
- || is_it_end_of_statement ()
- || *input_line_pointer != ',')
- {
- break;
- } /* all the bitfields we're gonna get */
+ To use this function the tc-XXX.h file should define
+ BITFIELD_CONS_EXPRESSIONS. */
- hold = ++input_line_pointer;
- segment = expression (&exp);
- } /* forever loop */
+static void
+parse_bitfield_cons (exp, nbytes)
+ expressionS *exp;
+ unsigned int nbytes;
+{
+ unsigned int bits_available = BITS_PER_CHAR * nbytes;
+ char *hold = input_line_pointer;
+ segT segment;
- exp.X_add_number = value;
- segment = absolute_section;
- } /* if looks like a bitfield */
-#endif /* WANT_BITFIELDS */
+ segment = expression (exp);
- if (!need_pass_2)
- { /* Still worthwhile making frags. */
+ if (*input_line_pointer == ':')
+ { /* bitfields */
+ long value = 0;
- /* Don't call this if we are going to junk this pass anyway! */
- know (segment != pass1_section);
+ for (;;)
+ {
+ unsigned long width;
- if (segment == diff_section && exp.X_add_symbol == NULL)
+ if (*input_line_pointer != ':')
{
- as_bad ("Subtracting symbol \"%s\"(segment\"%s\") is too hard. Absolute segment assumed.",
- S_GET_NAME (exp.X_subtract_symbol),
- segment_name (S_GET_SEGMENT (exp.X_subtract_symbol)));
+ input_line_pointer = hold;
+ break;
+ } /* next piece is not a bitfield */
+
+ /* In the general case, we can't allow
+ full expressions with symbol
+ differences and such. The relocation
+ entries for symbols not defined in this
+ assembly would require arbitrary field
+ widths, positions, and masks which most
+ of our current object formats don't
+ support.
+
+ In the specific case where a symbol
+ *is* defined in this assembly, we
+ *could* build fixups and track it, but
+ this could lead to confusion for the
+ backends. I'm lazy. I'll take any
+ SEG_ABSOLUTE. I think that means that
+ you can use a previous .set or
+ .equ type symbol. xoxorich. */
+
+ if (segment == absent_section)
+ {
+ as_warn ("Using a bit field width of zero.");
+ exp->X_add_number = 0;
segment = absolute_section;
- /* Leave exp . X_add_number alone. */
- }
- p = frag_more (nbytes);
- if (segment == big_section)
+ } /* implied zero width bitfield */
+
+ if (segment != absolute_section)
{
- as_bad ("%s number invalid. Absolute 0 assumed.",
- exp.X_add_number > 0 ? "Bignum" : "Floating-Point");
- md_number_to_chars (p, (long) 0, nbytes);
- }
- else if (segment == absent_section)
+ *input_line_pointer = '\0';
+ as_bad ("Field width \"%s\" too complex for a bitfield.\n", hold);
+ *input_line_pointer = ':';
+ demand_empty_rest_of_line ();
+ return;
+ } /* too complex */
+
+ if ((width = exp->X_add_number) > (BITS_PER_CHAR * nbytes))
{
- as_warn ("0 assumed for missing expression");
- exp.X_add_number = 0;
- know (exp.X_add_symbol == NULL);
- goto abs_sec;
- }
- else if (segment == absolute_section)
+ as_warn ("Field width %d too big to fit in %d bytes: truncated to %d bits.",
+ width, nbytes, (BITS_PER_CHAR * nbytes));
+ width = BITS_PER_CHAR * nbytes;
+ } /* too big */
+
+ if (width > bits_available)
{
- abs_sec:
- get = exp.X_add_number;
- use = get & unmask;
- if ((get & mask) && (get & mask) != mask)
- { /* Leading bits contain both 0s & 1s. */
- as_warn ("Value 0x%x truncated to 0x%x.", get, use);
- }
- md_number_to_chars (p, use, nbytes); /* put bytes in right order. */
- }
- else if (segment == diff_section)
+ /* FIXME-SOMEDAY: backing up and reparsing is wasteful. */
+ input_line_pointer = hold;
+ exp->X_add_number = value;
+ break;
+ } /* won't fit */
+
+ hold = ++input_line_pointer; /* skip ':' */
+
+ if ((segment = expression (exp)) != absolute_section)
{
-#ifndef WORKING_DOT_WORD
- if (nbytes == 2)
+ char cache = *input_line_pointer;
+
+ *input_line_pointer = '\0';
+ as_bad ("Field value \"%s\" too complex for a bitfield.\n", hold);
+ *input_line_pointer = cache;
+ demand_empty_rest_of_line ();
+ return;
+ } /* too complex */
+
+ value |= (~(-1 << width) & exp->X_add_number)
+ << ((BITS_PER_CHAR * nbytes) - bits_available);
+
+ if ((bits_available -= width) == 0
+ || is_it_end_of_statement ()
+ || *input_line_pointer != ',')
+ {
+ break;
+ } /* all the bitfields we're gonna get */
+
+ hold = ++input_line_pointer;
+ segment = expression (exp);
+ } /* forever loop */
+
+ exp->X_add_number = value;
+ exp->X_seg = absolute_section;
+ } /* if looks like a bitfield */
+} /* parse_bitfield_cons() */
+
+#endif /* BITFIELD_CONS_EXPRESSIONS */
+\f
+#ifdef MRI
+
+static void
+parse_mri_cons (exp, nbytes)
+ expressionS *exp;
+ unsigned int nbytes;
+{
+ if (*input_line_pointer == '\'')
+ {
+ /* An MRI style string, cut into as many bytes as will fit into
+ a nbyte chunk, left justify if necessary, and separate with
+ commas so we can try again later */
+ int scan = 0;
+ unsigned int result = 0;
+ input_line_pointer++;
+ for (scan = 0; scan < nbytes; scan++)
+ {
+ if (*input_line_pointer == '\'')
+ {
+ if (input_line_pointer[1] == '\'')
{
- struct broken_word *x;
-
- x = (struct broken_word *) xmalloc (sizeof (struct broken_word));
- x->next_broken_word = broken_words;
- broken_words = x;
- x->frag = frag_now;
- x->word_goes_here = p;
- x->dispfrag = 0;
- x->add = exp.X_add_symbol;
- x->sub = exp.X_subtract_symbol;
- x->addnum = exp.X_add_number;
- x->added = 0;
- new_broken_words++;
- goto after_switch;
+ input_line_pointer++;
}
-#endif
- goto defalt;
+ else
+ break;
}
- else
- /* undefined_section, others */
- {
- defalt:
- md_number_to_chars (p, (long) 0, nbytes);
-#ifdef BFD_ASSEMBLER
- fix_new (frag_now, p - frag_now->fr_literal, nbytes,
- exp.X_add_symbol, exp.X_subtract_symbol,
- exp.X_add_number, 0,
- /* @@ Should look at CPU word size. */
- BFD_RELOC_32);
-#else
-#ifdef TC_NS32K
- fix_new_ns32k (frag_now, p - frag_now->fr_literal, nbytes,
- exp.X_add_symbol, exp.X_subtract_symbol,
- exp.X_add_number, 0, 0, 2, 0, 0);
-#else
-#if defined(TC_SPARC) || defined(TC_A29K)
- fix_new (frag_now, p - frag_now->fr_literal, nbytes,
- exp.X_add_symbol, exp.X_subtract_symbol,
- exp.X_add_number, 0, RELOC_32);
-#else
-#if defined(TC_H8300)
- fix_new (frag_now, p - frag_now->fr_literal, nbytes,
- exp.X_add_symbol, exp.X_subtract_symbol,
- exp.X_add_number, 0, R_RELWORD);
+ result = (result << 8) | (*input_line_pointer++);
+ }
-#else
-#ifdef NO_RELOC
- fix_new (frag_now, p - frag_now->fr_literal, nbytes,
- exp.X_add_symbol, exp.X_subtract_symbol,
- exp.X_add_number, 0, NO_RELOC);
-#else
- fix_new (frag_now, p - frag_now->fr_literal, nbytes,
- exp.X_add_symbol, exp.X_subtract_symbol,
- exp.X_add_number, 0, 0);
-#endif /* NO_RELOC */
-#endif /* tc_h8300 */
-#endif /* tc_sparc|tc_a29k */
-#endif /* TC_NS32K */
-#endif /* BFD_ASSEMBLER */
- } /* switch(segment) */
- after_switch:
- ;
- } /* if (!need_pass_2) */
- c = *input_line_pointer++;
- } /* while(c==',') */
- input_line_pointer--; /* Put terminator back into stream. */
- demand_empty_rest_of_line ();
-} /* cons() */
+ /* Left justify */
+ while (scan < nbytes)
+ {
+ result <<= 8;
+ scan++;
+ }
+ /* Create correct expression */
+ exp->X_add_symbol = 0;
+ exp->X_add_number = result;
+ exp->X_seg = absolute_section;
+ /* Fake it so that we can read the next char too */
+ if (input_line_pointer[0] != '\'' ||
+ (input_line_pointer[0] == '\'' && input_line_pointer[1] == '\''))
+ {
+ input_line_pointer -= 2;
+ input_line_pointer[0] = ',';
+ input_line_pointer[1] = '\'';
+ }
+ else
+ input_line_pointer++;
+ }
+ else
+ expression (&exp);
+}
+
+#endif /* MRI */
+\f
+#ifdef REPEAT_CONS_EXPRESSIONS
+
+/* Parse a repeat expression for cons. This is used by the MIPS
+ assembler. The format is NUMBER:COUNT; NUMBER appears in the
+ object file COUNT times.
+
+ To use this for a target, define REPEAT_CONS_EXPRESSIONS. */
+
+static void
+parse_repeat_cons (exp, nbytes)
+ expressionS *exp;
+ unsigned int nbytes;
+{
+ expressionS count;
+ segT segment;
+ register int i;
+
+ expression (exp);
+
+ if (*input_line_pointer != ':')
+ {
+ /* No repeat count. */
+ return;
+ }
+
+ ++input_line_pointer;
+ segment = expression (&count);
+ if (segment != absolute_section
+ || count.X_add_number <= 0)
+ {
+ as_warn ("Unresolvable or nonpositive repeat count; using 1");
+ return;
+ }
+
+ /* The cons function is going to output this expression once. So we
+ output it count - 1 times. */
+ for (i = count.X_add_number - 1; i > 0; i--)
+ emit_expr (exp, nbytes);
+}
+
+#endif /* REPEAT_CONS_EXPRESSIONS */
\f
/*
* big_cons()