Back to index

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

Go to the source code of this file.

Classes

struct  memS
struct  regop
struct  tabentry

Defines

#define S_LEAFPROC   1
#define S_SYSPROC   2
#define adds(e)   e.X_add_symbol
#define offs(e)   e.X_add_number
#define BP_MASK   0x00000002 /* Mask for branch-prediction bit. */
#define BP_TAKEN   0x00000000 /* Value to OR in to predict branch. */
#define BP_NOT_TAKEN   0x00000002 /* Value to OR in to predict no branch. */
#define BE   0x12000000
#define BG   0x11000000
#define BGE   0x13000000
#define BL   0x14000000
#define BLE   0x16000000
#define BNE   0x15000000
#define BNO   0x10000000
#define BO   0x17000000
#define CHKBIT   0x5a002700
#define CMPI   0x5a002080
#define CMPO   0x5a002000
#define B   0x08000000
#define BAL   0x0b000000
#define CALL   0x09000000
#define CALLS   0x66003800
#define RET   0x0a000000
#define A_BIT   0x0400
#define I_BIT   0x0800
#define MEMB_BIT   0x1000
#define D_BIT   0x2000
#define MEMA_ABASE   0x2000
#define SF0   32
#define FP0   64
#define IS_RG_REG(n)   ((0 <= (n)) && ((n) < SF0))
#define IS_SF_REG(n)   ((SF0 <= (n)) && ((n) < FP0))
#define IS_FP_REG(n)   ((n) >= FP0)
#define IPREL   32
#define ARCH_ANY   0 /* Default: no architecture checking done. */
#define ARCH_KA   1
#define ARCH_KB   2
#define ARCH_MC   3
#define ARCH_CA   4
#define ARCH_JX   5
#define ARCH_HX   6
#define BR_LABEL_BASE   "LBRANCH"
#define BR_CNT_FUNC   "__inc_branch"
#define BR_TAB_NAME   "__BRANCH_TABLE__"
#define MAX_LITTLENUMS   6
#define LNUM_SIZE   sizeof (LITTLENUM_TYPE)
#define OPTION_LINKRELAX   (OPTION_MD_BASE)
#define OPTION_NORELAX   (OPTION_MD_BASE + 1)

Typedefs

typedef struct memS memS

Functions

static void ctrl_fmt (char *, long, int)
void md_begin (void)
static void parse_expr (char *textP, expressionS *expP)
static char * emit (long instr)
static void get_cdisp (char *dispP, char *ifmtP, long instr, int numbits, int var_frag, int callj)
static int md_chars_to_number (char *val, int n)
static void mema_to_memb (char *opcodeP)
static int targ_has_sfr (int n)
static int get_regnum (char *regname)
static void syntax (void)
static void parse_regop (struct regop *regopP, char *optext, char opdesc)
static char * get_ispec (char *textP)
static void parse_memop (memS *memP, char *argP, int optype)
static void mem_fmt (char *args[], struct i960_opcode *oP, int callx)
static int targ_has_iclass (int ic)
static int shift_ok (int n)
static int parse_ldconst (char *arg[])
static void reg_fmt (char *args[], struct i960_opcode *oP)
static int get_args (char *p, char *args[])
static int i_scan (char *iP, char *args[])
static void brcnt_emit (void)
static char * brlab_next (void)
static void cobr_fmt (char *arg[], long opcode, struct i960_opcode *oP)
void md_assemble (char *textP)
void md_number_to_chars (char *buf, valueT value, int n)
char * md_atof (int type, char *litP, int *sizeP)
static void md_number_to_imm (char *buf, long val, int n)
static void md_number_to_field (char *instrP, long val, bit_fixS *bfixP)
int md_parse_option (int c, char *arg)
void md_show_usage (FILE *stream)
static void relax_cobr (fragS *fragP)
void md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS *fragP)
int md_estimate_size_before_relax (fragS *fragP, segT segment_type)
void brtab_emit (void)
static void s_leafproc (int n_ops, char *args[])
static void s_sysproc (int n_ops, char *args[])
static void parse_po (int po_num)
int reloc_callj (fixS *fixP)
static void s_endian (int ignore ATTRIBUTE_UNUSED)
symbolS * md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
long md_pcrel_from (fixS *fixP)
void md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
valueT md_section_align (segT seg, valueT addr)
void tc_set_bal_of_call (symbolS *callP ATTRIBUTE_UNUSED, symbolS *balP ATTRIBUTE_UNUSED)
symbolS * tc_get_bal_of_call (symbolS *callP ATTRIBUTE_UNUSED)
void i960_handle_align (fragS *fragp ATTRIBUTE_UNUSED)
int i960_validate_fix (fixS *fixP, segT this_segment_type ATTRIBUTE_UNUSED)
static short tc_bfd_fix2rtype (fixS *fixP)
arelenttc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)

Variables

