Back to index

cell-binutils  2.17cvs20070401
Classes | Defines | Functions | Variables
tc-mmix.h File Reference

Go to the source code of this file.

Classes

struct  mmix_segment_info_type

Defines

#define TC_MMIX
#define TARGET_FORMAT   "elf64-mmix"
#define TARGET_ARCH   bfd_arch_mmix
#define TARGET_BYTES_BIG_ENDIAN   1
#define tc_comment_chars   mmix_comment_chars
#define tc_symbol_chars   mmix_symbol_chars
#define EXP_CHARS   mmix_exp_chars
#define FLT_CHARS   mmix_flt_chars
#define LEX_AT   (LEX_BEGIN_NAME)
#define LABELS_WITHOUT_COLONS   mmix_label_without_colon_this_line ()
#define TC_EOL_IN_INSN(p)   (*(p) == ';' && ! mmix_next_semicolon_is_eoln)
#define md_start_line_hook   mmix_handle_mmixal
#define md_begin   mmix_md_begin
#define md_end   mmix_md_end
#define md_parse_name(name, exp, mode, cpos)
#define tc_canonicalize_symbol_name(x)   (mmix_current_prefix == NULL && (x)[0] != ':' ? (x) : mmix_prefix_name (x))
#define md_undefined_symbol(x)   NULL
#define md_operand(exp)
#define tc_unrecognized_line(c)
#define md_number_to_chars   number_to_chars_bigendian
#define WORKING_DOT_WORD
#define TC_GENERIC_RELAX_TABLE   mmix_relax_table
#define md_relax_frag   mmix_md_relax_frag
#define tc_fix_adjustable(FIX)
#define tc_adjust_symtab()   mmix_adjust_symtab ()
#define tc_frob_symbol(sym, punt)
#define EXTERN_FORCE_RELOC   0
#define TC_FORCE_RELOCATION(fix)   mmix_force_relocation (fix)
#define MD_PCREL_FROM_SECTION(FIX, SEC)   md_pcrel_from_section (FIX, SEC)
#define md_section_align(seg, size)   (size)
#define LISTING_HEADER   "GAS for MMIX"
#define LISTING_LHS_CONT_LINES   5
#define TC_FRAG_TYPE   fragS *
#define TC_FRAG_INIT(frag)   (frag)->tc_frag_data = mmix_opcode_frag
#define tc_frob_file_before_fix   mmix_frob_file
#define TC_SYMFIELD_TYPE   struct mmix_symbol_gregs *
#define TC_SEGMENT_INFO_TYPE   struct mmix_segment_info_type
#define md_elf_section_change_hook   mmix_md_elf_section_change_hook
#define md_do_align(n, fill, len, max, label)   mmix_md_do_align (n, fill, len, max)
#define DWARF2_LINE_MIN_INSN_LENGTH   1
#define TC_FX_SIZE_SLACK(FIX)   6

Functions

int mmix_label_without_colon_this_line (void)
void mmix_handle_mmixal (void)
void mmix_md_begin (void)
void mmix_md_end (void)
int mmix_current_location (void(*fn)(expressionS *), expressionS *)
int mmix_parse_predefined_name (char *, expressionS *)
char * mmix_prefix_name (char *)
void mmix_fb_label (expressionS *)
int mmix_assemble_return_nonzero (char *)
long mmix_md_relax_frag (segT, fragS *, long)
void mmix_adjust_symtab (void)
int mmix_force_relocation (struct fix *)
long md_pcrel_from_section (struct fix *, segT)
void mmix_frob_file (void)
void mmix_md_elf_section_change_hook (void)
void mmix_md_do_align (int, char *, int, int)

Variables

const char mmix_comment_chars []
const char mmix_symbol_chars []
const char mmix_exp_chars []
const char mmix_flt_chars []
int mmix_next_semicolon_is_eoln
char * mmix_current_prefix
int mmix_gnu_syntax
int mmix_globalize_symbols
fragS * mmix_opcode_frag

Class Documentation

struct mmix_segment_info_type

Definition at line 203 of file tc-mmix.h.

Class Members
fragS * last_stubfrag
bfd_size_type nstubs

Define Documentation

Definition at line 223 of file tc-mmix.h.

#define EXP_CHARS   mmix_exp_chars

Definition at line 36 of file tc-mmix.h.

#define EXTERN_FORCE_RELOC   0

Definition at line 169 of file tc-mmix.h.

#define FLT_CHARS   mmix_flt_chars

Definition at line 39 of file tc-mmix.h.

Definition at line 45 of file tc-mmix.h.

#define LEX_AT   (LEX_BEGIN_NAME)

Definition at line 42 of file tc-mmix.h.

#define LISTING_HEADER   "GAS for MMIX"

Definition at line 181 of file tc-mmix.h.

#define LISTING_LHS_CONT_LINES   5

Definition at line 184 of file tc-mmix.h.

#define md_begin   mmix_md_begin

Definition at line 55 of file tc-mmix.h.

#define md_do_align (   n,
  fill,
  len,
  max,
  label 
)    mmix_md_do_align (n, fill, len, max)

Definition at line 217 of file tc-mmix.h.

Definition at line 214 of file tc-mmix.h.

#define md_end   mmix_md_end

Definition at line 58 of file tc-mmix.h.

Definition at line 119 of file tc-mmix.h.

#define md_operand (   exp)
Value:
do                                                             \
    {                                                          \
      if (input_line_pointer[0] == '#')                               \
       {                                                       \
         input_line_pointer++;                                        \
         integer_constant (16, (exp));                                \
       }                                                       \
      else if (input_line_pointer[0] == '&'                           \
              && input_line_pointer[1] != '&')                        \
       as_bad (_("`&' serial number operator is not supported"));     \
      else								\
	mmix_fb_label (exp);                                          \
    }                                                          \
  while (0)

