Back to index

cell-binutils  2.17cvs20070401
Classes | Defines | Typedefs | Functions | Variables
tc-i370.c File Reference
#include "as.h"
#include "safe-ctype.h"
#include "subsegs.h"
#include "struc-symbol.h"
#include "opcode/i370.h"

Go to the source code of this file.

Classes

struct  pd_reg
struct  literalS
struct  i370_fixup

Defines

#define TARGET_REG_NAMES_P   TRUE
#define REG_NAME_CNT   (sizeof (pre_defined_registers) / sizeof (struct pd_reg))
#define LITERAL_POOL_SUPPORT
#define MAX_LITERAL_POOL_SIZE   1024
#define DEBUG_SYMS
#define EMIT_ADDR_CONS_SYMBOLS
#define MAX_INSN_FIXUPS   5

Typedefs

typedef struct literalS literalT

Functions

void md_show_usage (FILE *stream)
static int reg_name_search (const struct pd_reg *regs, int regcount, const char *name)
static bfd_boolean register_name (expressionS *expressionP)
int md_parse_option (int c, char *arg)
static void i370_set_cpu (void)
enum bfd_architecture i370_arch (void)
void md_begin (void)
static i370_insn_t i370_insert_operand (i370_insn_t insn, const struct i370_operand *operand, offsetT val)
static symbolS * symbol_make_empty (void)
static void i370_make_relative (expressionS *exx, expressionS *baseaddr)
static void add_to_lit_pool (expressionS *exx, char *name, int sz)
static void symbol_locate (symbolS *symbolP, const char *name, segT segment, valueT valu, fragS *frag)
static bfd_boolean i370_addr_offset (expressionS *exx)
static bfd_boolean i370_addr_cons (expressionS *exp)
static void i370_ltorg (int ignore ATTRIBUTE_UNUSED)
static void i370_using (int ignore ATTRIBUTE_UNUSED)
static void i370_drop (int ignore ATTRIBUTE_UNUSED)
static void i370_macro (char *str, const struct i370_macro *macro)
void md_assemble (char *str)
static void i370_byte (int ignore ATTRIBUTE_UNUSED)
static void i370_tc (int ignore ATTRIBUTE_UNUSED)
char * md_atof (int type, char *litp, int *sizep)
void md_number_to_chars (char *buf, valueT val, int n)
valueT md_section_align (asection *seg, valueT addr)
int md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED, asection *seg ATTRIBUTE_UNUSED)
void md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, asection *sec ATTRIBUTE_UNUSED, fragS *fragp ATTRIBUTE_UNUSED)
symbolS * md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
long md_pcrel_from_section (fixS *fixp, segT sec ATTRIBUTE_UNUSED)
void md_apply_fix (fixS *fixP, valueT *valP, segT seg)
arelenttc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)

Variables

int target_big_endian
const char comment_chars [] = "#"
const char line_comment_chars [] = "#*"
const char line_separator_chars [] = ";"
const char EXP_CHARS [] = "eE"
const char FLT_CHARS [] = "dD"
static bfd_boolean reg_names_p = TARGET_REG_NAMES_P
static struct pd_reg []
static int i370_cpu = 0
static int i370_using_text_regno = -1
static int i370_using_other_regno = -1
static expressionS i370_using_text_baseaddr
static expressionS i370_using_other_baseaddr
static segT i370_other_section = undefined_section
static struct hash_controli370_hash
static struct hash_controli370_macro_hash
static flagword i370_flags = 0
int md_short_jump_size = 4
int md_long_jump_size = 4
const char * md_shortopts = "um:"
size_t md_longopts_size = sizeof (md_longopts)
literalT literals [MAX_LITERAL_POOL_SIZE]
int next_literal_pool_place = 0
static symbolS * longlong_poolP = NULL
static symbolS * word_poolP = NULL
static symbolS * short_poolP = NULL
static symbolS * byte_poolP = NULL
static int lit_pool_num = 1
const pseudo_typeS md_pseudo_table []

Class Documentation

struct pd_reg

Definition at line 467 of file tc-hppa.c.

Class Members
char * name
char * pname
int value
struct literalS

Definition at line 1196 of file tc-i370.c.

Collaboration diagram for literalS:
Class Members
struct score_it * inst
short offset
char size
char * sym_name
struct i370_fixup

Definition at line 1804 of file tc-i370.c.

Collaboration diagram for i370_fixup:
Class Members
expressionS exp
int opindex
bfd_reloc_code_real_type reloc

Define Documentation

#define DEBUG_SYMS

Definition at line 1179 of file tc-i370.c.

#define MAX_INSN_FIXUPS   5

Definition at line 1811 of file tc-i370.c.

#define MAX_LITERAL_POOL_SIZE   1024

Definition at line 1194 of file tc-i370.c.

#define REG_NAME_CNT   (sizeof (pre_defined_registers) / sizeof (struct pd_reg))

Definition at line 206 of file tc-i370.c.

#define TARGET_REG_NAMES_P   TRUE

Definition at line 94 of file tc-i370.c.


Typedef Documentation


Function Documentation

static void add_to_lit_pool ( expressionS exx,
char *  name,
int  sz 
) [static]

Definition at line 1251 of file tc-i370.c.