char * input_line_pointer
static char norelax
static char instrument_branches
const char comment_chars [] = "#"
const char line_comment_chars [] = "#"
const char line_separator_chars [] = ";"
const char EXP_CHARS [] = "eE"
const char FLT_CHARS [] = "fFdDtT"
const relax_typeS md_relax_table []
struct {
char * reg_name
int reg_num
regnames []
struct {
char * areg_name
int areg_num
aregs []
static struct hash_controlop_hash
static struct hash_controlreg_hash
static struct hash_controlareg_hash
int architecture = ARCH_ANY
int iclasses_seen
static int br_cnt
const char * md_shortopts = "A:b"
size_t md_longopts_size = sizeof (md_longopts)
static struct tabentry []
struct {
long compare
long branch
coj []
int coff_flags
const pseudo_typeS md_pseudo_table []

Class Documentation

struct memS

Definition at line 222 of file tc-i960.c.

Class Members
int disp
char * e
long opcode
struct regop

Definition at line 235 of file tc-i960.c.

Class Members
int mode
int n
int special
struct tabentry

Definition at line 1870 of file tc-i960.c.

Class Members
int arch
char * flag

Define Documentation

#define A_BIT   0x0400

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

#define adds (   e)    e.X_add_symbol

Definition at line 184 of file tc-i960.c.

#define ARCH_ANY   0 /* Default: no architecture checking done. */

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

#define ARCH_CA   4

Definition at line 397 of file tc-i960.c.

#define ARCH_HX   6

Definition at line 399 of file tc-i960.c.

#define ARCH_JX   5

Definition at line 398 of file tc-i960.c.

#define ARCH_KA   1

Definition at line 394 of file tc-i960.c.

#define ARCH_KB   2

Definition at line 395 of file tc-i960.c.

#define ARCH_MC   3

Definition at line 396 of file tc-i960.c.

#define B   0x08000000

Definition at line 205 of file tc-i960.c.

#define BAL   0x0b000000

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

#define BE   0x12000000

Definition at line 193 of file tc-i960.c.

#define BG   0x11000000

Definition at line 194 of file tc-i960.c.

#define BGE   0x13000000

Definition at line 195 of file tc-i960.c.

#define BL   0x14000000

Definition at line 196 of file tc-i960.c.

#define BLE   0x16000000

Definition at line 197 of file tc-i960.c.

#define BNE   0x15000000

Definition at line 198 of file tc-i960.c.

#define BNO   0x10000000

Definition at line 199 of file tc-i960.c.

#define BO   0x17000000

Definition at line 200 of file tc-i960.c.

#define BP_MASK   0x00000002 /* Mask for branch-prediction bit. */

Definition at line 188 of file tc-i960.c.

#define BP_NOT_TAKEN   0x00000002 /* Value to OR in to predict no branch. */

Definition at line 190 of file tc-i960.c.

#define BP_TAKEN   0x00000000 /* Value to OR in to predict branch. */

Definition at line 189 of file tc-i960.c.

#define BR_CNT_FUNC   "__inc_branch"

Definition at line 448 of file tc-i960.c.

#define BR_LABEL_BASE   "LBRANCH"

Definition at line 444 of file tc-i960.c.

#define BR_TAB_NAME   "__BRANCH_TABLE__"

Definition at line 452 of file tc-i960.c.

#define CALL   0x09000000

Definition at line 207 of file tc-i960.c.

#define CALLS   0x66003800

Definition at line 208 of file tc-i960.c.

#define CHKBIT   0x5a002700

Definition at line 201 of file tc-i960.c.

#define CMPI   0x5a002080

Definition at line 202 of file tc-i960.c.

#define CMPO   0x5a002000

Definition at line 203 of file tc-i960.c.

#define D_BIT   0x2000

Definition at line 215 of file tc-i960.c.

#define FP0   64
#define I_BIT   0x0800

Definition at line 213 of file tc-i960.c.

#define IPREL   32
#define IS_FP_REG (   n)    ((n) >= FP0)

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

#define IS_RG_REG (   n)    ((0 <= (n)) && ((n) < SF0))

Definition at line 333 of file tc-i960.c.

#define IS_SF_REG (   n)    ((SF0 <= (n)) && ((n) < FP0))

Definition at line 334 of file tc-i960.c.

#define LNUM_SIZE   sizeof (LITTLENUM_TYPE)

Definition at line 1714 of file tc-i960.c.

#define MAX_LITTLENUMS   6

Definition at line 1713 of file tc-i960.c.

#define MEMA_ABASE   0x2000

Definition at line 219 of file tc-i960.c.

#define MEMB_BIT   0x1000

Definition at line 214 of file tc-i960.c.

#define offs (   e)    e.X_add_number

Definition at line 185 of file tc-i960.c.

#define OPTION_NORELAX   (OPTION_MD_BASE + 1)
#define RET   0x0a000000

Definition at line 209 of file tc-i960.c.

#define S_LEAFPROC   1

Definition at line 180 of file tc-i960.c.

#define S_SYSPROC   2

Definition at line 181 of file tc-i960.c.

#define SF0   32

Typedef Documentation

typedef struct memS memS

Function Documentation

static void brcnt_emit ( void  ) [static]

Definition at line 1482 of file tc-i960.c.

{
  /* Emit call to "increment" routine.  */
  ctrl_fmt (BR_CNT_FUNC, CALL, 1);
  /* Emit inline counter to be incremented.  */
  emit (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* brlab_next ( void  ) [static]

Definition at line 1491 of file tc-i960.c.

{
  static char buf[20];

  sprintf (buf, "%s%d", BR_LABEL_BASE, br_cnt++);
  return buf;
}

Here is the caller graph for this function:

void brtab_emit ( void  )

Definition at line 2154 of file tc-i960.c.

{
  int i;
  char buf[20];
  /* Where the binary was output to.  */
  char *p;
  /* Pointer to description of deferred address fixup.  */
  fixS *fixP;

  if (!instrument_branches)
    return;

  subseg_set (data_section, 0);    /*      .data */
  frag_align (2, 0, 0);            /*      .align 2 */
  record_alignment (now_seg, 2);
  colon (BR_TAB_NAME);             /* BR_TAB_NAME: */
  emit (0);                 /*      .word 0 #link to next table */
  emit (br_cnt);            /*      .word n #length of table */

  for (i = 0; i < br_cnt; i++)
    {
      sprintf (buf, "%s%d", BR_LABEL_BASE, i);
      p = emit (0);
      fixP = fix_new (frag_now,
                    p - frag_now->fr_literal,
                    4, symbol_find (buf), 0, 0, NO_RELOC);
    }
}

Here is the call graph for this function:

static void cobr_fmt ( char *  arg[],
long  opcode,
struct i960_opcode oP 
) [static]

Definition at line 1530 of file tc-i960.c.

{
  long instr;               /* 32-bit instruction.  */
  struct regop regop;              /* Description of register operand.  */
  int n;                    /* Number of operands.  */
  int var_frag;                    /* 1 if varying length code fragment should
                                 be emitted;  0 if an address fix
                                    should be emitted.  */

  instr = opcode;
  n = oP->num_ops;

  if (n >= 1)
    {
      /* First operand (if any) of a COBR is always a register
        operand.  Parse it.  */
      parse_regop (&regop, arg[1], oP->operand[0]);
      instr |= (regop.n << 19) | (regop.mode << 13);
    }

  if (n >= 2)
    {
      /* Second operand (if any) of a COBR is always a register
        operand.  Parse it.  */
      parse_regop (&regop, arg[2], oP->operand[1]);
      instr |= (regop.n << 14) | regop.special;
    }

  if (n < 3)
    emit (instr);
  else
    {
      if (instrument_branches)
       {
         brcnt_emit ();
         colon (brlab_next ());
       }

      /* A third operand to a COBR is always a displacement.  Parse
         it; if it's relaxable (a cobr "j" directive, or any cobr
         other than bbs/bbc when the "-norelax" option is not in use)
         set up a variable code fragment; otherwise set up an address
         fix.  */
      var_frag = !norelax || (oP->format == COJ);       /* TRUE or FALSE */
      get_cdisp (arg[3], "COBR", instr, 13, var_frag, 0);

      if (instrument_branches)
       brcnt_emit ();
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void ctrl_fmt ( char *  targP,
long  opcode,
int  num_ops 
) [static]

Definition at line 1500 of file tc-i960.c.

{
  int instrument;           /* TRUE iff we should add instrumentation to track
                               how often the branch is taken.  */

  if (num_ops == 0)
    emit (opcode);          /* Output opcode.  */
  else
    {
      instrument = instrument_branches && (opcode != CALL)
       && (opcode != B) && (opcode != RET) && (opcode != BAL);

      if (instrument)
       {
         brcnt_emit ();
         colon (brlab_next ());
       }

      /* The operand MUST be an ip-relative displacement. Parse it
         and set up address fix for the instruction we just output.  */
      get_cdisp (targP, "CTRL", opcode, 24, 0, 0);

      if (instrument)
       brcnt_emit ();
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* emit ( long  instr) [static]

Definition at line 542 of file tc-i960.c.

{
  char *toP;                /* Where to output it.  */

  toP = frag_more (4);             /* Allocate storage.  */
  md_number_to_chars (toP, instr, 4);     /* Convert to target byte order.  */
  return toP;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int get_args ( char *  p,
char *  args[] 
) [static]

Definition at line 1391 of file tc-i960.c.

{
  int n;             /* Number of operands.  */
  char *to;

  /* Skip lead white space.  */
  while (*p == ' ')
    p++;

  if (*p == '\0')
    return 0;

  n = 1;
  args[1] = p;

  /* Squeze blanks out by moving non-blanks toward start of string.
     Isolate operands, whenever comma is found.  */
  to = p;
  while (*p != '\0')
    {
      if (*p == ' '
         && (! ISALNUM (p[1])
             || ! ISALNUM (p[-1])))
       p++;
      else if (*p == ',')
       {
         /* Start of operand.  */
         if (n == 3)
           {
             as_bad (_("too many operands"));
             return -1;
           }
         *to++ = '\0';             /* Terminate argument.  */
         args[++n] = to;    /* Start next argument.  */
         p++;
       }
      else
       *to++ = *p++;
    }
  *to = '\0';
  return n;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void get_cdisp ( char *  dispP,
char *  ifmtP,
long  instr,
int  numbits,
int  var_frag,
int  callj 
) [static]

Definition at line 564 of file tc-i960.c.

{
  expressionS e;            /* Parsed expression.  */
  fixS *fixP;               /* Structure describing needed address fix.  */
  char *outP;               /* Where instruction binary is output to.  */

  fixP = NULL;

  parse_expr (dispP, &e);
  switch (e.X_op)
    {
    case O_illegal:
      as_bad (_("expression syntax error"));

    case O_symbol:
      if (S_GET_SEGMENT (e.X_add_symbol) == now_seg
         || S_GET_SEGMENT (e.X_add_symbol) == undefined_section)
       {
         if (var_frag)
           {
             outP = frag_more (8); /* Allocate worst-case storage.  */
             md_number_to_chars (outP, instr, 4);
             frag_variant (rs_machine_dependent, 4, 4, 1,
                         adds (e), offs (e), outP);
           }
         else
           {
             /* Set up a new fix structure, so address can be updated
                when all symbol values are known.  */
             outP = emit (instr);
             fixP = fix_new (frag_now,
                           outP - frag_now->fr_literal,
                           4,
                           adds (e),
                           offs (e),
                           1,
                           NO_RELOC);

             fixP->fx_tcbit = callj;

             /* We want to modify a bit field when the address is
                known.  But we don't need all the garbage in the
                bit_fix structure.  So we're going to lie and store
                the number of bits affected instead of a pointer.  */
             fixP->fx_bit_fixP = (bit_fixS *) (size_t) numbits;
           }
       }
      else
       as_bad (_("attempt to branch into different segment"));
      break;

    default:
      as_bad (_("target of %s instruction must be a label"), ifmtP);
      break;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* get_ispec ( char *  textP) [static]

Definition at line 816 of file tc-i960.c.

{
  /* Points to start of index specification.  */
  char *start;
  /* Points to end of index specification.  */
  char *end;

  /* Find opening square bracket, if any.  */
  start = strchr (textP, '[');

  if (start != NULL)
    {
      /* Eliminate '[', detach from rest of operand.  */
      *start++ = '\0';

      end = strchr (start, ']');

      if (end == NULL)
       as_bad (_("unmatched '['"));
      else
       {
         /* Eliminate ']' and make sure it was the last thing
            in the string.  */
         *end = '\0';
         if (*(end + 1) != '\0')
           as_bad (_("garbage after index spec ignored"));
       }
    }
  return start;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int get_regnum ( char *  regname) [static]

Definition at line 695 of file tc-i960.c.

{
  int *rP;

  rP = (int *) hash_find (reg_hash, regname);
  return (rP == NULL) ? -1 : *rP;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void i960_handle_align ( fragS *fragp  ATTRIBUTE_UNUSED)

Definition at line 2621 of file tc-i960.c.

{
  if (!linkrelax)
    return;

#ifndef OBJ_BOUT
  as_bad (_("option --link-relax is only supported in b.out format"));
  linkrelax = 0;
  return;
#else

  /* The text section "ends" with another alignment reloc, to which we
     aren't adding padding.  */
  if (fragp->fr_next == text_last_frag
      || fragp->fr_next == data_last_frag)
    return;

  /* alignment directive */
  fix_new (fragp, fragp->fr_fix, fragp->fr_offset, 0, 0, 0,
          (int) fragp->fr_type);
#endif /* OBJ_BOUT */
}

Here is the call graph for this function:

int i960_validate_fix ( fixS *  fixP,
segT this_segment_type  ATTRIBUTE_UNUSED 
)

Definition at line 2645 of file tc-i960.c.

{
  if (fixP->fx_tcbit && TC_S_IS_CALLNAME (fixP->fx_addsy))
    {
      /* Relocation should be done via the associated 'bal'
         entry point symbol.  */
      if (!TC_S_IS_BALNAME (tc_get_bal_of_call (fixP->fx_addsy)))
       {
         as_bad_where (fixP->fx_file, fixP->fx_line,
                     _("No 'bal' entry point for leafproc %s"),
                     S_GET_NAME (fixP->fx_addsy));
         return 0;
       }
      fixP->fx_addsy = tc_get_bal_of_call (fixP->fx_addsy);
    }

  return 1;
}

Here is the call graph for this function:

static int i_scan ( char *  iP,
char *  args[] 
) [static]

Definition at line 1454 of file tc-i960.c.

{
  /* Isolate opcode.  */
  if (*(iP) == ' ')
    iP++;

  args[0] = iP;
  for (; *iP != ' '; iP++)
    {
      if (*iP == '\0')
       {
         /* There are no operands.  */
         if (args[0] == iP)
           {
             /* We never moved: there was no opcode either!  */
             as_bad (_("missing opcode"));
             return -1;
           }
         return 0;
       }
    }
  *iP++ = '\0';
  return (get_args (iP, args));
}

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 2432 of file tc-i960.c.

{
  long val = *valP;
  char *place = fixP->fx_where + fixP->fx_frag->fr_literal;

  if (!fixP->fx_bit_fixP)
    {
      md_number_to_imm (place, val, fixP->fx_size);
    }
  else if ((int) (size_t) fixP->fx_bit_fixP == 13
          && fixP->fx_addsy != NULL
          && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section)
    {
      /* This is a COBR instruction.  They have only a
        13-bit displacement and are only to be used
        for local branches: flag as error, don't generate
        relocation.  */
      as_bad_where (fixP->fx_file, fixP->fx_line,
                  _("can't use COBR format with external label"));
      fixP->fx_addsy = NULL;
    }
  else
    md_number_to_field (place, val, fixP->fx_bit_fixP);

  if (fixP->fx_addsy == NULL)
    fixP->fx_done = 1;
}

Here is the call graph for this function:

void md_assemble ( char *  textP)

Definition at line 1593 of file tc-i960.c.

{
  /* Parsed instruction text, containing NO whitespace: arg[0]->opcode
     mnemonic arg[1-3]->operands, with char constants replaced by
     decimal numbers.  */
  char *args[4];
  /* Number of instruction operands.  */
  int n_ops;
  /* Pointer to instruction description.  */
  struct i960_opcode *oP;
  /* TRUE iff opcode mnemonic included branch-prediction suffix (".f"
     or ".t").  */
  int branch_predict;
  /* Setting of branch-prediction bit(s) to be OR'd into instruction
     opcode of CTRL/COBR format instructions.  */
  long bp_bits;
  /* Offset of last character in opcode mnemonic.  */
  int n;
  const char *bp_error_msg = _("branch prediction invalid on this opcode");

  /* Parse instruction into opcode and operands.  */
  memset (args, '\0', sizeof (args));

  n_ops = i_scan (textP, args);

  if (n_ops == -1)
    return;                 /* Error message already issued.  */

  /* Do "macro substitution" (sort of) on 'ldconst' pseudo-instruction.  */
  if (!strcmp (args[0], "ldconst"))
    {
      n_ops = parse_ldconst (args);
      if (n_ops == -1)
       return;
    }

  /* Check for branch-prediction suffix on opcode mnemonic, strip it off.  */
  n = strlen (args[0]) - 1;
  branch_predict = 0;
  bp_bits = 0;

  if (args[0][n - 1] == '.' && (args[0][n] == 't' || args[0][n] == 'f'))
    {
      /* We could check here to see if the target architecture
        supports branch prediction, but why bother?  The bit will
        just be ignored by processors that don't use it.  */
      branch_predict = 1;
      bp_bits = (args[0][n] == 't') ? BP_TAKEN : BP_NOT_TAKEN;
      args[0][n - 1] = '\0';       /* Strip suffix from opcode mnemonic */
    }

  /* Look up opcode mnemonic in table and check number of operands.
     Check that opcode is legal for the target architecture.  If all
     looks good, assemble instruction.  */
  oP = (struct i960_opcode *) hash_find (op_hash, args[0]);
  if (!oP || !targ_has_iclass (oP->iclass))
    as_bad (_("invalid opcode, \"%s\"."), args[0]);
  else if (n_ops != oP->num_ops)
    as_bad (_("improper number of operands.  expecting %d, got %d"),
           oP->num_ops, n_ops);
  else
    {
      switch (oP->format)
       {
       case FBRA:
       case CTRL:
         ctrl_fmt (args[1], oP->opcode | bp_bits, oP->num_ops);
         if (oP->format == FBRA)
           /* Now generate a 'bno' to same arg */
           ctrl_fmt (args[1], BNO | bp_bits, 1);
         break;
       case COBR:
       case COJ:
         cobr_fmt (args, oP->opcode | bp_bits, oP);
         break;
       case REG:
         if (branch_predict)
           as_warn (bp_error_msg);
         reg_fmt (args, oP);
         break;
       case MEM1:
         if (args[0][0] == 'c' && args[0][1] == 'a')
           {
             if (branch_predict)
              as_warn (bp_error_msg);
             mem_fmt (args, oP, 1);
             break;
           }
       case MEM2:
       case MEM4:
       case MEM8:
       case MEM12:
       case MEM16:
         if (branch_predict)
           as_warn (bp_error_msg);
         mem_fmt (args, oP, 0);
         break;
       case CALLJ:
         if (branch_predict)
           as_warn (bp_error_msg);
         /* Output opcode & set up "fixup" (relocation); flag
            relocation as 'callj' type.  */
         know (oP->num_ops == 1);
         get_cdisp (args[1], "CTRL", oP->opcode, 24, 0, 1);
         break;
       default:
         BAD_CASE (oP->format);
         break;
       }
    }
}

Here is the call graph for this function:

char* md_atof ( int type  ,
char *  litP,
int sizeP 
)

Definition at line 1727 of file tc-i960.c.

{
  LITTLENUM_TYPE words[MAX_LITTLENUMS];
  LITTLENUM_TYPE *wordP;
  int prec;
  char *t;

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

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

    case 't':
    case 'T':
      prec = 5;
      type = 'x';           /* That's what atof_ieee() understands.  */
      break;

    default:
      *sizeP = 0;
      return _("Bad call to md_atof()");
    }

  t = atof_ieee (input_line_pointer, type, words);
  if (t)
    input_line_pointer = t;

  *sizeP = prec * LNUM_SIZE;

  /* Output the LITTLENUMs in REVERSE order in accord with i80960
     word-order.  (Dunno why atof_ieee doesn't do it in the right
     order in the first place -- probably because it's a hack of
     atof_m68k.)  */
  for (wordP = words + prec - 1; prec--;)
    {
      md_number_to_chars (litP, (long) (*wordP--), LNUM_SIZE);
      litP += sizeof (LITTLENUM_TYPE);
    }

  return 0;
}

Here is the call graph for this function:

void md_begin ( void  )

Definition at line 460 of file tc-i960.c.

{
  int i;                    /* Loop counter.  */
  const struct i960_opcode *oP;    /* Pointer into opcode table.  */
  const char *retval;              /* Value returned by hash functions.  */

  op_hash = hash_new ();
  reg_hash = hash_new ();
  areg_hash = hash_new ();

  /* For some reason, the base assembler uses an empty string for "no
     error message", instead of a NULL pointer.  */
  retval = 0;

  for (oP = i960_opcodes; oP->name && !retval; oP++)
    retval = hash_insert (op_hash, oP->name, (void *) oP);

  for (i = 0; regnames[i].reg_name && !retval; i++)
    retval = hash_insert (reg_hash, regnames[i].reg_name,
                       (char *) &regnames[i].reg_num);

  for (i = 0; aregs[i].areg_name && !retval; i++)
    retval = hash_insert (areg_hash, aregs[i].areg_name,
                       (char *) &aregs[i].areg_num);

  if (retval)
    as_fatal (_("Hashing returned \"%s\"."), retval);
}

Here is the call graph for this function:

static int md_chars_to_number ( char *  val,
int  n 
) [static]

Definition at line 628 of file tc-i960.c.

{
  int retval;

  for (retval = 0; n--;)
    {
      retval <<= 8;
      retval |= (unsigned char) val[n];
    }
  return retval;
}
void md_convert_frag ( bfd *abfd  ATTRIBUTE_UNUSED,
segT sec  ATTRIBUTE_UNUSED,
fragS *  fragP 
)

Definition at line 2044 of file tc-i960.c.

{
  /* Structure describing needed address fix.  */
  fixS *fixP;

  switch (fragP->fr_subtype)
    {
    case 1:
      /* Leave single cobr instruction.  */
      fixP = fix_new (fragP,
                    fragP->fr_opcode - fragP->fr_literal,
                    4,
                    fragP->fr_symbol,
                    fragP->fr_offset,
                    1,
                    NO_RELOC);

      fixP->fx_bit_fixP = (bit_fixS *) 13;       /* Size of bit field.  */
      break;
    case 2:
      /* Replace cobr with compare/branch instructions.  */
      relax_cobr (fragP);
      break;
    default:
      BAD_CASE (fragP->fr_subtype);
      break;
    }
}

Here is the call graph for this function:

int md_estimate_size_before_relax ( fragS *  fragP,
segT  segment_type 
)

Definition at line 2086 of file tc-i960.c.

{
  /* If symbol is undefined in this segment, go to "relaxed" state
     (compare and branch instructions instead of cobr) right now.  */
  if (S_GET_SEGMENT (fragP->fr_symbol) != segment_type)
    {
      relax_cobr (fragP);
      return 4;
    }

  return md_relax_table[fragP->fr_subtype].rlx_length;
}

Here is the call graph for this function:

void md_number_to_chars ( char *  buf,
valueT  value,
int  n 
)

Definition at line 1706 of file tc-i960.c.

Here is the call graph for this function:

static void md_number_to_field ( char *  instrP,
long  val,
bit_fixS *  bfixP 
) [static]

Definition at line 1783 of file tc-i960.c.

{
  int numbits;                     /* Length of bit field to be fixed.  */
  long instr;               /* 32-bit instruction to be fixed-up.  */
  long sign;                /* 0 or -1, according to sign bit of 'val'.  */

  /* Convert instruction back to host byte order.  */
  instr = md_chars_to_number (instrP, 4);

  /* Surprise! -- we stored the number of bits to be modified rather
     than a pointer to a structure.  */
  numbits = (int) (size_t) bfixP;
  if (numbits == 1)
    /* This is a no-op, stuck here by reloc_callj().  */
    return;

  know ((numbits == 13) || (numbits == 24));

  /* Propagate sign bit of 'val' for the given number of bits.  Result
     should be all 0 or all 1.  */
  sign = val >> ((int) numbits - 1);
  if (((val < 0) && (sign != -1))
      || ((val > 0) && (sign != 0)))
    as_bad (_("Fixup of %ld too large for field width of %d"),
           val, numbits);
  else
    {
      /* Put bit field into instruction and write back in target
         * byte order.  */
      val &= ~(-1 << (int) numbits);      /* Clear unused sign bits.  */
      instr |= val;
      md_number_to_chars (instrP, instr, 4);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void md_number_to_imm ( char *  buf,
long  val,
int  n 
) [static]

Definition at line 1777 of file tc-i960.c.

{
  md_number_to_chars (buf, val, n);
}

Here is the caller graph for this function:

int md_parse_option ( int c  ,
char *  arg 
)

Definition at line 1890 of file tc-i960.c.

{
  switch (c)
    {
    case OPTION_LINKRELAX:
      linkrelax = 1;
      flag_keep_locals = 1;
      break;

    case OPTION_NORELAX:
      norelax = 1;
      break;

    case 'b':
      instrument_branches = 1;
      break;

    case 'A':
      {
       const struct tabentry *tp;
       char *p = arg;

       for (tp = arch_tab; tp->flag != NULL; tp++)
         if (!strcmp (p, tp->flag))
           break;

       if (tp->flag == NULL)
         {
           as_bad (_("invalid architecture %s"), p);
           return 0;
         }
       else
         architecture = tp->arch;
      }
      break;

    default:
      return 0;
    }

  return 1;
}

Here is the call graph for this function:

long md_pcrel_from ( fixS *  fixP)

Definition at line 2426 of file tc-i960.c.

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

Definition at line 2526 of file tc-i960.c.

{
  int align;

  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 1934 of file tc-i960.c.

{
  int i;

  fprintf (stream, _("I960 options:\n"));
  for (i = 0; arch_tab[i].flag; i++)
    fprintf (stream, "%s-A%s", i ? " | " : "", arch_tab[i].flag);
  fprintf (stream, _("\n\
                     specify variant of 960 architecture\n\
-b                   add code to collect statistics about branches taken\n\
-link-relax          preserve individual alignment directives so linker\n\
                     can do relaxing (b.out format only)\n\
-no-relax            don't alter compare-and-branch instructions for\n\
                     long displacements\n"));
}

Here is the call graph for this function:

symbolS* md_undefined_symbol ( char *name  ATTRIBUTE_UNUSED)

Definition at line 2417 of file tc-i960.c.

{
  return 0;
}
static void mem_fmt ( char *  args[],
struct i960_opcode oP,
int  callx 
) [static]

Definition at line 1063 of file tc-i960.c.

{
  int i;                    /* Loop counter.  */
  struct regop regop;              /* Description of register operand.  */
  char opdesc;                     /* Operand descriptor byte.  */
  memS instr;               /* Description of binary to be output.  */
  char *outP;               /* Where the binary was output to.  */
  expressionS expr;         /* Parsed expression.  */
  /* ->description of deferred address fixup.  */
  fixS *fixP;

#ifdef OBJ_COFF
  /* COFF support isn't in place yet for callx relaxing.  */
  callx = 0;
#endif

  memset (&instr, '\0', sizeof (memS));
  instr.opcode = oP->opcode;

  /* Process operands.  */
  for (i = 1; i <= oP->num_ops; i++)
    {
      opdesc = oP->operand[i - 1];

      if (MEMOP (opdesc))
       parse_memop (&instr, args[i], oP->format);
      else
       {
         parse_regop (&regop, args[i], opdesc);
         instr.opcode |= regop.n << 19;
       }
    }

  /* Parse the displacement; this must be done before emitting the
     opcode, in case it is an expression using `.'.  */
  parse_expr (instr.e, &expr);

  /* Output opcode.  */
  outP = emit (instr.opcode);

  if (instr.disp == 0)
    return;

  /* Process the displacement.  */
  switch (expr.X_op)
    {
    case O_illegal:
      as_bad (_("expression syntax error"));
      break;

    case O_constant:
      if (instr.disp == 32)
       (void) emit (offs (expr));  /* Output displacement.  */
      else
       {
         /* 12-bit displacement.  */
         if (offs (expr) & ~0xfff)
           {
             /* Won't fit in 12 bits: convert already-output
                instruction to MEMB format, output
                displacement.  */
             mema_to_memb (outP);
             (void) emit (offs (expr));
           }
         else
           {
             /* WILL fit in 12 bits:  OR into opcode and
                overwrite the binary we already put out.  */
             instr.opcode |= offs (expr);
             md_number_to_chars (outP, instr.opcode, 4);
           }
       }
      break;

    default:
      if (instr.disp == 12)
       /* Displacement is dependent on a symbol, whose value
          may change at link time.  We HAVE to reserve 32 bits.
          Convert already-output opcode to MEMB format.  */
       mema_to_memb (outP);

      /* Output 0 displacement and set up address fixup for when
         this symbol's value becomes known.  */
      outP = emit ((long) 0);
      fixP = fix_new_exp (frag_now,
                       outP - frag_now->fr_literal,
                       4, & expr, 0, NO_RELOC);
      /* Steve's linker relaxing hack.  Mark this 32-bit relocation as
         being in the instruction stream, specifically as part of a callx
         instruction.  */
      fixP->fx_bsr = callx;
      break;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void mema_to_memb ( char *  opcodeP) [static]

Definition at line 650 of file tc-i960.c.

{
  long opcode;                     /* Opcode in host byte order.  */
  long mode;                /* Mode bits for MEMB instruction.  */

  opcode = md_chars_to_number (opcodeP, 4);
  know (!(opcode & MEMB_BIT));

  mode = MEMB_BIT | D_BIT;
  if (opcode & MEMA_ABASE)
    mode |= A_BIT;

  opcode &= 0xffffc000;            /* Clear MEMA offset and mode bits.  */
  opcode |= mode;           /* Set MEMB mode bits.  */

  md_number_to_chars (opcodeP, opcode, 4);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void parse_expr ( char *  textP,
expressionS expP 
) [static]

Definition at line 501 of file tc-i960.c.

{
  char *save_in;            /* Save global here.  */
  symbolS *symP;

  know (textP);

  if (*textP == '\0')
    {
      /* Treat empty string as absolute 0.  */
      expP->X_add_symbol = expP->X_op_symbol = NULL;
      expP->X_add_number = 0;
      expP->X_op = O_constant;
    }
  else
    {
      save_in = input_line_pointer;       /* Save global.  */
      input_line_pointer = textP;  /* Make parser work for us.  */

      (void) expression (expP);
      if ((size_t) (input_line_pointer - textP) != strlen (textP))
       /* Did not consume all of the input.  */
       expP->X_op = O_illegal;

      symP = expP->X_add_symbol;
      if (symP && (hash_find (reg_hash, S_GET_NAME (symP))))
       /* Register name in an expression.  */
       /* FIXME: this isn't much of a check any more.  */
       expP->X_op = O_illegal;

      input_line_pointer = save_in;       /* Restore global.  */
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int parse_ldconst ( char *  arg[]) [static]

Definition at line 1237 of file tc-i960.c.

{
  int n;                    /* Constant to be loaded.  */
  int shift;                /* Shift count for "shlo" instruction.  */
  static char buf[5];              /* Literal for first operand.  */
  static char buf2[5];             /* Literal for second operand.  */
  expressionS e;            /* Parsed expression.  */

  arg[3] = NULL;            /* So we can tell at the end if it got used or not.  */

  parse_expr (arg[1], &e);
  switch (e.X_op)
    {
    default:
      /* We're dependent on one or more symbols -- use "lda".  */
      arg[0] = "lda";
      break;

    case O_constant:
      /* Try the following mappings:
              ldconst   0,<reg>  -> mov  0,<reg>
              ldconst  31,<reg>  -> mov  31,<reg>
              ldconst  32,<reg>  -> addo 1,31,<reg>
              ldconst  62,<reg>  -> addo 31,31,<reg>
              ldconst  64,<reg>  -> shlo 8,3,<reg>
              ldconst  -1,<reg>  -> subo 1,0,<reg>
              ldconst -31,<reg>  -> subo 31,0,<reg>
        
         Anything else becomes:
                lda xxx,<reg>.  */
      n = offs (e);
      if ((0 <= n) && (n <= 31))
       arg[0] = "mov";
      else if ((-31 <= n) && (n <= -1))
       {
         arg[0] = "subo";
         arg[3] = arg[2];
         sprintf (buf, "%d", -n);
         arg[1] = buf;
         arg[2] = "0";
       }
      else if ((32 <= n) && (n <= 62))
       {
         arg[0] = "addo";
         arg[3] = arg[2];
         arg[1] = "31";
         sprintf (buf, "%d", n - 31);
         arg[2] = buf;
       }
      else if ((shift = shift_ok (n)) != 0)
       {
         arg[0] = "shlo";
         arg[3] = arg[2];
         sprintf (buf, "%d", shift);
         arg[1] = buf;
         sprintf (buf2, "%d", n >> shift);
         arg[2] = buf2;
       }
      else
       arg[0] = "lda";
      break;

    case O_illegal:
      as_bad (_("invalid constant"));
      return -1;
      break;
    }
  return (arg[3] == 0) ? 2 : 3;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void parse_memop ( memS memP,
char *  argP,
int  optype 
) [static]

Definition at line 878 of file tc-i960.c.

{
  char *indexP;                    /* Pointer to index specification with "[]" removed.  */
  char *p;                  /* Temp char pointer.  */
  char iprel_flag;          /* True if this is an IP-relative operand.  */
  int regnum;               /* Register number.  */
  /* Scale factor: 1,2,4,8, or 16.  Later converted to internal format
     (0,1,2,3,4 respectively).  */
  int scale;
  int mode;                 /* MEMB mode bits.  */
  int *intP;                /* Pointer to register number.  */

  /* The following table contains the default scale factors for each
     type of memory instruction.  It is accessed using (optype-MEM1)
     as an index -- thus it assumes the 'optype' constants are
     assigned consecutive values, in the order they appear in this
     table.  */
  static const int def_scale[] =
  {
    1,                      /* MEM1 */
    2,                      /* MEM2 */
    4,                      /* MEM4 */
    8,                      /* MEM8 */
    -1,                            /* MEM12 -- no valid default */
    16                      /* MEM16 */
  };

  iprel_flag = mode = 0;

  /* Any index present? */
  indexP = get_ispec (argP);
  if (indexP)
    {
      p = strchr (indexP, '*');
      if (p == NULL)
       {
         /* No explicit scale -- use default for this instruction
            type and assembler mode.  */
         if (flag_mri)
           scale = 1;
         else
           /* GNU960 compatibility */
           scale = def_scale[optype - MEM1];
       }
      else
       {
         *p++ = '\0';              /* Eliminate '*' */

         /* Now indexP->a '\0'-terminated register name,
            and p->a scale factor.  */

         if (!strcmp (p, "16"))
           scale = 16;
         else if (strchr ("1248", *p) && (p[1] == '\0'))
           scale = *p - '0';
         else
           scale = -1;
       }

      regnum = get_regnum (indexP);       /* Get index reg. # */
      if (!IS_RG_REG (regnum))
       {
         as_bad (_("invalid index register"));
         return;
       }

      /* Convert scale to its binary encoding.  */
      switch (scale)
       {
       case 1:
         scale = 0 << 7;
         break;
       case 2:
         scale = 1 << 7;
         break;
       case 4:
         scale = 2 << 7;
         break;
       case 8:
         scale = 3 << 7;
         break;
       case 16:
         scale = 4 << 7;
         break;
       default:
         as_bad (_("invalid scale factor"));
         return;
       };

      memP->opcode |= scale | regnum;     /* Set index bits in opcode.  */
      mode |= I_BIT;               /* Found a valid index spec.  */
    }

  /* Any abase (Register Indirect) specification present?  */
  if ((p = strrchr (argP, '(')) != NULL)
    {
      /* "(" is there -- does it start a legal abase spec?  If not, it
         could be part of a displacement expression.  */
      intP = (int *) hash_find (areg_hash, p);
      if (intP != NULL)
       {
         /* Got an abase here.  */
         regnum = *intP;
         *p = '\0';         /* Discard register spec.  */
         if (regnum == IPREL)
           /* We have to specialcase ip-rel mode.  */
           iprel_flag = 1;
         else
           {
             memP->opcode |= regnum << 14;
             mode |= A_BIT;
           }
       }
    }

  /* Any expression present?  */
  memP->e = argP;
  if (*argP != '\0')
    mode |= D_BIT;

  /* Special-case ip-relative addressing.  */
  if (iprel_flag)
    {
      if (mode & I_BIT)
       syntax ();
      else
       {
         memP->opcode |= 5 << 10;  /* IP-relative mode.  */
         memP->disp = 32;
       }
      return;
    }

  /* Handle all other modes.  */
  switch (mode)
    {
    case D_BIT | A_BIT:
      /* Go with MEMA instruction format for now (grow to MEMB later
         if 12 bits is not enough for the displacement).  MEMA format
         has a single mode bit: set it to indicate that abase is
         present.  */
      memP->opcode |= MEMA_ABASE;
      memP->disp = 12;
      break;

    case D_BIT:
      /* Go with MEMA instruction format for now (grow to MEMB later
         if 12 bits is not enough for the displacement).  */
      memP->disp = 12;
      break;

    case A_BIT:
      /* For some reason, the bit string for this mode is not
         consistent: it should be 0 (exclusive of the MEMB bit), so we
         set it "by hand" here.  */
      memP->opcode |= MEMB_BIT;
      break;

    case A_BIT | I_BIT:
      /* set MEMB bit in mode, and OR in mode bits.  */
      memP->opcode |= mode | MEMB_BIT;
      break;

    case I_BIT:
      /* Treat missing displacement as displacement of 0.  */
      mode |= D_BIT;
      /* Fall into next case.  */
    case D_BIT | A_BIT | I_BIT:
    case D_BIT | I_BIT:
      /* Set MEMB bit in mode, and OR in mode bits.  */
      memP->opcode |= mode | MEMB_BIT;
      memP->disp = 32;
      break;

    default:
      syntax ();
      break;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void parse_po ( int  po_num) [static]

Definition at line 2289 of file tc-i960.c.

{
  /* Pointers operands, with no embedded whitespace.
     arg[0] unused, arg[1-3]->operands.  */
  char *args[4];
  int n_ops;                /* Number of operands.  */
  char *p;                  /* Pointer to beginning of unparsed argument string.  */
  char eol;                 /* Character that indicated end of line.  */

  extern char is_end_of_line[];

  /* Advance input pointer to end of line.  */
  p = input_line_pointer;
  while (!is_end_of_line[(unsigned char) *input_line_pointer])
    input_line_pointer++;

  eol = *input_line_pointer;       /* Save end-of-line char.  */
  *input_line_pointer = '\0';      /* Terminate argument list.  */

  /* Parse out operands.  */
  n_ops = get_args (p, args);
  if (n_ops == -1)
    return;

  /* Dispatch to correct handler.  */
  switch (po_num)
    {
    case S_SYSPROC:
      s_sysproc (n_ops, args);
      break;
    case S_LEAFPROC:
      s_leafproc (n_ops, args);
      break;
    default:
      BAD_CASE (po_num);
      break;
    }

  /* Restore eol, so line numbers get updated correctly.  Base
     assembler assumes we leave input pointer pointing at char
     following the eol.  */
  *input_line_pointer++ = eol;
}

Here is the call graph for this function:

static void parse_regop ( struct regop regopP,
char *  optext,
char  opdesc 
) [static]

Definition at line 717 of file tc-i960.c.

{
  int n;                    /* Register number.  */
  expressionS e;            /* Parsed expression.  */

  /* See if operand is a register.  */
  n = get_regnum (optext);
  if (n >= 0)
    {
      if (IS_RG_REG (n))
       {
         /* Global or local register.  */
         if (!REG_ALIGN (opdesc, n))
           as_bad (_("unaligned register"));

         regopP->n = n;
         regopP->mode = 0;
         regopP->special = 0;
         return;
       }
      else if (IS_FP_REG (n) && FP_OK (opdesc))
       {
         /* Floating point register, and it's allowed.  */
         regopP->n = n - FP0;
         regopP->mode = 1;
         regopP->special = 0;
         return;
       }
      else if (IS_SF_REG (n) && SFR_OK (opdesc))
       {
         /* Special-function register, and it's allowed.  */
         regopP->n = n - SF0;
         regopP->mode = 0;
         regopP->special = 1;
         if (!targ_has_sfr (regopP->n))
           as_bad (_("no such sfr in this architecture"));

         return;
       }
    }
  else if (LIT_OK (opdesc))
    {
      /* How about a literal?  */
      regopP->mode = 1;
      regopP->special = 0;
      if (FP_OK (opdesc))
       {
         /* Floating point literal acceptable.  */
         /* Skip over 0f, 0d, or 0e prefix.  */
         if ((optext[0] == '0')
             && (optext[1] >= 'd')
             && (optext[1] <= 'f'))
           optext += 2;

         if (!strcmp (optext, "0.0") || !strcmp (optext, "0"))
           {
             regopP->n = 0x10;
             return;
           }

         if (!strcmp (optext, "1.0") || !strcmp (optext, "1"))
           {
             regopP->n = 0x16;
             return;
           }
       }
      else
       {
         /* Fixed point literal acceptable.  */
         parse_expr (optext, &e);
         if (e.X_op != O_constant
             || (offs (e) < 0) || (offs (e) > 31))
           {
             as_bad (_("illegal literal"));
             offs (e) = 0;
           }
         regopP->n = offs (e);
         return;
       }
    }

  /* Nothing worked.  */
  syntax ();
  regopP->mode = 0;         /* Register r0 is always a good one.  */
  regopP->n = 0;
  regopP->special = 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void reg_fmt ( char *  args[],
struct i960_opcode oP 
) [static]

Definition at line 1310 of file tc-i960.c.

{
  long instr;               /* Binary to be output.  */
  struct regop regop;              /* Description of register operand.  */
  int n_ops;                /* Number of operands.  */

  instr = oP->opcode;
  n_ops = oP->num_ops;

  if (n_ops >= 1)
    {
      parse_regop (&regop, args[1], oP->operand[0]);

      if ((n_ops == 1) && !(instr & M3))
       {
         /* 1-operand instruction in which the dst field should
            be used (instead of src1).  */
         regop.n <<= 19;
         if (regop.special)
           regop.mode = regop.special;
         regop.mode <<= 13;
         regop.special = 0;
       }
      else
       {
         /* regop.n goes in bit 0, needs no shifting.  */
         regop.mode <<= 11;
         regop.special <<= 5;
       }
      instr |= regop.n | regop.mode | regop.special;
    }

  if (n_ops >= 2)
    {
      parse_regop (&regop, args[2], oP->operand[1]);

      if ((n_ops == 2) && !(instr & M3))
       {
         /* 2-operand instruction in which the dst field should
            be used instead of src2).  */
         regop.n <<= 19;
         if (regop.special)
           regop.mode = regop.special;
         regop.mode <<= 13;
         regop.special = 0;
       }
      else
       {
         regop.n <<= 14;
         regop.mode <<= 12;
         regop.special <<= 6;
       }
      instr |= regop.n | regop.mode | regop.special;
    }
  if (n_ops == 3)
    {
      parse_regop (&regop, args[3], oP->operand[2]);
      if (regop.special)
       regop.mode = regop.special;
      instr |= (regop.n <<= 19) | (regop.mode <<= 13);
    }
  emit (instr);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void relax_cobr ( fragS *  fragP) [static]

Definition at line 1986 of file tc-i960.c.

{
  int opcode, src1, src2, m1, s2;
  /* Bit fields from cobr instruction.  */
  long bp_bits;                    /* Branch prediction bits from cobr instruction.  */
  long instr;               /* A single i960 instruction.  */
  /* ->instruction to be replaced.  */
  char *iP;
  fixS *fixP;               /* Relocation that can be done at assembly time.  */

  /* Pick up & parse cobr instruction.  */
  iP = fragP->fr_opcode;
  instr = md_chars_to_number (iP, 4);
  opcode = ((instr >> 24) & 0xff) - 0x30; /* "-0x30" for table index.  */
  src1 = (instr >> 19) & 0x1f;
  m1 = (instr >> 13) & 1;
  s2 = instr & 1;
  src2 = (instr >> 14) & 0x1f;
  bp_bits = instr & BP_MASK;

  /* Generate and output compare instruction.  */
  instr = coj[opcode].compare
    | src1 | (m1 << 11) | (s2 << 6) | (src2 << 14);
  md_number_to_chars (iP, instr, 4);

  /* Output branch instruction.  */
  md_number_to_chars (iP + 4, coj[opcode].branch | bp_bits, 4);

  /* Set up address fixup/relocation.  */
  fixP = fix_new (fragP,
                iP + 4 - fragP->fr_literal,
                4,
                fragP->fr_symbol,
                fragP->fr_offset,
                1,
                NO_RELOC);

  fixP->fx_bit_fixP = (bit_fixS *) 24;    /* Store size of bit field.  */

  fragP->fr_fix += 4;
  frag_wane (fragP);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int reloc_callj ( fixS *  fixP)

Definition at line 2352 of file tc-i960.c.

{
  /* Points to the binary for the instruction being relocated.  */
  char *where;

  if (!fixP->fx_tcbit)
    /* This wasn't a callj instruction in the first place.  */
    return 0;

  where = fixP->fx_frag->fr_literal + fixP->fx_where;

  if (TC_S_IS_SYSPROC (fixP->fx_addsy))
    {
      /* Symbol is a .sysproc: replace 'call' with 'calls'.  System
         procedure number is (other-1).  */
      md_number_to_chars (where, CALLS | TC_S_GET_SYSPROC (fixP->fx_addsy), 4);

      /* Nothing else needs to be done for this instruction.  Make
         sure 'md_number_to_field()' will perform a no-op.  */
      fixP->fx_bit_fixP = (bit_fixS *) 1;
    }
  else if (TC_S_IS_CALLNAME (fixP->fx_addsy))
    {
      /* Should not happen: see block comment above.  */
      as_fatal (_("Trying to 'bal' to %s"), S_GET_NAME (fixP->fx_addsy));
    }
  else if (TC_S_IS_BALNAME (fixP->fx_addsy))
    {
      /* Replace 'call' with 'bal'; both instructions have the same
         format, so calling code should complete relocation as if
         nothing happened here.  */
      md_number_to_chars (where, BAL, 4);
    }
  else if (TC_S_IS_BADPROC (fixP->fx_addsy))
    as_bad (_("Looks like a proc, but can't tell what kind.\n"));

  /* Otherwise Symbol is neither a sysproc nor a leafproc.  */
  return 0;
}

Here is the call graph for this function:

static void s_endian ( int ignore  ATTRIBUTE_UNUSED) [static]

Definition at line 2395 of file tc-i960.c.

{
  char *name;
  char c;

  name = input_line_pointer;
  c = get_symbol_end ();
  if (strcasecmp (name, "little") == 0)
    ;
  else if (strcasecmp (name, "big") == 0)
    as_bad (_("big endian mode is not supported"));
  else
    as_warn (_("ignoring unrecognized .endian type `%s'"), name);

  *input_line_pointer = c;

  demand_empty_rest_of_line ();
}

Here is the call graph for this function:

static void s_leafproc ( int  n_ops,
char *  args[] 
) [static]

Definition at line 2197 of file tc-i960.c.

{
  symbolS *callP;           /* Pointer to leafproc 'call' entry point symbol.  */
  symbolS *balP;            /* Pointer to leafproc 'bal' entry point symbol.  */

  if ((n_ops != 1) && (n_ops != 2))
    {
      as_bad (_("should have 1 or 2 operands"));
      return;
    }

  /* Find or create symbol for 'call' entry point.  */
  callP = symbol_find_or_make (args[1]);

  if (TC_S_IS_CALLNAME (callP))
    as_warn (_("Redefining leafproc %s"), S_GET_NAME (callP));

  /* If that was the only argument, use it as the 'bal' entry point.
     Otherwise, mark it as the 'call' entry point and find or create
     another symbol for the 'bal' entry point.  */
  if ((n_ops == 1) || !strcmp (args[1], args[2]))
    {
      TC_S_FORCE_TO_BALNAME (callP);
    }
  else
    {
      TC_S_FORCE_TO_CALLNAME (callP);

      balP = symbol_find_or_make (args[2]);
      if (TC_S_IS_CALLNAME (balP))
       as_warn (_("Redefining leafproc %s"), S_GET_NAME (balP));

      TC_S_FORCE_TO_BALNAME (balP);

#ifndef OBJ_ELF
      tc_set_bal_of_call (callP, balP);
#endif
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void s_sysproc ( int  n_ops,
char *  args[] 
) [static]

Definition at line 2250 of file tc-i960.c.

{
  expressionS exp;
  symbolS *symP;

  if (n_ops != 2)
    {
      as_bad (_("should have two operands"));
      return;
    }

  /* Parse "entry_num" argument and check it for validity.  */
  parse_expr (args[2], &exp);
  if (exp.X_op != O_constant
      || (offs (exp) < 0)
      || (offs (exp) > 31))
    {
      as_bad (_("'entry_num' must be absolute number in [0,31]"));
      return;
    }

  /* Find/make symbol and stick entry number (biased by +1) into it.  */
  symP = symbol_find_or_make (args[1]);

  if (TC_S_IS_SYSPROC (symP))
    as_warn (_("Redefining entrynum for sysproc %s"), S_GET_NAME (symP));

  TC_S_SET_SYSPROC (symP, offs (exp));    /* Encode entry number.  */
  TC_S_FORCE_TO_SYSPROC (symP);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int shift_ok ( int  n) [static]

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

{
  int shift;                /* The shift count.  */

  if (n <= 0)
    /* Can't do it for negative numbers.  */
    return 0;

  /* Shift 'n' right until a 1 is about to be lost.  */
  for (shift = 0; (n & 1) == 0; shift++)
    n >>= 1;

  if (n >= 32)
    return 0;

  return shift;
}

Here is the caller graph for this function:

static void syntax ( void  ) [static]

Definition at line 706 of file tc-i960.c.

{
  as_bad (_("syntax error"));
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int targ_has_iclass ( int  ic) [static]

Definition at line 1166 of file tc-i960.c.

{
  iclasses_seen |= ic;

  switch (architecture)
    {
    case ARCH_KA:
      return ic & (I_BASE | I_KX);
    case ARCH_KB:
      return ic & (I_BASE | I_KX | I_FP | I_DEC);
    case ARCH_MC:
      return ic & (I_BASE | I_KX | I_FP | I_DEC | I_MIL);
    case ARCH_CA:
      return ic & (I_BASE | I_CX | I_CX2 | I_CASIM);
    case ARCH_JX:
      return ic & (I_BASE | I_CX2 | I_JX);
    case ARCH_HX:
      return ic & (I_BASE | I_CX2 | I_JX | I_HX);
    default:
      if ((iclasses_seen & (I_KX | I_FP | I_DEC | I_MIL))
         && (iclasses_seen & (I_CX | I_CX2)))
       {
         as_warn (_("architecture of opcode conflicts with that of earlier instruction(s)"));
         iclasses_seen &= ~ic;
       }
      return 1;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int targ_has_sfr ( int  n) [static]

Definition at line 674 of file tc-i960.c.

{
  switch (architecture)
    {
    case ARCH_KA:
    case ARCH_KB:
    case ARCH_MC:
    case ARCH_JX:
      return 0;
    case ARCH_HX:
      return ((0 <= n) && (n <= 4));
    case ARCH_CA:
    default:
      return ((0 <= n) && (n <= 2));
    }
}

Here is the caller graph for this function:

static short tc_bfd_fix2rtype ( fixS *  fixP) [static]

Definition at line 2667 of file tc-i960.c.

{
  if (fixP->fx_pcrel == 0 && fixP->fx_size == 4)
    return BFD_RELOC_32;

  if (fixP->fx_pcrel != 0 && fixP->fx_size == 4)
    return BFD_RELOC_24_PCREL;

  abort ();
  return 0;
}

Here is the caller graph for this function:

arelent* tc_gen_reloc ( asection *section  ATTRIBUTE_UNUSED,
fixS *  fixP 
)

Definition at line 2685 of file tc-i960.c.

{
  arelent * reloc;

  reloc = xmalloc (sizeof (arelent));

  /* HACK: Is this right?  */
  fixP->fx_r_type = tc_bfd_fix2rtype (fixP);

  reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
  if (reloc->howto == NULL)
    {
      as_bad_where (fixP->fx_file, fixP->fx_line,
                  "internal error: can't export reloc type %d (`%s')",
                  fixP->fx_r_type,
                  bfd_get_reloc_code_name (fixP->fx_r_type));
      return NULL;
    }

  assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);

  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->addend = fixP->fx_addnumber;

  return reloc;
}

Here is the call graph for this function:

symbolS* tc_get_bal_of_call ( symbolS *callP  ATTRIBUTE_UNUSED)

Definition at line 2580 of file tc-i960.c.

{
  symbolS *retval;

  know (TC_S_IS_CALLNAME (callP));

#ifdef OBJ_COFF
  retval = callP->sy_tc;
#else
#ifdef OBJ_ABOUT
  retval = symbol_next (callP);
#else
  as_fatal ("Only supported for a.out, b.out, or COFF");
#endif /* ! OBJ_ABOUT */
#endif /* ! OBJ_COFF */

  know (TC_S_IS_BALNAME (retval));
  return retval;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void tc_set_bal_of_call ( symbolS *callP  ATTRIBUTE_UNUSED,
symbolS *balP  ATTRIBUTE_UNUSED 
)

Definition at line 2551 of file tc-i960.c.

{
  know (TC_S_IS_CALLNAME (callP));
  know (TC_S_IS_BALNAME (balP));

#ifdef OBJ_COFF

  callP->sy_tc = balP;
  S_SET_NUMBER_AUXILIARY (callP, 2);

#else /* ! OBJ_COFF */
#ifdef OBJ_ABOUT

  /* If the 'bal' entry doesn't immediately follow the 'call'
     symbol, unlink it from the symbol list and re-insert it.  */
  if (symbol_next (callP) != balP)
    {
      symbol_remove (balP, &symbol_rootP, &symbol_lastP);
      symbol_append (balP, callP, &symbol_rootP, &symbol_lastP);
    }                       /* if not in order */

#else /* ! OBJ_ABOUT */
  as_fatal ("Only supported for a.out, b.out, or COFF");
#endif /* ! OBJ_ABOUT */
#endif /* ! OBJ_COFF */
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 400 of file tc-i960.c.

Definition at line 390 of file tc-i960.c.

struct { ... } aregs[] [static]
int br_cnt [static]

Definition at line 442 of file tc-i960.c.

struct { ... } coj[] [static]
const char comment_chars[] = "#"

Definition at line 134 of file tc-i960.c.

const char EXP_CHARS[] = "eE"

Definition at line 150 of file tc-i960.c.

const char FLT_CHARS[] = "fFdDtT"

Definition at line 154 of file tc-i960.c.

Definition at line 401 of file tc-i960.c.

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

char instrument_branches [static]

Definition at line 130 of file tc-i960.c.

const char line_comment_chars[] = "#"

Definition at line 146 of file tc-i960.c.

Definition at line 147 of file tc-i960.c.

size_t md_longopts_size = sizeof (md_longopts)

Definition at line 1868 of file tc-i960.c.

const pseudo_typeS md_pseudo_table[]
Initial value:
{
  {"bss", s_lcomm, 1},
  {"endian", s_endian, 0},
  {"extended", float_cons, 't'},
  {"leafproc", parse_po, S_LEAFPROC},
  {"sysproc", parse_po, S_SYSPROC},

  {"word", cons, 4},
  {"quad", cons, 16},

  {0, 0, 0}
}

Definition at line 2716 of file tc-i960.c.

const relax_typeS md_relax_table[]
Initial value:
{
  {0, 0, 0, 0},                           
  {4088, -4096, 0, 2},                    
  {0x800000 - 8, -0x800000, 4, 0}, 
}

Definition at line 166 of file tc-i960.c.

const char* md_shortopts = "A:b"

Definition at line 1857 of file tc-i960.c.

char norelax [static]

Definition at line 126 of file tc-i960.c.

Definition at line 388 of file tc-i960.c.

Definition at line 389 of file tc-i960.c.

struct { ... } regnames[] [static]
struct tabentry[] [static]
Initial value:
{
  {"KA", ARCH_KA},
  {"KB", ARCH_KB},
  {"SA", ARCH_KA},          
  {"SB", ARCH_KB},          
  {"KC", ARCH_MC},          
  {"MC", ARCH_MC},
  {"CA", ARCH_CA},
  {"JX", ARCH_JX},
  {"HX", ARCH_HX},
  {NULL, 0}
}

Definition at line 1875 of file tc-i960.c.