Definition at line 94 of file tc-mmix.h.

#define md_parse_name (   name,
  exp,
  mode,
  cpos 
)
Value:
(! mmix_gnu_syntax                                      \
  && (name[0] == '@'                                    \
      ? (! is_part_of_name (name[1])                           \
        && mmix_current_location (current_location, exp))      \
      : ((name[0] == ':' || ISUPPER (name[0]))                 \
        && mmix_parse_predefined_name (name, exp))))

Definition at line 73 of file tc-mmix.h.

#define MD_PCREL_FROM_SECTION (   FIX,
  SEC 
)    md_pcrel_from_section (FIX, SEC)

Definition at line 176 of file tc-mmix.h.

Definition at line 128 of file tc-mmix.h.

#define md_section_align (   seg,
  size 
)    (size)

Definition at line 179 of file tc-mmix.h.

Definition at line 52 of file tc-mmix.h.

#define md_undefined_symbol (   x)    NULL

Definition at line 88 of file tc-mmix.h.

#define TARGET_ARCH   bfd_arch_mmix

Definition at line 26 of file tc-mmix.h.

#define TARGET_BYTES_BIG_ENDIAN   1

Definition at line 27 of file tc-mmix.h.

#define TARGET_FORMAT   "elf64-mmix"

Definition at line 25 of file tc-mmix.h.

#define tc_adjust_symtab ( )    mmix_adjust_symtab ()

Definition at line 138 of file tc-mmix.h.

#define tc_canonicalize_symbol_name (   x)    (mmix_current_prefix == NULL && (x)[0] != ':' ? (x) : mmix_prefix_name (x))

Definition at line 85 of file tc-mmix.h.

Definition at line 30 of file tc-mmix.h.

#define TC_EOL_IN_INSN (   p)    (*(p) == ';' && ! mmix_next_semicolon_is_eoln)

Definition at line 48 of file tc-mmix.h.

#define tc_fix_adjustable (   FIX)
Value:
(((FIX)->fx_addsy == NULL                               \
   || S_GET_SEGMENT ((FIX)->fx_addsy) != reg_section)          \
  && (FIX)->fx_r_type != BFD_RELOC_VTABLE_INHERIT              \
  && (FIX)->fx_r_type != BFD_RELOC_VTABLE_ENTRY                \
  && (FIX)->fx_r_type != BFD_RELOC_MMIX_LOCAL)

Definition at line 130 of file tc-mmix.h.

Definition at line 172 of file tc-mmix.h.

#define TC_FRAG_INIT (   frag)    (frag)->tc_frag_data = mmix_opcode_frag

Definition at line 188 of file tc-mmix.h.

#define TC_FRAG_TYPE   fragS *

Definition at line 187 of file tc-mmix.h.

Definition at line 196 of file tc-mmix.h.

#define tc_frob_symbol (   sym,
  punt 
)
Value:
do                                                      \
    {                                                   \
      if (S_GET_SEGMENT (sym) == reg_section)                  \
       {                                                \
         if (S_GET_NAME (sym)[0] != '$'                 \
             && S_GET_VALUE (sym) < 256)                \
           {                                            \
             if (mmix_globalize_symbols)                \
              S_SET_EXTERNAL (sym);                            \
	      else						\
		symbol_mark_used_in_reloc (sym);        \
           }                                            \
       }                                                \
      else if (mmix_globalize_symbols                          \
              && ! symbol_section_p (sym)               \
              && sym != section_symbol (absolute_section)      \
              && ! S_IS_LOCAL (sym))                           \
       S_SET_EXTERNAL (sym);                                   \
    }                                                   \
  while (0)

Definition at line 145 of file tc-mmix.h.

#define TC_FX_SIZE_SLACK (   FIX)    6

Definition at line 226 of file tc-mmix.h.

Definition at line 124 of file tc-mmix.h.

#define TC_MMIX

Definition at line 22 of file tc-mmix.h.

Definition at line 211 of file tc-mmix.h.

Definition at line 33 of file tc-mmix.h.

Definition at line 200 of file tc-mmix.h.

#define tc_unrecognized_line (   c)
Value:
((c) == ' '                                                    \
  || (((c) == '1' || (c) == '2' || (c) == '4' || (c) == '8')          \
      && mmix_assemble_return_nonzero (input_line_pointer - 1)))

Definition at line 114 of file tc-mmix.h.

Definition at line 121 of file tc-mmix.h.


Function Documentation

void mmix_adjust_symtab ( void  )

Definition at line 3303 of file tc-mmix.c.

{
  symbolS *sym;
  symbolS *regsec = section_symbol (reg_section);

  for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
    if (S_GET_SEGMENT (sym) == reg_section)
      {
       if (sym == regsec)
         {
           if (S_IS_EXTERNAL (sym) || symbol_used_in_reloc_p (sym))
             abort ();
           symbol_remove (sym, &symbol_rootP, &symbol_lastP);
         }
       else
         /* Change section to the *real* register section, so it gets
            proper treatment when writing it out.  Only do this for
            global symbols.  This also means we don't have to check for
            $0..$255.  */
         S_SET_SEGMENT (sym, real_reg_section);
      }
}

Here is the call graph for this function:

Definition at line 1891 of file tc-mmix.c.

{
  int last_error_count = had_errors ();
  char *s2 = str;
  char c;

  /* Normal instruction handling downcases, so we must too.  */
  while (ISALNUM (*s2))
    {
      if (ISUPPER ((unsigned char) *s2))
       *s2 = TOLOWER (*s2);
      s2++;
    }

  /* Cut the line for sake of the assembly.  */
  for (s2 = str; *s2 && *s2 != '\n'; s2++)
    ;

  c = *s2;
  *s2 = 0;
  md_assemble (str);
  *s2 = c;

  return had_errors () == last_error_count;
}