{
  int lit_count = 0;
  int offset_in_pool = 0;

  /* Start a new pool, if necessary.  */
  if (8 == sz && NULL == longlong_poolP)
    longlong_poolP = symbol_make_empty ();
  else if (4 == sz && NULL == word_poolP)
    word_poolP = symbol_make_empty ();
  else if (2 == sz && NULL == short_poolP)
    short_poolP = symbol_make_empty ();
  else if (1 == sz && NULL == byte_poolP)
    byte_poolP = symbol_make_empty ();

  /* Check if this literal value is already in the pool.
     FIXME: We should probably be checking expressions
            of type O_symbol as well.
     FIXME: This is probably(certainly?) broken for O_big,
            which includes 64-bit long-longs.  */
  while (lit_count < next_literal_pool_place)
    {
      if (exx->X_op == O_constant
          && literals[lit_count].exp.X_op == exx->X_op
          && literals[lit_count].exp.X_add_number == exx->X_add_number
          && literals[lit_count].exp.X_unsigned == exx->X_unsigned
          && literals[lit_count].size == sz)
        break;
      else if (literals[lit_count].sym_name
              && name
              && !strcmp (name, literals[lit_count].sym_name))
        break;
      if (sz == literals[lit_count].size)
       offset_in_pool += sz;
      lit_count ++;
    }

  if (lit_count == next_literal_pool_place) /* new entry */
    {
      if (next_literal_pool_place > MAX_LITERAL_POOL_SIZE)
       as_bad ("Literal Pool Overflow");

      literals[next_literal_pool_place].exp = *exx;
      literals[next_literal_pool_place].size = sz;
      literals[next_literal_pool_place].offset = offset_in_pool;
      if (name)
       literals[next_literal_pool_place].sym_name = strdup (name);
      else
       literals[next_literal_pool_place].sym_name = NULL;
      next_literal_pool_place++;
    }

  /* ???_poolP points to the beginning of the literal pool.
     X_add_number is the offset from the beginning of the
     literal pool to this expr minus the location of the most
     recent .using directive.  Thus, the grand total value of the
     expression is the distance from .using to the literal.  */
  if (8 == sz)
    exx->X_add_symbol = longlong_poolP;
  else if (4 == sz)
    exx->X_add_symbol = word_poolP;
  else if (2 == sz)
    exx->X_add_symbol = short_poolP;
  else if (1 == sz)
    exx->X_add_symbol = byte_poolP;
  exx->X_add_number = offset_in_pool;
  exx->X_op_symbol = NULL;

  /* If the user has set up a base reg in another section,
     use that; otherwise use the text section.  */
  if (0 < i370_using_other_regno)
    i370_make_relative (exx, &i370_using_other_baseaddr);
  else
    i370_make_relative (exx, &i370_using_text_baseaddr);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean i370_addr_cons ( expressionS exp) [static]

Definition at line 1463 of file tc-i370.c.

{
  char *name;
  char *sym_name, delim;
  int name_len;
  int hex_len = 0;
  int cons_len = 0;

  name = input_line_pointer;
  sym_name = input_line_pointer;
  /* Find the spelling of the operand.  */
  if (name[0] == '=' && ISALPHA (name[1]))
    name = ++input_line_pointer;
  else
    return FALSE;

  switch (name[0])
    {
    case 'A': /* A == address-of.  */
    case 'V': /* V == extern.  */
      ++input_line_pointer;
      expression (exp);

      /* We use a simple string name to collapse together
         multiple refrences to the same address literal.  */
      name_len = strcspn (sym_name, ", ");
      delim = *(sym_name + name_len);
      *(sym_name + name_len) = 0x0;
      add_to_lit_pool (exp, sym_name, 4);
      *(sym_name + name_len) = delim;

      break;
    case 'H':
    case 'F':
    case 'X':
    case 'E':  /* Single-precision float point.  */
    case 'D':  /* Double-precision float point.  */

      /* H == 16-bit fixed-point const; expression must be const.  */
      /* F == fixed-point const; expression must be const.  */
      /* X == fixed-point const; expression must be const.  */
      if ('H' == name[0]) cons_len = 2;
      else if ('F' == name[0]) cons_len = 4;
      else if ('X' == name[0]) cons_len = -1;
      else if ('E' == name[0]) cons_len = 4;
      else if ('D' == name[0]) cons_len = 8;

      /* Extract length, if it is present;
        FIXME: assume single-digit length.  */
      if ('L' == name[1])
       {
         /* Should work for ASCII and EBCDIC.  */
         cons_len = name[2] - '0';
         input_line_pointer += 2;
       }

      ++input_line_pointer;

      /* Get rid of pesky quotes.  */
      if ('\'' == *input_line_pointer)
       {
         char * close;
         ++input_line_pointer;
         close = strchr (input_line_pointer, '\'');
         if (close)
           *close= ' ';
         else
           as_bad ("missing end-quote");
       }
      if ('\"' == *input_line_pointer)
       {
         char * close;
         ++input_line_pointer;
         close = strchr (input_line_pointer, '\"');
         if (close)
           *close= ' ';
         else
           as_bad ("missing end-quote");
       }
      if (('X' == name[0]) || ('E' == name[0]) || ('D' == name[0]))
       {
         char tmp[50];
         char *save;

         /* The length of hex constants is specified directly with L,
            or implied through the number of hex digits. For example:
            =X'AB'       one byte
            =X'abcd'     two bytes
            =X'000000AB' four bytes
            =XL4'AB'     four bytes, left-padded withn zero.  */
         if (('X' == name[0]) && (0 > cons_len))
           {
             save = input_line_pointer;
             while (*save)
              {
                if (ISXDIGIT (*save))
                  hex_len++;
                save++;
              }
             cons_len = (hex_len+1) /2;
           }
         /* I believe this works even for =XL8'dada0000beeebaaa'
            which should parse out to X_op == O_big
            Note that floats and doubles get represented as
            0d3.14159265358979  or 0f 2.7.  */
         tmp[0] = '0';
         tmp[1] = name[0];
         tmp[2] = 0;
         strcat (tmp, input_line_pointer);
         save = input_line_pointer;
         input_line_pointer = tmp;
         expression (exp);
         input_line_pointer = save + (input_line_pointer-tmp-2);

         /* Fix up lengths for floats and doubles.  */
         if (O_big == exp->X_op)
           exp->X_add_number = cons_len / CHARS_PER_LITTLENUM;
       }
      else
       expression (exp);

      /* O_big occurs when more than 4 bytes worth gets parsed.  */
      if ((exp->X_op != O_constant) && (exp->X_op != O_big))
       {
         as_bad ("expression not a constant");
         return FALSE;
       }
      add_to_lit_pool (exp, 0x0, cons_len);
      break;

    default:
      as_bad ("Unknown/unsupported address literal type");
      return FALSE;
    }

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean i370_addr_offset ( expressionS exx) [static]

Definition at line 1396 of file tc-i370.c.

{
  char *dot, *lab;
  int islabel = 0;
  int all_digits = 0;

  /* Search for a label; anything with an alpha char will do.
     Local labels consist of N digits followed by either b or f.  */
  lab = input_line_pointer;
  while (*lab && (',' != *lab) && ('(' != *lab))
    {
      if (ISDIGIT (*lab))
       all_digits = 1;
      else if (ISALPHA (*lab))
       {
         if (!all_digits)
           {
             islabel = 1;
             break;
           }
         else if (('f' == *lab) || ('b' == *lab))
           {
             islabel = 1;
             break;
           }
         if (all_digits)
           break;
       }
      else if ('.' != *lab)
        break;
      ++lab;
    }

  /* See if operand has a * in it.  */
  dot = strchr (input_line_pointer, '*');

  if (!dot && !islabel)
    return FALSE;

  /* Replace * with . and let expr munch on it.  */
  if (dot)
    *dot = '.';
  expression (exx);

  /* OK, now we have to subtract the "using" location.
     Normally branches appear in the text section only.  */
  if (0 == strncmp (now_seg->name, ".text", 5) || 0 > i370_using_other_regno)
    i370_make_relative (exx, &i370_using_text_baseaddr);
  else
    i370_make_relative (exx, &i370_using_other_baseaddr);

  /* Put the * back.  */
  if (dot)
    *dot = '*';

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

enum bfd_architecture i370_arch ( void  )

Definition at line 474 of file tc-i370.c.

{
   return bfd_arch_i370;
}
static void i370_byte ( int ignore  ATTRIBUTE_UNUSED) [static]

Definition at line 2291 of file tc-i370.c.

{
  if (*input_line_pointer != '\"')
    {
      cons (1);
      return;
    }

  /* Gather characters.  A real double quote is doubled.  Unusual
     characters are not permitted.  */
  ++input_line_pointer;
  while (1)
    {
      char c;

      c = *input_line_pointer++;

      if (c == '\"')
        {
        if (*input_line_pointer != '\"')
            break;
          ++input_line_pointer;
        }

      FRAG_APPEND_1_CHAR (c);
    }

  demand_empty_rest_of_line ();
}

Here is the call graph for this function:

static void i370_drop ( int ignore  ATTRIBUTE_UNUSED) [static]

Definition at line 1765 of file tc-i370.c.

{
  expressionS ex;
  int iregno;

  register_name (&ex);
  demand_empty_rest_of_line ();
  iregno = ex.X_add_number;

  if (0 == strncmp (now_seg->name, ".text", 5))
    {
      if (iregno != i370_using_text_regno)
       as_bad ("droping register %d in section %s does not match using register %d",
              iregno, now_seg->name, i370_using_text_regno);

      i370_using_text_regno = -1;
      i370_using_text_baseaddr.X_op = O_absent;
    }
  else
    {
      if (iregno != i370_using_other_regno)
       as_bad ("droping register %d in section %s does not match using register %d",
              iregno, now_seg->name, i370_using_other_regno);

      if (i370_other_section != now_seg)
       as_bad ("droping register %d in section %s previously used in section %s",
              iregno, now_seg->name, i370_other_section->name);

      i370_using_other_regno = -1;
      i370_using_other_baseaddr.X_op = O_absent;
      i370_other_section = undefined_section;
    }
}

Here is the call graph for this function:

static i370_insn_t i370_insert_operand ( i370_insn_t  insn,
const struct i370_operand operand,
offsetT  val 
) [static]

Definition at line 548 of file tc-i370.c.

{
  if (operand->insert)
    {
      const char *errmsg;

      /* Used for 48-bit insn's.  */
      errmsg = NULL;
      insn = (*operand->insert) (insn, (long) val, &errmsg);
      if (errmsg)
        as_bad ("%s", errmsg);
    }
  else
    /* This is used only for 16, 32 bit insn's.  */
    insn.i[0] |= (((long) val & ((1 << operand->bits) - 1))
                << operand->shift);

  return insn;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void i370_ltorg ( int ignore  ATTRIBUTE_UNUSED) [static]

Definition at line 1606 of file tc-i370.c.

{
  int litsize;
  int lit_count = 0;
  int biggest_literal_size = 0;
  int biggest_align = 0;
  char pool_name[20];

  if (strncmp (now_seg->name, ".text", 5))
    {
      if (i370_other_section == undefined_section)
       as_bad (".ltorg without prior .using in section %s",
              now_seg->name);

      if (i370_other_section != now_seg)
       as_bad (".ltorg in section %s paired to .using in section %s",
              now_seg->name, i370_other_section->name);
    }

  if (! longlong_poolP
      && ! word_poolP
      && ! short_poolP
      && ! byte_poolP)
    /* Nothing to do.  */
    return;

  /* Find largest literal .. 2 4 or 8.  */
  lit_count = 0;
  while (lit_count < next_literal_pool_place)
    {
      if (biggest_literal_size < literals[lit_count].size)
       biggest_literal_size = literals[lit_count].size;
      lit_count ++;
    }
  if (1 == biggest_literal_size) biggest_align = 0;
  else if (2 == biggest_literal_size) biggest_align = 1;
  else if (4 == biggest_literal_size) biggest_align = 2;
  else if (8 == biggest_literal_size) biggest_align = 3;
  else as_bad ("bad alignment of %d bytes in literal pool", biggest_literal_size);
  if (0 == biggest_align) biggest_align = 1;

  /* Align pool for short, word, double word accesses.  */
  frag_align (biggest_align, 0, 0);
  record_alignment (now_seg, biggest_align);

  /* Note that the gas listing will print only the first five
     entries in the pool .... wonder how to make it print more.  */
  /* Output largest literals first, then the smaller ones.  */
  for (litsize=8; litsize; litsize /=2)
    {
      symbolS *current_poolP = NULL;
      switch (litsize)
       {
       case 8:
         current_poolP = longlong_poolP; break;
       case 4:
         current_poolP = word_poolP; break;
       case 2:
         current_poolP = short_poolP; break;
       case 1:
         current_poolP = byte_poolP; break;
       default:
         as_bad ("bad literal size\n");
       }
      if (NULL == current_poolP)
       continue;
      sprintf (pool_name, ".LITP%01d%06d", litsize, lit_pool_num);
      symbol_locate (current_poolP, pool_name, now_seg,
                   (valueT) frag_now_fix (), frag_now);
      symbol_table_insert (current_poolP);

      lit_count = 0;
      while (lit_count < next_literal_pool_place)
       {
         if (litsize == literals[lit_count].size)
           {
#define EMIT_ADDR_CONS_SYMBOLS
#ifdef EMIT_ADDR_CONS_SYMBOLS
             /* Create a bogus symbol, add it to the pool ...
                For the most part, I think this is a useless exercise,
                except that having these symbol names in the objects
                is vaguely useful for debugging.  */
             if (literals[lit_count].sym_name)
              {
                symbolS * symP = symbol_make_empty ();
                symbol_locate (symP, literals[lit_count].sym_name, now_seg,
                             (valueT) frag_now_fix (), frag_now);
                symbol_table_insert (symP);
              }
#endif /* EMIT_ADDR_CONS_SYMBOLS */

             emit_expr (&(literals[lit_count].exp), literals[lit_count].size);
           }
         lit_count ++;
       }
    }

  next_literal_pool_place = 0;
  longlong_poolP = NULL;
  word_poolP = NULL;
  short_poolP = NULL;
  byte_poolP = NULL;
  lit_pool_num++;
}

Here is the call graph for this function:

static void i370_macro ( char *  str,
const struct i370_macro macro 
) [static]

Definition at line 1819 of file tc-i370.c.

{
  char *operands[10];
  unsigned int count;
  char *s;
  unsigned int len;
  const char *format;
  int arg;
  char *send;
  char *complete;

  /* Gather the users operands into the operands array.  */
  count = 0;
  s = str;
  while (1)
    {
      if (count >= sizeof operands / sizeof operands[0])
        break;
      operands[count++] = s;
      s = strchr (s, ',');
      if (s == (char *) NULL)
        break;
      *s++ = '\0';
    }

  if (count != macro->operands)
    {
      as_bad ("wrong number of operands");
      return;
    }

  /* Work out how large the string must be (the size is unbounded
     because it includes user input).  */
  len = 0;
  format = macro->format;
  while (*format != '\0')
    {
      if (*format != '%')
        {
          ++len;
          ++format;
        }
      else
        {
          arg = strtol (format + 1, &send, 10);
          know (send != format && arg >= 0 && (unsigned) arg < count);
          len += strlen (operands[arg]);
          format = send;
        }
    }

  /* Put the string together.  */
  complete = s = alloca (len + 1);
  format = macro->format;
  while (*format != '\0')
    {
      if (*format != '%')
        *s++ = *format++;
      else
        {
          arg = strtol (format + 1, &send, 10);
          strcpy (s, operands[arg]);
          s += strlen (s);
          format = send;
        }
    }
  *s = '\0';

  /* Assemble the constructed instruction.  */
  md_assemble (complete);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void i370_make_relative ( expressionS exx,
expressionS baseaddr 
) [static]

Definition at line 1226 of file tc-i370.c.

{
  if (O_constant == baseaddr->X_op)
    {
       exx->X_op = O_symbol;
       exx->X_add_number -= baseaddr->X_add_number;
    }
  else if (O_symbol == baseaddr->X_op)
    {
       exx->X_op = O_subtract;
       exx->X_op_symbol = baseaddr->X_add_symbol;
       exx->X_add_number -= baseaddr->X_add_number;
    }
  else if (O_uminus == baseaddr->X_op)
    {
       exx->X_op = O_add;
       exx->X_op_symbol = baseaddr->X_add_symbol;
       exx->X_add_number += baseaddr->X_add_number;
    }
  else
    as_bad ("Missing or bad .using directive");
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void i370_set_cpu ( void  ) [static]

Definition at line 450 of file tc-i370.c.

{
  const char *default_os  = TARGET_OS;
  const char *default_cpu = TARGET_CPU;

  /* Override with the superset for the moment.  */
  i370_cpu = I370_OPCODE_ESA390_SUPERSET;
  if (i370_cpu == 0)
    {
      if (strcmp (default_cpu, "i360") == 0)
        i370_cpu = I370_OPCODE_360;
      else if (strcmp (default_cpu, "i370") == 0)
        i370_cpu = I370_OPCODE_370;
      else if (strcmp (default_cpu, "XA") == 0)
        i370_cpu = I370_OPCODE_370_XA;
      else
        as_fatal ("Unknown default cpu = %s, os = %s", default_cpu, default_os);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void i370_tc ( int ignore  ATTRIBUTE_UNUSED) [static]

Definition at line 2334 of file tc-i370.c.

{

  /* Skip the TOC symbol name.  */
  while (is_part_of_name (*input_line_pointer)
         || *input_line_pointer == '['
         || *input_line_pointer == ']'
         || *input_line_pointer == '{'
         || *input_line_pointer == '}')
    ++input_line_pointer;

  /* Align to a four byte boundary.  */
  frag_align (2, 0, 0);
  record_alignment (now_seg, 2);

  if (*input_line_pointer != ',')
    demand_empty_rest_of_line ();
  else
    {
      ++input_line_pointer;
      cons (4);
    }
}

Here is the call graph for this function:

static void i370_using ( int ignore  ATTRIBUTE_UNUSED) [static]

Definition at line 1722 of file tc-i370.c.

{
  expressionS ex, baseaddr;
  int iregno;
  char *star;

  /* If "*" appears in a using, it means "."
     replace it with "." so that expr doesn't get confused.  */
  star = strchr (input_line_pointer, '*');
  if (star)
    *star = '.';

  /* The first arg to using will usually be ".", but it can
     be a more complex expression too.  */
  expression (&baseaddr);
  if (star)
    *star = '*';
  if (O_constant != baseaddr.X_op
      && O_symbol != baseaddr.X_op
      && O_uminus != baseaddr.X_op)
    as_bad (".using: base address expression illegal or too complex");

  if (*input_line_pointer != '\0') ++input_line_pointer;

  /* The second arg to using had better be a register.  */
  register_name (&ex);
  demand_empty_rest_of_line ();
  iregno = ex.X_add_number;

  if (0 == strncmp (now_seg->name, ".text", 5))
    {
      i370_using_text_baseaddr = baseaddr;
      i370_using_text_regno = iregno;
    }
  else
    {
      i370_using_other_baseaddr = baseaddr;
      i370_using_other_regno = iregno;
      i370_other_section = now_seg;
    }
}

Here is the call graph for this function:

void md_apply_fix ( fixS *  fixP,
valueT valP,
segT seg   
)

Definition at line 2478 of file tc-i370.c.

{
  valueT value = * valP;

  if (fixP->fx_addsy != NULL)
    {
#ifdef DEBUG
      printf ("\nmd_apply_fix: symbol %s at 0x%x (%s:%d) val=0x%x addend=0x%x\n",
             S_GET_NAME (fixP->fx_addsy),
             fixP->fx_frag->fr_address + fixP->fx_where,
             fixP->fx_file, fixP->fx_line,
             S_GET_VALUE (fixP->fx_addsy), value);
#endif
    }
  else
    fixP->fx_done = 1;

  /* Apply fixups to operands.  Note that there should be no relocations
     for any operands, since no instruction ever takes an operand
     that requires reloc.  */
  if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
    {
      int opindex;
      const struct i370_operand *operand;
      char *where;
      i370_insn_t insn;

      opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;

      operand = &i370_operands[opindex];

#ifdef DEBUG
      printf ("\nmd_apply_fix: fixup operand %s at 0x%x in %s:%d addend=0x%x\n",
             operand->name,
             fixP->fx_frag->fr_address + fixP->fx_where,
             fixP->fx_file, fixP->fx_line,
             value);
#endif
      /* Fetch the instruction, insert the fully resolved operand
         value, and stuff the instruction back again.
         fisxp->fx_size is the length of the instruction.  */
      where = fixP->fx_frag->fr_literal + fixP->fx_where;
      insn.i[0] = bfd_getb32 ((unsigned char *) where);

      if (6 <= fixP->fx_size)
       /* Deal with 48-bit insn's.  */
       insn.i[1] = bfd_getb32 (((unsigned char *) where)+4);

      insn = i370_insert_operand (insn, operand, (offsetT) value);
      bfd_putb32 ((bfd_vma) insn.i[0], (unsigned char *) where);

      if (6 <= fixP->fx_size)
       /* Deal with 48-bit insn's.  */
       bfd_putb32 ((bfd_vma) insn.i[1], (((unsigned char *) where)+4));

      /* We are done, right? right !!  */
      fixP->fx_done = 1;
      if (fixP->fx_done)
       /* Nothing else to do here.  */
       return;

      /* Determine a BFD reloc value based on the operand information.
        We are only prepared to turn a few of the operands into
        relocs.  In fact, we support *zero* operand relocations ...
        Why?  Because we are not expecting the compiler to generate
        any operands that need relocation.  Due to the 12-bit naturew of
        i370 addressing, this would be unusual.  */
        {
          char *sfile;
          unsigned int sline;

          /* Use expr_symbol_where to see if this is an expression
             symbol.  */
          if (expr_symbol_where (fixP->fx_addsy, &sfile, &sline))
            as_bad_where (fixP->fx_file, fixP->fx_line,
                       "unresolved expression that must be resolved");
          else
            as_bad_where (fixP->fx_file, fixP->fx_line,
                       "unsupported relocation type");
          fixP->fx_done = 1;
          return;
        }
    }
  else
    {
      /* We branch to here if the fixup is not to a symbol that
         appears in an instruction operand, but is rather some
         declared storage.  */
#ifdef OBJ_ELF
      i370_elf_validate_fix (fixP, seg);
#endif
#ifdef DEBUG
      printf ("md_apply_fix: reloc case %d in segment  %s %s:%d\n",
             fixP->fx_r_type, segment_name (seg), fixP->fx_file, fixP->fx_line);
      printf ("\tcurrent fixup value is 0x%x \n", value);
#endif
      switch (fixP->fx_r_type)
        {
        case BFD_RELOC_32:
        case BFD_RELOC_CTOR:
          if (fixP->fx_pcrel)
            fixP->fx_r_type = BFD_RELOC_32_PCREL;
         /* Fall through.  */

        case BFD_RELOC_RVA:
        case BFD_RELOC_32_PCREL:
        case BFD_RELOC_32_BASEREL:
#ifdef DEBUG
          printf ("\t32 bit relocation at 0x%x\n",
                fixP->fx_frag->fr_address + fixP->fx_where);
#endif
          md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
                           value, 4);
          break;

        case BFD_RELOC_LO16:
        case BFD_RELOC_16:
          if (fixP->fx_pcrel)
            as_bad_where (fixP->fx_file, fixP->fx_line,
                       "cannot emit PC relative %s relocation%s%s",
                       bfd_get_reloc_code_name (fixP->fx_r_type),
                       fixP->fx_addsy != NULL ? " against " : "",
                       (fixP->fx_addsy != NULL
                        ? S_GET_NAME (fixP->fx_addsy)
                        : ""));

          md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
                           value, 2);
          break;

          /* This case happens when you write, for example,
             lis %r3,(L1-L2)@ha
             where L1 and L2 are defined later.  */
        case BFD_RELOC_HI16:
          if (fixP->fx_pcrel)
            abort ();
          md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
                           value >> 16, 2);
          break;
        case BFD_RELOC_HI16_S:
          if (fixP->fx_pcrel)
            abort ();
          md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
                           (value + 0x8000) >> 16, 2);
          break;

        case BFD_RELOC_8:
          if (fixP->fx_pcrel)
            abort ();

          md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
                           value, 1);
          break;

        default:
          fprintf (stderr,
                "Gas failure, reloc value %d\n", fixP->fx_r_type);
          fflush (stderr);
          abort ();
        }
    }

  fixP->fx_addnumber = value;
}

Here is the call graph for this function:

void md_assemble ( char *  str)

Definition at line 1894 of file tc-i370.c.

{
  char *s, *opcode_str;
  const struct i370_opcode *opcode;
  i370_insn_t insn;
  const unsigned char *opindex_ptr;
  int have_optional_index, have_optional_basereg, have_optional_reg;
  int skip_optional_index, skip_optional_basereg, skip_optional_reg;
  int use_text=0, use_other=0;
  int off_by_one;
  struct i370_fixup fixups[MAX_INSN_FIXUPS];
  int fc;
  char *f;
  int i;
#ifdef OBJ_ELF
  bfd_reloc_code_real_type reloc;
#endif

  /* Get the opcode.  */
  for (s = str; *s != '\0' && ! ISSPACE (*s); s++)
    ;
  if (*s != '\0')
    *s++ = '\0';
  opcode_str = str;

  /* Look up the opcode in the hash table.  */
  opcode = (const struct i370_opcode *) hash_find (i370_hash, str);
  if (opcode == (const struct i370_opcode *) NULL)
    {
      const struct i370_macro *macro;

      assert (i370_macro_hash);
      macro = (const struct i370_macro *) hash_find (i370_macro_hash, str);
      if (macro == (const struct i370_macro *) NULL)
        as_bad ("Unrecognized opcode: `%s'", str);
      else
       i370_macro (s, macro);

      return;
    }

  insn = opcode->opcode;

  str = s;
  while (ISSPACE (*str))
    ++str;

  /* I370 operands are either expressions or address constants.
     Many operand types are optional.  The optional operands
     are always surrounded by parens, and are used to denote the base
     register ... e.g. "A R1, D2" or "A R1, D2(,B2) as opposed to
     the fully-formed "A R1, D2(X2,B2)".  Note also the = sign,
     such as A R1,=A(i) where the address-of operator =A implies
     use of both a base register, and a missing index register.

     So, before we start seriously parsing the operands, we check
     to see if we have an optional operand, and, if we do, we count
     the number of commas to see which operand should be omitted.  */

  have_optional_index = have_optional_basereg = have_optional_reg = 0;
  for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)
    {
      const struct i370_operand *operand;

      operand = &i370_operands[*opindex_ptr];
      if ((operand->flags & I370_OPERAND_INDEX) != 0)
       have_optional_index = 1;
      if ((operand->flags & I370_OPERAND_BASE) != 0)
       have_optional_basereg = 1;
      if ((operand->flags & I370_OPERAND_OPTIONAL) != 0)
       have_optional_reg = 1;
    }

  skip_optional_index = skip_optional_basereg = skip_optional_reg = 0;
  if (have_optional_index || have_optional_basereg)
    {
      unsigned int opcount, nwanted;

      /* There is an optional operand.  Count the number of
        commas and open-parens in the input line.  */
      if (*str == '\0')
       opcount = 0;
      else
       {
         opcount = 1;
         s = str;
         while ((s = strpbrk (s, ",(=")) != (char *) NULL)
           {
             ++opcount;
             ++s;
             if (',' == *s) ++s;  /* avoid counting things like (, */
             if ('=' == *s) { ++s; --opcount; }
           }
       }

      /* If there are fewer operands in the line then are called
        for by the instruction, we want to skip the optional
        operand.  */
      nwanted = strlen ((char *) opcode->operands);
      if (have_optional_index)
       {
         if (opcount < nwanted)
           skip_optional_index = 1;
         if (have_optional_basereg && ((opcount+1) < nwanted))
           skip_optional_basereg = 1;
         if (have_optional_reg && ((opcount+1) < nwanted))
           skip_optional_reg = 1;
       }
      else
       {
         if (have_optional_basereg && (opcount < nwanted))
           skip_optional_basereg = 1;
         if (have_optional_reg && (opcount < nwanted))
           skip_optional_reg = 1;
       }
    }

  /* Perform some off-by-one hacks on the length field of certain instructions.
     Its such a shame to have to do this, but the problem is that HLASM got
     defined so that the lengths differ by one from the actual machine instructions.
     this code should probably be moved to a special inster-operand routine.
     Sigh. Affected instructions are Compare Logical, Move and Exclusive OR
     hack alert -- aren't *all* SS instructions affected ??  */
  off_by_one = 0;
  if (0 == strcasecmp ("CLC", opcode->name)
      || 0 == strcasecmp ("ED", opcode->name)
      || 0 == strcasecmp ("EDMK", opcode->name)
      || 0 == strcasecmp ("MVC", opcode->name)
      || 0 == strcasecmp ("MVCIN", opcode->name)
      || 0 == strcasecmp ("MVN", opcode->name)
      || 0 == strcasecmp ("MVZ", opcode->name)
      || 0 == strcasecmp ("NC", opcode->name)
      || 0 == strcasecmp ("OC", opcode->name)
      || 0 == strcasecmp ("XC", opcode->name))
    off_by_one = 1;

  /* Gather the operands.  */
  fc = 0;
  for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)
    {
      const struct i370_operand *operand;
      const char *errmsg;
      char *hold;
      expressionS ex;

      operand = &i370_operands[*opindex_ptr];
      errmsg = NULL;

      /* If this is an index operand, and we are skipping it,
        just insert a zero.  */
      if (skip_optional_index &&
         ((operand->flags & I370_OPERAND_INDEX) != 0))
        {
          insn = i370_insert_operand (insn, operand, 0);
          continue;
        }

      /* If this is the base operand, and we are skipping it,
        just insert the current using basreg.  */
      if (skip_optional_basereg &&
          ((operand->flags & I370_OPERAND_BASE) != 0))
        {
          int basereg = -1;
          if (use_text)
            {
              if (0 == strncmp (now_seg->name, ".text", 5)
                || 0 > i370_using_other_regno)
              basereg = i370_using_text_regno;
              else
              basereg = i370_using_other_regno;
            }
          else if (use_other)
            {
              if (0 > i370_using_other_regno)
              basereg = i370_using_text_regno;
              else
              basereg = i370_using_other_regno;
            }
          if (0 > basereg)
           as_bad ("not using any base register");

          insn = i370_insert_operand (insn, operand, basereg);
          continue;
        }

      /* If this is an optional operand, and we are skipping it,
        Use zero (since a non-zero value would denote a register)  */
      if (skip_optional_reg
         && ((operand->flags & I370_OPERAND_OPTIONAL) != 0))
        {
          insn = i370_insert_operand (insn, operand, 0);
          continue;
        }

      /* Gather the operand.  */
      hold = input_line_pointer;
      input_line_pointer = str;

      /* Register names are only allowed where there are registers.  */
      if ((operand->flags & I370_OPERAND_GPR) != 0)
        {
          /* Quickie hack to get past things like (,r13).  */
          if (skip_optional_index && (',' == *input_line_pointer))
            {
              *input_line_pointer = ' ';
              input_line_pointer ++;
            }

          if (! register_name (&ex))
           as_bad ("expecting a register for operand %d",
                  (int) (opindex_ptr - opcode->operands + 1));
        }

      /* Check for an address constant expression.  */
      /* We will put PSW-relative addresses in the text section,
         and address literals in the .data (or other) section.  */
      else if (i370_addr_cons (&ex))
       use_other = 1;
      else if (i370_addr_offset (&ex))
       use_text = 1;
      else expression (&ex);

      str = input_line_pointer;
      input_line_pointer = hold;

      /* Perform some off-by-one hacks on the length field of certain instructions.
         Its such a shame to have to do this, but the problem is that HLASM got
         defined so that the programmer specifies a length that is one greater
         than what the machine instruction wants.  Sigh.  */
      if (off_by_one && (0 == strcasecmp ("SS L", operand->name)))
       ex.X_add_number --;

      if (ex.X_op == O_illegal)
        as_bad ("illegal operand");
      else if (ex.X_op == O_absent)
        as_bad ("missing operand");
      else if (ex.X_op == O_register)
       insn = i370_insert_operand (insn, operand, ex.X_add_number);
      else if (ex.X_op == O_constant)
        {
#ifdef OBJ_ELF
          /* Allow @HA, @L, @H on constants.
             Well actually, no we don't; there really don't make sense
             (at least not to me) for the i370.  However, this code is
             left here for any dubious future expansion reasons.  */
          char *orig_str = str;

          if ((reloc = i370_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
            switch (reloc)
              {
              default:
              str = orig_str;
              break;

              case BFD_RELOC_LO16:
              /* X_unsigned is the default, so if the user has done
                   something which cleared it, we always produce a
                   signed value.  */
              ex.X_add_number = (((ex.X_add_number & 0xffff)
                                ^ 0x8000)
                               - 0x8000);
              break;

              case BFD_RELOC_HI16:
              ex.X_add_number = (ex.X_add_number >> 16) & 0xffff;
              break;

              case BFD_RELOC_HI16_S:
              ex.X_add_number = (((ex.X_add_number >> 16) & 0xffff)
                               + ((ex.X_add_number >> 15) & 1));
              break;
              }
#endif
          insn = i370_insert_operand (insn, operand, ex.X_add_number);
        }
#ifdef OBJ_ELF
      else if ((reloc = i370_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
        {
          as_tsktsk ("md_assemble(): suffixed relocations not supported\n");

          /* We need to generate a fixup for this expression.  */
          if (fc >= MAX_INSN_FIXUPS)
            as_fatal ("too many fixups");
          fixups[fc].exp = ex;
          fixups[fc].opindex = 0;
          fixups[fc].reloc = reloc;
          ++fc;
        }
#endif /* OBJ_ELF */
      else
        {
          /* We need to generate a fixup for this expression.  */
          /* Typically, the expression will just be a symbol ...
               printf ("insn %s needs fixup for %s \n",
                    opcode->name, ex.X_add_symbol->bsym->name);  */

          if (fc >= MAX_INSN_FIXUPS)
            as_fatal ("too many fixups");
          fixups[fc].exp = ex;
          fixups[fc].opindex = *opindex_ptr;
          fixups[fc].reloc = BFD_RELOC_UNUSED;
          ++fc;
        }

      /* Skip over delimiter (close paren, or comma).  */
      if ((')' == *str) && (',' == *(str+1)))
       ++str;
      if (*str != '\0')
       ++str;
    }

  while (ISSPACE (*str))
    ++str;

  if (*str != '\0')
    as_bad ("junk at end of line: `%s'", str);

  /* Write out the instruction.  */
  f = frag_more (opcode->len);
  if (4 >= opcode->len)
    md_number_to_chars (f, insn.i[0], opcode->len);
  else
    {
      md_number_to_chars (f, insn.i[0], 4);

      if (6 == opcode->len)
       md_number_to_chars ((f + 4), ((insn.i[1])>>16), 2);
      else
       {
         /* Not used --- don't have any 8 byte instructions.  */
         as_bad ("Internal Error: bad instruction length");
         md_number_to_chars ((f + 4), insn.i[1], opcode->len -4);
       }
    }

  /* Create any fixups.  At this point we do not use a
     bfd_reloc_code_real_type, but instead just use the
     BFD_RELOC_UNUSED plus the operand index.  This lets us easily
     handle fixups for any operand type, although that is admittedly
     not a very exciting feature.  We pick a BFD reloc type in
     md_apply_fix.  */
  for (i = 0; i < fc; i++)
    {
      const struct i370_operand *operand;

      operand = &i370_operands[fixups[i].opindex];
      if (fixups[i].reloc != BFD_RELOC_UNUSED)
       {
         reloc_howto_type *reloc_howto = bfd_reloc_type_lookup (stdoutput, fixups[i].reloc);
         int size;
         fixS *fixP;

         if (!reloc_howto)
           abort ();

         size = bfd_get_reloc_size (reloc_howto);

         if (size < 1 || size > 4)
           abort ();

         printf (" gwana doo fixup %d \n", i);
         fixP = fix_new_exp (frag_now, f - frag_now->fr_literal, size,
                           &fixups[i].exp, reloc_howto->pc_relative,
                           fixups[i].reloc);

         /* Turn off complaints that the addend is too large for things like
            foo+100000@ha.  */
         switch (fixups[i].reloc)
           {
           case BFD_RELOC_16_GOTOFF:
           case BFD_RELOC_LO16:
           case BFD_RELOC_HI16:
           case BFD_RELOC_HI16_S:
             fixP->fx_no_overflow = 1;
             break;
           default:
             break;
           }
       }
      else
       {
         fix_new_exp (frag_now, f - frag_now->fr_literal, opcode->len,
                     &fixups[i].exp,
                     (operand->flags & I370_OPERAND_RELATIVE) != 0,
                     ((bfd_reloc_code_real_type)
                     (fixups[i].opindex + (int) BFD_RELOC_UNUSED)));
       }
    }
}

Here is the call graph for this function:

char* md_atof ( int type  ,
char *  litp,
int sizep 
)

Definition at line 2364 of file tc-i370.c.

{
  int prec;
  LITTLENUM_TYPE words[4];
  char *t;
  int i;

  switch (type)
    {
    case 'f':
    case 'E':
      type = 'f';
      prec = 2;
      break;

    case 'd':
    case 'D':
      type = 'd';
      prec = 4;
      break;

    default:
      *sizep = 0;
      return "bad call to md_atof";
    }

  /* 360/370/390 have two float formats: an old, funky 360 single-precision
   * format, and the ieee format.  Support only the ieee format.  */
  t = atof_ieee (input_line_pointer, type, words);
  if (t)
    input_line_pointer = t;

  *sizep = prec * 2;

  for (i = 0; i < prec; i++)
    {
      md_number_to_chars (litp, (valueT) words[i], 2);
      litp += 2;
    }

  return NULL;
}

Here is the call graph for this function:

void md_begin ( void  )

Definition at line 484 of file tc-i370.c.

{
  const struct i370_opcode *op;
  const struct i370_opcode *op_end;
  const struct i370_macro *macro;
  const struct i370_macro *macro_end;
  bfd_boolean dup_insn = FALSE;

  i370_set_cpu ();

#ifdef OBJ_ELF
  /* Set the ELF flags if desired.  */
  if (i370_flags)
    bfd_set_private_flags (stdoutput, i370_flags);
#endif

  /* Insert the opcodes into a hash table.  */
  i370_hash = hash_new ();

   op_end = i370_opcodes + i370_num_opcodes;
   for (op = i370_opcodes; op < op_end; op++)
     {
       know ((op->opcode.i[0] & op->mask.i[0]) == op->opcode.i[0]
            && (op->opcode.i[1] & op->mask.i[1]) == op->opcode.i[1]);

       if ((op->flags & i370_cpu) != 0)
         {
           const char *retval;

           retval = hash_insert (i370_hash, op->name, (void *) op);
           if (retval != (const char *) NULL)
             {
               as_bad ("Internal assembler error for instruction %s", op->name);
               dup_insn = TRUE;
             }
         }
     }

  /* Insert the macros into a hash table.  */
  i370_macro_hash = hash_new ();

  macro_end = i370_macros + i370_num_macros;
  for (macro = i370_macros; macro < macro_end; macro++)
    {
      if ((macro->flags & i370_cpu) != 0)
        {
          const char *retval;

          retval = hash_insert (i370_macro_hash, macro->name, (void *) macro);
          if (retval != (const char *) NULL)
            {
              as_bad ("Internal assembler error for macro %s", macro->name);
              dup_insn = TRUE;
            }
        }
    }

  if (dup_insn)
    abort ();
}

Here is the call graph for this function:

void md_convert_frag ( bfd *abfd  ATTRIBUTE_UNUSED,
asection *sec  ATTRIBUTE_UNUSED,
fragS *fragp  ATTRIBUTE_UNUSED 
)

Definition at line 2439 of file tc-i370.c.

{
  abort ();
}
int md_estimate_size_before_relax ( fragS *fragp  ATTRIBUTE_UNUSED,
asection *seg  ATTRIBUTE_UNUSED 
)

Definition at line 2429 of file tc-i370.c.

{
  abort ();
  return 0;
}
void md_number_to_chars ( char *  buf,
valueT  val,
int  n 
)

Definition at line 2411 of file tc-i370.c.

Here is the call graph for this function:

int md_parse_option ( int c  ,
char *  arg 
)

Definition at line 362 of file tc-i370.c.

{
  switch (c)
    {
    case 'u':
      /* -u means that any undefined symbols should be treated as
         external, which is the default for gas anyhow.  */
      break;

#ifdef OBJ_ELF
    case 'K':
      /* Recognize -K PIC */
      if (strcmp (arg, "PIC") == 0 || strcmp (arg, "pic") == 0)
        {
          shlib = SHLIB_PIC;
          i370_flags |= EF_I370_RELOCATABLE_LIB;
        }
      else
        return 0;

      break;
#endif

    case 'm':

      /* -m360 mean to assemble for the ancient 360 architecture.  */
      if (strcmp (arg, "360") == 0 || strcmp (arg, "i360") == 0)
       i370_cpu = I370_OPCODE_360;
      /* -mxa means to assemble for the IBM 370 XA.  */
      else if (strcmp (arg, "xa") == 0)
       i370_cpu = I370_OPCODE_370_XA;
      /* -many means to assemble for any architecture (370/XA).  */
      else if (strcmp (arg, "any") == 0)
       i370_cpu = I370_OPCODE_370;

      else if (strcmp (arg, "regnames") == 0)
       reg_names_p = TRUE;

      else if (strcmp (arg, "no-regnames") == 0)
       reg_names_p = FALSE;

#ifdef OBJ_ELF
      /* -mrelocatable/-mrelocatable-lib -- warn about
        initializations that require relocation.  */
      else if (strcmp (arg, "relocatable") == 0)
        {
          shlib = SHILB_MRELOCATABLE;
          i370_flags |= EF_I370_RELOCATABLE;
        }
      else if (strcmp (arg, "relocatable-lib") == 0)
        {
          shlib = SHILB_MRELOCATABLE;
          i370_flags |= EF_I370_RELOCATABLE_LIB;
        }
#endif
      else
        {
          as_bad ("invalid switch -m%s", arg);
          return 0;
        }
      break;

#ifdef OBJ_ELF
      /* -V: SVR4 argument to print version ID.  */
    case 'V':
      print_version_id ();
      break;

      /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section
         should be emitted or not.  FIXME: Not implemented.  */
    case 'Q':
      break;

#endif

    default:
      return 0;
    }

  return 1;
}

Here is the call graph for this function:

long md_pcrel_from_section ( fixS *  fixp,
segT sec  ATTRIBUTE_UNUSED 
)

Definition at line 2460 of file tc-i370.c.

{
  return fixp->fx_frag->fr_address + fixp->fx_where;
}

Definition at line 2419 of file tc-i370.c.

{
  int align = bfd_get_section_alignment (stdoutput, seg);

  return (addr + (1 << align) - 1) & (-1 << align);
}

Here is the call graph for this function:

void md_show_usage ( FILE *  stream)

Definition at line 78 of file tc-i370.c.

{
  fprintf (stream, "\
S/370 options: (these have not yet been tested and may not work) \n\
-u                   ignored\n\
-mregnames           Allow symbolic names for registers\n\
-mno-regnames               Do not allow symbolic names for registers\n");
#ifdef OBJ_ELF
  fprintf (stream, "\
-mrelocatable               support for GCC's -mrelocatble option\n\
-mrelocatable-lib       support for GCC's -mrelocatble-lib option\n\
-V                   print assembler version number\n");
#endif
}

Here is the call graph for this function:

symbolS* md_undefined_symbol ( char *name  ATTRIBUTE_UNUSED)

Definition at line 2449 of file tc-i370.c.

{
  return 0;
}
static int reg_name_search ( const struct pd_reg regs,
int  regcount,
const char *  name 
) [static]

Definition at line 212 of file tc-i370.c.

{
  int middle, low, high;
  int cmp;

  low = 0;
  high = regcount - 1;

  do
    {
      middle = (low + high) / 2;
      cmp = strcasecmp (name, regs[middle].name);
      if (cmp < 0)
        high = middle - 1;
      else if (cmp > 0)
        low = middle + 1;
      else
        return regs[middle].value;
    }
  while (low <= high);

  return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean register_name ( expressionS expressionP) [static]

Definition at line 249 of file tc-i370.c.

{
  int reg_number;
  char *name;
  char *start;
  char c;

  /* Find the spelling of the operand.  */
  start = name = input_line_pointer;
  if (name[0] == '%' && ISALPHA (name[1]))
    name = ++input_line_pointer;

  else if (!reg_names_p)
    return FALSE;

  while (' ' == *name)
    name = ++input_line_pointer;

  /* If it's a number, treat it as a number.  If it's alpha, look to
     see if it's in the register table.  */
  if (!ISALPHA (name[0]))
    reg_number = get_single_number ();
  else
    {
      c = get_symbol_end ();
      reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT, name);

      /* Put back the delimiting char.  */
      *input_line_pointer = c;
    }

  /* If numeric, make sure its not out of bounds.  */
  if ((0 <= reg_number) && (16 >= reg_number))
    {
      expressionP->X_op = O_register;
      expressionP->X_add_number = reg_number;

      /* Make the rest nice.  */
      expressionP->X_add_symbol = NULL;
      expressionP->X_op_symbol = NULL;
      return TRUE;
    }

  /* Reset the line as if we had not done anything.  */
  input_line_pointer = start;
  return FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void symbol_locate ( symbolS *  symbolP,
const char *  name,
segT  segment,
valueT  valu,
fragS *  frag 
) [static]

Definition at line 1337 of file tc-i370.c.

{
  size_t name_length;
  char *preserved_copy_of_name;

  name_length = strlen (name) + 1;      /* +1 for \0 */
  obstack_grow (&notes, name, name_length);
  preserved_copy_of_name = obstack_finish (&notes);

  S_SET_NAME (symbolP, preserved_copy_of_name);

  S_SET_SEGMENT (symbolP, segment);
  S_SET_VALUE (symbolP, valu);
  symbol_clear_list_pointers (symbolP);

  symbol_set_frag (symbolP, frag);

  /* Link to end of symbol chain.  */
  {
    extern int symbol_table_frozen;

    if (symbol_table_frozen)
      abort ();
  }

  symbol_append (symbolP, symbol_lastP, &symbol_rootP, &symbol_lastP);

  obj_symbol_new_hook (symbolP);

#ifdef tc_symbol_new_hook
  tc_symbol_new_hook (symbolP);
#endif

#define DEBUG_SYMS
#ifdef DEBUG_SYMS
  verify_symbol_chain(symbol_rootP, symbol_lastP);
#endif /* DEBUG_SYMS */
}

Here is the call graph for this function:

Here is the caller graph for this function:

static symbolS* symbol_make_empty ( void  ) [static]

Definition at line 1216 of file tc-i370.c.

Here is the call graph for this function:

Here is the caller graph for this function:

arelent* tc_gen_reloc ( asection *seg  ATTRIBUTE_UNUSED,
fixS *  fixp 
)

Definition at line 2646 of file tc-i370.c.

{
  arelent *reloc;

  reloc = xmalloc (sizeof (arelent));

  reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
  reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
  if (reloc->howto == (reloc_howto_type *) NULL)
    {
      as_bad_where (fixp->fx_file, fixp->fx_line,
                  "reloc %d not supported by object file format", (int)fixp->fx_r_type);
      return NULL;
    }
  reloc->addend = fixp->fx_addnumber;

#ifdef DEBUG
  printf ("\ngen_reloc(): sym %s (%s:%d) at addr 0x%x addend=0x%x\n",
         fixp->fx_addsy->bsym->name,
         fixp->fx_file, fixp->fx_line,
         reloc->address, reloc->addend);
#endif

  return reloc;
}

Here is the call graph for this function:


Variable Documentation

symbolS* byte_poolP = NULL [static]

Definition at line 1210 of file tc-i370.c.

const char comment_chars[] = "#"

Definition at line 59 of file tc-i370.c.

const char EXP_CHARS[] = "eE"

Definition at line 71 of file tc-i370.c.

const char FLT_CHARS[] = "dD"

Definition at line 75 of file tc-i370.c.

int i370_cpu = 0 [static]

Definition at line 301 of file tc-i370.c.

flagword i370_flags = 0 [static]

Definition at line 343 of file tc-i370.c.

Definition at line 332 of file tc-i370.c.

Definition at line 335 of file tc-i370.c.

Definition at line 329 of file tc-i370.c.

Definition at line 326 of file tc-i370.c.

int i370_using_other_regno = -1 [static]

Definition at line 322 of file tc-i370.c.

Definition at line 325 of file tc-i370.c.

int i370_using_text_regno = -1 [static]

Definition at line 321 of file tc-i370.c.

const char line_comment_chars[] = "#*"

Definition at line 63 of file tc-i370.c.

Definition at line 67 of file tc-i370.c.

int lit_pool_num = 1 [static]

Definition at line 1212 of file tc-i370.c.

Definition at line 1204 of file tc-i370.c.

symbolS* longlong_poolP = NULL [static]

Definition at line 1207 of file tc-i370.c.

Definition at line 347 of file tc-i370.c.

size_t md_longopts_size = sizeof (md_longopts)

Definition at line 359 of file tc-i370.c.

const pseudo_typeS md_pseudo_table[]

Definition at line 2676 of file tc-i370.c.

Definition at line 346 of file tc-i370.c.

const char* md_shortopts = "um:"

Definition at line 353 of file tc-i370.c.

Definition at line 1205 of file tc-i370.c.

struct pd_reg[] [static]

Definition at line 135 of file tc-i370.c.

Definition at line 96 of file tc-i370.c.

symbolS* short_poolP = NULL [static]

Definition at line 1209 of file tc-i370.c.

Definition at line 164 of file read.c.

symbolS* word_poolP = NULL [static]

Definition at line 1208 of file tc-i370.c.