Here is the call graph for this function:

int mmix_current_location ( void(*)(expressionS *)  fn,
expressionS  
)

Definition at line 440 of file tc-mmix.c.

{
  (*fn) (exp);

  return 1;
}
void mmix_fb_label ( expressionS )

Definition at line 3213 of file tc-mmix.c.

{
  symbolS *sym;
  char *fb_internal_name;

  /* This doesn't happen when not using mmixal syntax.  */
  if (mmix_gnu_syntax
      || (input_line_pointer[0] != MAGIC_FB_BACKWARD_CHAR
         && input_line_pointer[0] != MAGIC_FB_FORWARD_CHAR))
    return;

  /* The current backward reference has augmentation 0.  A forward
     reference has augmentation 1, unless it's the same as a fb-label on
     _this_ line, in which case we add one more so we don't refer to it.
     This is the semantics of mmixal; it differs to that of common
     fb-labels which refer to a here-label on the current line as a
     backward reference.  */
  fb_internal_name
    = fb_label_name (input_line_pointer[1] - '0',
                   (input_line_pointer[0] == MAGIC_FB_FORWARD_CHAR ? 1 : 0)
                   + ((input_line_pointer[1] - '0' == current_fb_label
                      && input_line_pointer[0] == MAGIC_FB_FORWARD_CHAR)
                     ? 1 : 0));

  input_line_pointer += 2;
  sym = symbol_find_or_make (fb_internal_name);

  /* We don't have to clean up unrelated fields here; we just do what the
     expr machinery does, but *not* just what it does for [0-9][fb], since
     we need to treat those as ordinary symbols sometimes; see testcases
     err-byte2.s and fb-2.s.  */
  if (S_GET_SEGMENT (sym) == absolute_section)
    {
      expP->X_op = O_constant;
      expP->X_add_number = S_GET_VALUE (sym);
    }
  else
    {
      expP->X_op = O_symbol;
      expP->X_add_symbol = sym;
      expP->X_add_number = 0;
    }
}

Here is the call graph for this function:

void mmix_frob_file ( void  )

Definition at line 3667 of file tc-mmix.c.

{
  int i;
  struct mmix_symbol_gregs *all_greg_symbols[MAX_GREGS];
  int n_greg_symbols = 0;

  /* Collect all greg fixups and decorate each corresponding symbol with
     the greg fixups for it.  */
  for (i = 0; i < n_of_cooked_gregs; i++)
    {
      offsetT offs;
      symbolS *sym;
      struct mmix_symbol_gregs *gregs;
      fixS *fixP;

      fixP = mmix_gregs[i];
      know (fixP->fx_r_type == BFD_RELOC_64);

      /* This case isn't doable in general anyway, methinks.  */
      if (fixP->fx_subsy != NULL)
       {
         as_bad_where (fixP->fx_file, fixP->fx_line,
                     _("GREG expression too complicated"));
         continue;
       }

      sym = fixP->fx_addsy;
      offs = (offsetT) fixP->fx_offset;

      /* If the symbol is defined, then it must be resolved to a section
        symbol at this time, or else we don't know how to handle it.  */
      if (S_IS_DEFINED (sym)
         && !bfd_is_com_section (S_GET_SEGMENT (sym))
         && !S_IS_WEAK (sym))
       {
         if (! symbol_section_p (sym)
             && ! bfd_is_abs_section (S_GET_SEGMENT (sym)))
           as_fatal (_("internal: GREG expression not resolved to section"));

         offs += S_GET_VALUE (sym);
       }

      /* If this is an absolute symbol sufficiently near lowest_data_loc,
        then we canonicalize on the data section.  Note that offs is
        signed here; we may subtract lowest_data_loc which is unsigned.
        Careful with those comparisons.  */
      if (lowest_data_loc != (bfd_vma) -1
         && (bfd_vma) offs + 256 > lowest_data_loc
         && bfd_is_abs_section (S_GET_SEGMENT (sym)))
       {
         offs -= (offsetT) lowest_data_loc;
         sym = section_symbol (data_section);
       }
      /* Likewise text section.  */
      else if (lowest_text_loc != (bfd_vma) -1
              && (bfd_vma) offs + 256 > lowest_text_loc
              && bfd_is_abs_section (S_GET_SEGMENT (sym)))
       {
         offs -= (offsetT) lowest_text_loc;
         sym = section_symbol (text_section);
       }

      gregs = *symbol_get_tc (sym);

      if (gregs == NULL)
       {
         gregs = xmalloc (sizeof (*gregs));
         gregs->n_gregs = 0;
         symbol_set_tc (sym, &gregs);
         all_greg_symbols[n_greg_symbols++] = gregs;
       }

      gregs->greg_fixes[gregs->n_gregs].fix = fixP;
      gregs->greg_fixes[gregs->n_gregs++].offs = offs;
    }

  /* For each symbol having a GREG definition, sort those definitions on
     offset.  */
  for (i = 0; i < n_greg_symbols; i++)
    qsort (all_greg_symbols[i]->greg_fixes, all_greg_symbols[i]->n_gregs,
          sizeof (all_greg_symbols[i]->greg_fixes[0]), cmp_greg_symbol_fixes);

  if (real_reg_section != NULL)
    {
      /* FIXME: Pass error state gracefully.  */
      if (bfd_get_section_flags (stdoutput, real_reg_section) & SEC_HAS_CONTENTS)
       as_fatal (_("register section has contents\n"));

      bfd_section_list_remove (stdoutput, real_reg_section);
      --stdoutput->section_count;
    }

}

Here is the call graph for this function:

void mmix_handle_mmixal ( void  )

Definition at line 2900 of file tc-mmix.c.

{
  char *insn;
  char *s = input_line_pointer;
  char *label = NULL;
  char c;

  if (pending_label != NULL)
    as_fatal (_("internal: unhandled label %s"), pending_label);

  if (mmix_gnu_syntax)
    return;

  /* If we're on a line with a label, check if it's a mmixal fb-label.
     Save an indicator and skip the label; it must be set only after all
     fb-labels of expressions are evaluated.  */
  if (ISDIGIT (s[0]) && s[1] == 'H' && ISSPACE (s[2]))
    {
      current_fb_label = s[0] - '0';

      /* We have to skip the label, but also preserve the newlineness of
        the previous character, since the caller checks that.  It's a
        mess we blame on the caller.  */
      s[1] = s[-1];
      s += 2;
      input_line_pointer = s;

      while (*s && ISSPACE (*s) && ! is_end_of_line[(unsigned int) *s])
       s++;

      /* For errors emitted here, the book-keeping is off by one; the
        caller is about to bump the counters.  Adjust the error messages.  */
      if (is_end_of_line[(unsigned int) *s])
       {
         char *name;
         unsigned int line;
         as_where (&name, &line);
         as_bad_where (name, line + 1,
                     _("[0-9]H labels may not appear alone on a line"));
         current_fb_label = -1;
       }
      if (*s == '.')
       {
         char *name;
         unsigned int line;
         as_where (&name, &line);
         as_bad_where (name, line + 1,
                     _("[0-9]H labels do not mix with dot-pseudos"));
         current_fb_label = -1;
       }

      /* Back off to the last space before the opcode so we don't handle
        the opcode as a label.  */
      s--;
    }
  else
    current_fb_label = -1;

  if (*s == '.')
    {
      /* If the first character is a '.', then it's a pseudodirective, not a
        label.  Make GAS not handle label-without-colon on this line.  We
        also don't do mmixal-specific stuff on this line.  */
      label_without_colon_this_line = 0;
      return;
    }

  if (*s == 0 || is_end_of_line[(unsigned int) *s])
    /* We avoid handling empty lines here.  */
    return;
      
  if (is_name_beginner (*s))
    label = s;

  /* If there is a label, skip over it.  */
  while (*s && is_part_of_name (*s))
    s++;

  /* Find the start of the instruction or pseudo following the label,
     if there is one.  */
  for (insn = s;
       *insn && ISSPACE (*insn) && ! is_end_of_line[(unsigned int) *insn];
       insn++)
    /* Empty */
    ;

  /* Remove a trailing ":" off labels, as they'd otherwise be considered
     part of the name.  But don't do this for local labels.  */
  if (s != input_line_pointer && s[-1] == ':'
      && (s - 2 != input_line_pointer
         || ! ISDIGIT (s[-2])))
    s[-1] = ' ';
  else if (label != NULL
          /* For a lone label on a line, we don't attach it to the next
             instruction or MMIXAL-pseudo (getting its alignment).  Thus
             is acts like a "normal" :-ended label.  Ditto if it's
             followed by a non-MMIXAL pseudo.  */
          && !is_end_of_line[(unsigned int) *insn]
          && *insn != '.')
    {
      /* For labels that don't end in ":", we save it so we can later give
        it the same alignment and address as the associated instruction.  */

      /* Make room for the label including the ending nul.  */
      int len_0 = s - label + 1;

      /* Save this label on the MMIX symbol obstack.  Saving it on an
        obstack is needless for "IS"-pseudos, but it's harmless and we
        avoid a little code-cluttering.  */
      obstack_grow (&mmix_sym_obstack, label, len_0);
      pending_label = obstack_finish (&mmix_sym_obstack);
      pending_label[len_0 - 1] = 0;
    }

  /* If we have a non-MMIXAL pseudo, we have not business with the rest of
     the line.  */
  if (*insn == '.')
    return;

  /* Find local labels of operands.  Look for "[0-9][FB]" where the
     characters before and after are not part of words.  Break if a single
     or double quote is seen anywhere.  It means we can't have local
     labels as part of list with mixed quoted and unquoted members for
     mmixal compatibility but we can't have it all.  For the moment.
     Replace the '<N>B' or '<N>F' with MAGIC_FB_BACKWARD_CHAR<N> and
     MAGIC_FB_FORWARD_CHAR<N> respectively.  */

  /* First make sure we don't have any of the magic characters on the line
     appearing as input.  */
  while (*s)
    {
      c = *s++;
      if (is_end_of_line[(unsigned int) c])
       break;
      if (c == MAGIC_FB_BACKWARD_CHAR || c == MAGIC_FB_FORWARD_CHAR)
       as_bad (_("invalid characters in input"));
    }

  /* Scan again, this time looking for ';' after operands.  */
  s = insn;

  /* Skip the insn.  */
  while (*s
        && ! ISSPACE (*s)
        && *s != ';'
        && ! is_end_of_line[(unsigned int) *s])
    s++;

  /* Skip the spaces after the insn.  */
  while (*s
        && ISSPACE (*s)
        && *s != ';'
        && ! is_end_of_line[(unsigned int) *s])
    s++;

  /* Skip the operands.  While doing this, replace [0-9][BF] with
     (MAGIC_FB_BACKWARD_CHAR|MAGIC_FB_FORWARD_CHAR)[0-9].  */
  while ((c = *s) != 0
        && ! ISSPACE (c)
        && c != ';'
        && ! is_end_of_line[(unsigned int) c])
    {
      if (c == '"')
       {
         s++;

         /* FIXME: Test-case for semi-colon in string.  */
         while (*s
               && *s != '"'
               && (! is_end_of_line[(unsigned int) *s] || *s == ';'))
           s++;

         if (*s == '"')
           s++;
       }
      else if (ISDIGIT (c))
       {
         if ((s[1] != 'B' && s[1] != 'F')
             || is_part_of_name (s[-1])
             || is_part_of_name (s[2])
             /* Don't treat e.g. #1F as a local-label reference.  */
             || (s != input_line_pointer && s[-1] == '#'))
           s++;
         else
           {
             s[0] = (s[1] == 'B'
                    ? MAGIC_FB_BACKWARD_CHAR : MAGIC_FB_FORWARD_CHAR);
             s[1] = c;
           }
       }
      else
       s++;
    }

  /* Skip any spaces after the operands.  */
  while (*s
        && ISSPACE (*s)
        && *s != ';'
        && !is_end_of_line[(unsigned int) *s])
    s++;

  /* If we're now looking at a semi-colon, then it's an end-of-line
     delimiter.  */
  mmix_next_semicolon_is_eoln = (*s == ';');

  /* Make IS into an EQU by replacing it with "= ".  Only match upper-case
     though; let lower-case be a syntax error.  */
  s = insn;
  if (s[0] == 'I' && s[1] == 'S' && ISSPACE (s[2]))
    {
      *s = '=';
      s[1] = ' ';

      /* Since labels can start without ":", we have to handle "X IS 42"
        in full here, or "X" will be parsed as a label to be set at ".".  */
      input_line_pointer = s;

      /* Right after this function ends, line numbers will be bumped if
        input_line_pointer[-1] = '\n'.  We want accurate line numbers for
        the equals call, so we bump them before the call, and make sure
        they aren't bumped afterwards.  */
      bump_line_counters ();

      /* A fb-label is valid as an IS-label.  */
      if (current_fb_label >= 0)
       {
         char *fb_name;

         /* We need to save this name on our symbol obstack, since the
            string we got in fb_label_name is volatile and will change
            with every call to fb_label_name, like those resulting from
            parsing the IS-operand.  */
         fb_name = fb_label_name (current_fb_label, 1);
         obstack_grow (&mmix_sym_obstack, fb_name, strlen (fb_name) + 1);
         equals (obstack_finish (&mmix_sym_obstack), 0);
         fb_label_instance_inc (current_fb_label);
         current_fb_label = -1;
       }
      else
       {
         if (pending_label == NULL)
           as_bad (_("empty label field for IS"));
         else
           equals (pending_label, 0);
         pending_label = NULL;
       }

      /* For mmixal, we can have comments without a comment-start
        character.   */
      mmix_handle_rest_of_empty_line ();
      input_line_pointer--;

      input_line_pointer[-1] = ' ';
    }
  else if (s[0] == 'G'
          && s[1] == 'R'
          && strncmp (s, "GREG", 4) == 0
          && (ISSPACE (s[4]) || is_end_of_line[(unsigned char) s[4]]))
    {
      input_line_pointer = s + 4;

      /* Right after this function ends, line numbers will be bumped if
        input_line_pointer[-1] = '\n'.  We want accurate line numbers for
        the s_greg call, so we bump them before the call, and make sure
        they aren't bumped afterwards.  */
      bump_line_counters ();

      /* A fb-label is valid as a GREG-label.  */
      if (current_fb_label >= 0)
       {
         char *fb_name;

         /* We need to save this name on our symbol obstack, since the
            string we got in fb_label_name is volatile and will change
            with every call to fb_label_name, like those resulting from
            parsing the IS-operand.  */
         fb_name = fb_label_name (current_fb_label, 1);

         /* Make sure we save the canonical name and don't get bitten by
             prefixes.  */
         obstack_1grow (&mmix_sym_obstack, ':');
         obstack_grow (&mmix_sym_obstack, fb_name, strlen (fb_name) + 1);
         mmix_greg_internal (obstack_finish (&mmix_sym_obstack));
         fb_label_instance_inc (current_fb_label);
         current_fb_label = -1;
       }
      else
       mmix_greg_internal (pending_label);

      /* Back up before the end-of-line marker that was skipped in
        mmix_greg_internal.  */
      input_line_pointer--;
      input_line_pointer[-1] = ' ';

      pending_label = NULL;
    }
  else if (pending_label != NULL)
    {
      input_line_pointer += strlen (pending_label);

      /* See comment above about getting line numbers bumped.  */
      input_line_pointer[-1] = '\n';
    }
}

Here is the call graph for this function:

Definition at line 3333 of file tc-mmix.c.

void mmix_md_begin ( void  )

Definition at line 751 of file tc-mmix.c.

{
  int i;
  const struct mmix_opcode *opcode;

  /* We assume nobody will use this, so don't allocate any room.  */
  obstack_begin (&mmix_sym_obstack, 0);

  /* This will break the day the "lex" thingy changes.  For now, it's the
     only way to make ':' part of a name, and a name beginner.  */
  lex_type[':'] = (LEX_NAME | LEX_BEGIN_NAME);

  mmix_opcode_hash = hash_new ();

  real_reg_section
    = bfd_make_section_old_way (stdoutput, MMIX_REG_SECTION_NAME);

  for (opcode = mmix_opcodes; opcode->name; opcode++)
    hash_insert (mmix_opcode_hash, opcode->name, (char *) opcode);

  /* We always insert the ordinary registers 0..255 as registers.  */
  for (i = 0; i < 256; i++)
    {
      char buf[5];

      /* Alternatively, we could diddle with '$' and the following number,
        but keeping the registers as symbols helps keep parsing simple.  */
      sprintf (buf, "$%d", i);
      symbol_table_insert (symbol_new (buf, reg_section, i,
                                   &zero_address_frag));
    }

  /* Insert mmixal built-in names if allowed.  */
  if (predefined_syms)
    {
      for (i = 0; mmix_spec_regs[i].name != NULL; i++)
       symbol_table_insert (symbol_new (mmix_spec_regs[i].name,
                                    reg_section,
                                    mmix_spec_regs[i].number + 256,
                                    &zero_address_frag));

      /* FIXME: Perhaps these should be recognized as specials; as field
        names for those instructions.  */
      symbol_table_insert (symbol_new ("ROUND_CURRENT", reg_section, 512,
                                   &zero_address_frag));
      symbol_table_insert (symbol_new ("ROUND_OFF", reg_section, 512 + 1,
                                   &zero_address_frag));
      symbol_table_insert (symbol_new ("ROUND_UP", reg_section, 512 + 2,
                                   &zero_address_frag));
      symbol_table_insert (symbol_new ("ROUND_DOWN", reg_section, 512 + 3,
                                   &zero_address_frag));
      symbol_table_insert (symbol_new ("ROUND_NEAR", reg_section, 512 + 4,
                                   &zero_address_frag));
    }
}

Here is the call graph for this function:

void mmix_md_do_align ( int  ,
char *  ,
int  ,
int   
)

Definition at line 3877 of file tc-mmix.c.

{
  if (doing_bspec)
    as_bad (_("section change from within a BSPEC/ESPEC pair is not supported"));

  last_alignment = bfd_get_section_alignment (now_seg->owner, now_seg);
  want_unaligned = 0;
}

Here is the call graph for this function:

void mmix_md_end ( void  )

Definition at line 3475 of file tc-mmix.c.

{
  fragS *fragP;
  symbolS *mainsym;
  int i;

  /* The first frag of GREG:s going into the register contents section.  */
  fragS *mmix_reg_contents_frags = NULL;

  /* Reset prefix.  All labels reachable at this point must be
     canonicalized.  */
  mmix_current_prefix = NULL;

  if (doing_bspec)
    as_bad_where (bspec_file, bspec_line, _("BSPEC without ESPEC."));

  /* Emit the low LOC setting of .text.  */
  if (text_has_contents && lowest_text_loc != (bfd_vma) -1)
    {
      symbolS *symbolP;
      char locsymbol[sizeof (":") - 1
                  + sizeof (MMIX_LOC_SECTION_START_SYMBOL_PREFIX) - 1
                  + sizeof (".text")];

      /* An exercise in non-ISO-C-ness, this one.  */
      sprintf (locsymbol, ":%s%s", MMIX_LOC_SECTION_START_SYMBOL_PREFIX,
              ".text");
      symbolP
       = symbol_new (locsymbol, absolute_section, lowest_text_loc,
                    &zero_address_frag);
      S_SET_EXTERNAL (symbolP);
    }

  /* Ditto .data.  */
  if (data_has_contents && lowest_data_loc != (bfd_vma) -1)
    {
      symbolS *symbolP;
      char locsymbol[sizeof (":") - 1
                   + sizeof (MMIX_LOC_SECTION_START_SYMBOL_PREFIX) - 1
                   + sizeof (".data")];

      sprintf (locsymbol, ":%s%s", MMIX_LOC_SECTION_START_SYMBOL_PREFIX,
              ".data");
      symbolP
       = symbol_new (locsymbol, absolute_section, lowest_data_loc,
                    &zero_address_frag);
      S_SET_EXTERNAL (symbolP);
    }

  /* Unless GNU syntax mode, set "Main" to be a function, so the
     disassembler doesn't get confused when we write truly
     mmixal-compatible code (and don't use .type).  Similarly set it
     global (regardless of -globalize-symbols), so the linker sees it as
     the start symbol in ELF mode.  */
  mainsym = symbol_find (MMIX_START_SYMBOL_NAME);
  if (mainsym != NULL && ! mmix_gnu_syntax)
    {
      symbol_get_bfdsym (mainsym)->flags |= BSF_FUNCTION;
      S_SET_EXTERNAL (mainsym);
    }

  if (n_of_raw_gregs != 0)
    {
      /* Emit GREGs.  They are collected in order of appearance, but must
        be emitted in opposite order to both have section address regno*8
        and the same allocation order (within a file) as mmixal.  */
      segT this_segment = now_seg;
      subsegT this_subsegment = now_subseg;
      asection *regsec
       = bfd_make_section_old_way (stdoutput,
                                MMIX_REG_CONTENTS_SECTION_NAME);
      subseg_set (regsec, 0);

      /* Finally emit the initialization-value.  Emit a variable frag, which
        we'll fix in md_estimate_size_before_relax.  We set the initializer
        for the tc_frag_data field to NULL, so we can use that field for
        relaxation purposes.  */
      mmix_opcode_frag = NULL;

      frag_grow (0);
      mmix_reg_contents_frags = frag_now;

      for (i = n_of_raw_gregs - 1; i >= 0; i--)
       {
         if (mmix_raw_gregs[i].label != NULL)
           /* There's a symbol.  Let it refer to this location in the
              register contents section.  The symbol must be globalized
              separately.  */
           colon (mmix_raw_gregs[i].label);

         frag_var (rs_machine_dependent, 8, 0, STATE_GREG_UNDF,
                  make_expr_symbol (&mmix_raw_gregs[i].exp), 0, NULL);
       }

      subseg_set (this_segment, this_subsegment);
    }

  /* Iterate over frags resulting from GREGs and move those that evidently
     have the same value together and point one to another.

     This works in time O(N^2) but since the upper bound for non-error use
     is 223, it's best to keep this simpler algorithm.  */
  for (fragP = mmix_reg_contents_frags; fragP != NULL; fragP = fragP->fr_next)
    {
      fragS **fpp;
      fragS *fp = NULL;
      fragS *osymfrag;
      offsetT osymval;
      expressionS *oexpP;
      symbolS *symbolP = fragP->fr_symbol;

      if (fragP->fr_type != rs_machine_dependent
         || fragP->fr_subtype != STATE_GREG_UNDF)
       continue;

      /* Whatever the outcome, we will have this GREG judged merged or
        non-merged.  Since the tc_frag_data is NULL at this point, we
        default to non-merged.  */
      fragP->fr_subtype = STATE_GREG_DEF;

      /* If we're not supposed to merge GREG definitions, then just don't
        look for equivalents.  */
      if (! merge_gregs)
       continue;

      osymval = (offsetT) S_GET_VALUE (symbolP);
      osymfrag = symbol_get_frag (symbolP);

      /* If the symbol isn't defined, we can't say that another symbol
        equals this frag, then.  FIXME: We can look at the "deepest"
        defined name; if a = c and b = c then obviously a == b.  */
      if (! S_IS_DEFINED (symbolP))
       continue;

      oexpP = symbol_get_value_expression (fragP->fr_symbol);

      /* If the initialization value is zero, then we must not merge them.  */
      if (oexpP->X_op == O_constant && osymval == 0)
       continue;

      /* Iterate through the frags downward this one.  If we find one that
        has the same non-zero value, move it to after this one and point
        to it as the equivalent.  */
      for (fpp = &fragP->fr_next; *fpp != NULL; fpp = &fpp[0]->fr_next)
       {
         fp = *fpp;

         if (fp->fr_type != rs_machine_dependent
             || fp->fr_subtype != STATE_GREG_UNDF)
           continue;

         /* Calling S_GET_VALUE may simplify the symbol, changing from
            expr_section etc. so call it first.  */
         if ((offsetT) S_GET_VALUE (fp->fr_symbol) == osymval
             && symbol_get_frag (fp->fr_symbol) == osymfrag)
           {
             /* Move the frag links so the one we found equivalent comes
               after the current one, carefully considering that
               sometimes fpp == &fragP->fr_next and the moves must be a
               NOP then.  */
             *fpp = fp->fr_next;
             fp->fr_next = fragP->fr_next;
             fragP->fr_next = fp;
             break;
           }
       }

      if (*fpp != NULL)
       fragP->tc_frag_data = fp;
    }
}

Here is the call graph for this function:

long mmix_md_relax_frag ( segT  ,
fragS *  ,
long   
)

Definition at line 3349 of file tc-mmix.c.

{
  switch (fragP->fr_subtype)
    {
      /* Growth for this type has been handled by mmix_md_end and
        correctly estimated, so there's nothing more to do here.  */
    case STATE_GREG_DEF:
      return 0;

    case ENCODE_RELAX (STATE_PUSHJ, STATE_ZERO):
      {
       /* We need to handle relaxation type ourselves, since relax_frag
          doesn't update fr_subtype if there's no size increase in the
          current section; when going from plain PUSHJ to a stub.  This
          is otherwise functionally the same as relax_frag in write.c,
          simplified for this case.  */
       offsetT aim;
       addressT target;
       addressT address;
       symbolS *symbolP;
       target = fragP->fr_offset;
       address = fragP->fr_address;
       symbolP = fragP->fr_symbol;

       if (symbolP)
         {
           fragS *sym_frag;

           sym_frag = symbol_get_frag (symbolP);
           know (S_GET_SEGMENT (symbolP) != absolute_section
                || sym_frag == &zero_address_frag);
           target += S_GET_VALUE (symbolP);

           /* If frag has yet to be reached on this pass, assume it will
              move by STRETCH just as we did.  If this is not so, it will
              be because some frag between grows, and that will force
              another pass.  */

           if (stretch != 0
              && sym_frag->relax_marker != fragP->relax_marker
              && S_GET_SEGMENT (symbolP) == seg)
             target += stretch;
         }

       aim = target - address - fragP->fr_fix;
       if (aim >= PUSHJ_0B && aim <= PUSHJ_0F)
         {
           /* Target is reachable with a PUSHJ.  */
           segment_info_type *seginfo = seg_info (seg);

           /* If we're at the end of a relaxation round, clear the stub
              counter as initialization for the next round.  */
           if (fragP == seginfo->tc_segment_info_data.last_stubfrag)
             seginfo->tc_segment_info_data.nstubs = 0;
           return 0;
         }

       /* Not reachable.  Try a stub.  */
       fragP->fr_subtype = ENCODE_RELAX (STATE_PUSHJSTUB, STATE_ZERO);
      }
      /* FALLTHROUGH.  */
    
      /* See if this PUSHJ is redirectable to a stub.  */
    case ENCODE_RELAX (STATE_PUSHJSTUB, STATE_ZERO):
      {
       segment_info_type *seginfo = seg_info (seg);
       fragS *lastfrag = seginfo->frchainP->frch_last;
       relax_substateT prev_type = fragP->fr_subtype;

       /* The last frag is always an empty frag, so it suffices to look
          at its address to know the ending address of this section.  */
       know (lastfrag->fr_type == rs_fill
             && lastfrag->fr_fix == 0
             && lastfrag->fr_var == 0);

       /* For this PUSHJ to be relaxable into a call to a stub, the
          distance must be no longer than 256k bytes from the PUSHJ to
          the end of the section plus the maximum size of stubs so far.  */
       if ((lastfrag->fr_address
            + stretch
            + PUSHJ_MAX_LEN * seginfo->tc_segment_info_data.nstubs)
           - (fragP->fr_address + fragP->fr_fix)
           > GETA_0F
           || !pushj_stubs)
         fragP->fr_subtype = mmix_relax_table[prev_type].rlx_more;
       else
         seginfo->tc_segment_info_data.nstubs++;

       /* If we're at the end of a relaxation round, clear the stub
          counter as initialization for the next round.  */
       if (fragP == seginfo->tc_segment_info_data.last_stubfrag)
         seginfo->tc_segment_info_data.nstubs = 0;

       return
          (mmix_relax_table[fragP->fr_subtype].rlx_length
           - mmix_relax_table[prev_type].rlx_length);
      }

    case ENCODE_RELAX (STATE_PUSHJ, STATE_MAX):
      {
       segment_info_type *seginfo = seg_info (seg);

       /* Need to cover all STATE_PUSHJ states to act on the last stub
          frag (the end of this relax round; initialization for the
          next).  */
       if (fragP == seginfo->tc_segment_info_data.last_stubfrag)
         seginfo->tc_segment_info_data.nstubs = 0;

       return 0;
      }

    default:
      return relax_frag (seg, fragP, stretch);

    case STATE_GREG_UNDF:
      BAD_CASE (fragP->fr_subtype);
    }

  as_fatal (_("internal: unexpected relax type %d:%d"),
           fragP->fr_type, fragP->fr_subtype);
  return 0;
}

Here is the call graph for this function:

Definition at line 3768 of file tc-mmix.c.

{
  char *canon_name;
  char *handler_charp;
  const char handler_chars[] = "DVWIOUZX";
  symbolS *symp;

  if (! predefined_syms)
    return 0;

  canon_name = tc_canonicalize_symbol_name (name);

  if (canon_name[1] == '_'
      && strcmp (canon_name + 2, "Handler") == 0
      && (handler_charp = strchr (handler_chars, *canon_name)) != NULL)
    {
      /* If the symbol doesn't exist, provide one relative to the .text
        section.

        FIXME: We should provide separate sections, mapped in the linker
        script.  */
      symp = symbol_find (name);
      if (symp == NULL)
       symp = symbol_new (name, text_section,
                        0x10 * (handler_charp + 1 - handler_chars),
                        &zero_address_frag);
    }
  else
    {
      /* These symbols appear when referenced; needed for
         mmixal-compatible programs.  */
      unsigned int i;

      static const struct
      {
       const char *name;
       valueT val;
      } predefined_abs_syms[] =
       {
         {"Data_Segment", (valueT) 0x20 << 56},
         {"Pool_Segment", (valueT) 0x40 << 56},
         {"Stack_Segment", (valueT) 0x60 << 56},
         {"StdIn", 0},
         {"StdOut", 1},
         {"StdErr", 2},
         {"TextRead", 0},
         {"TextWrite", 1},
         {"BinaryRead", 2},
         {"BinaryWrite", 3},
         {"BinaryReadWrite", 4},
         {"Halt", 0},
         {"Fopen", 1},
         {"Fclose", 2},
         {"Fread", 3},
         {"Fgets", 4},
         {"Fgetws", 5},
         {"Fwrite", 6},
         {"Fputs", 7},
         {"Fputws", 8},
         {"Fseek", 9},
         {"Ftell", 10},
         {"D_BIT", 0x80},
         {"V_BIT", 0x40},
         {"W_BIT", 0x20},
         {"I_BIT", 0x10},
         {"O_BIT", 0x08},
         {"U_BIT", 0x04},
         {"Z_BIT", 0x02},
         {"X_BIT", 0x01},
         {"Inf", 0x7ff00000}
       };

      /* If it's already in the symbol table, we shouldn't do anything.  */
      symp = symbol_find (name);
      if (symp != NULL)
       return 0;

      for (i = 0;
          i < sizeof (predefined_abs_syms) / sizeof (predefined_abs_syms[0]);
          i++)
       if (strcmp (canon_name, predefined_abs_syms[i].name) == 0)
         {
           symbol_table_insert (symbol_new (predefined_abs_syms[i].name,
                                        absolute_section,
                                        predefined_abs_syms[i].val,
                                        &zero_address_frag));

           /* Let gas find the symbol we just created, through its
               ordinary lookup.  */
           return 0;
         }

      /* Not one of those symbols.  Let gas handle it.  */
      return 0;
    }

  expP->X_op = O_symbol;
  expP->X_add_number = 0;
  expP->X_add_symbol = symp;
  expP->X_op_symbol = NULL;

  return 1;
}

Here is the call graph for this function:

char* mmix_prefix_name ( char *  )

Definition at line 1962 of file tc-mmix.c.

{
  if (*shortname == ':')
    return shortname + 1;

  if (mmix_current_prefix == NULL)
    as_fatal (_("internal: mmix_prefix_name but empty prefix"));

  if (*shortname == '$')
    return shortname;

  obstack_grow (&mmix_sym_obstack, mmix_current_prefix,
              strlen (mmix_current_prefix));
  obstack_grow (&mmix_sym_obstack, shortname, strlen (shortname) + 1);
  return obstack_finish (&mmix_sym_obstack);
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 378 of file tc-mmix.c.

Definition at line 216 of file tc-mmix.c.

Definition at line 391 of file tc-mmix.c.

Definition at line 393 of file tc-mmix.c.

Definition at line 170 of file tc-mmix.c.

Definition at line 167 of file tc-mmix.c.

Definition at line 178 of file tc-mmix.c.

Definition at line 101 of file tc-mmix.c.

Definition at line 385 of file tc-mmix.c.