Back to index

cell-binutils  2.17cvs20070401
Defines | Enumerations | Functions | Variables
tc-crx.c File Reference
#include "as.h"
#include "safe-ctype.h"
#include "dwarf2dbg.h"
#include "opcode/crx.h"
#include "elf/crx.h"

Go to the source code of this file.

Defines

#define WORD_SHIFT   16
#define REG_SIZE   4
#define INSN_MAX_SIZE   3
#define MAX_REGS_IN_MASK16   8
#define streq(a, b)   (strcmp (a, b) == 0)
#define strneq(a, b, c)   (strncmp (a, b, c) == 0)
#define CRX_PRINT(BYTE, NUM, SHIFT)   output_opcode[BYTE] |= (NUM << SHIFT)
#define SWITCH_TABLE(fix)
#define IMAGE_ERR
#define GET_CURRENT_DATA(FUNC, ARRAY)
#define GET_CURRENT_TYPE   GET_CURRENT_DATA(get_optype, cur_type)
#define GET_CURRENT_SIZE   GET_CURRENT_DATA(get_opbits, cur_size)
#define GET_CURRENT_FLAGS   GET_CURRENT_DATA(get_opflags, cur_flags)

Enumerations

enum  op_err {
  OP_LEGAL = 0, OP_OUT_OF_RANGE, OP_NOT_EVEN, OP_ILLEGAL_DISPU4,
  OP_ILLEGAL_CST4, OP_NOT_UPPER_64KB
}

Functions

static void reset_vars (char *)
static reg get_register (char *)
static copreg get_copregister (char *)
static argtype get_optype (operand_type)
static int get_opbits (operand_type)
static int get_opflags (operand_type)
static int get_number_of_operands (void)
static void parse_operand (char *, ins *)
static int gettrap (char *)
static void handle_LoadStor (char *)
static int get_cinv_parameters (char *)
static long getconstant (long, int)
static op_err check_range (long *, int, unsigned int, int)
static int getreg_image (reg)
static void parse_operands (ins *, char *)
static void parse_insn (ins *, char *)
static void print_operand (int, int, argument *)
static void print_constant (int, int, argument *)
static int exponent2scale (int)
static void mask_reg (int, unsigned short *)
static void process_label_constant (char *, ins *)
static void set_operand (char *, ins *)
static char * preprocess_reglist (char *, int *)
static int assemble_insn (char *, ins *)
static void print_insn (ins *)
static void warn_if_needed (ins *)
static int adjust_if_needed (ins *)
valueT md_section_align (segT seg, valueT val)
void md_operand (expressionS *exp)
int crx_force_relocation (fixS *fix)
arelenttc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
int md_estimate_size_before_relax (fragS *fragp, asection *seg)
void md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, fragS *fragP)
int md_parse_option (int c ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED)
void md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
char * md_atof (int type, char *litP, int *sizeP)
void md_apply_fix (fixS *fixP, valueT *valP, segT seg)
long md_pcrel_from (fixS *fixp)
void md_begin (void)
static op_err check_range (long *num, int bits, int unsigned flags, int update)
static void mask_reg (int r, unsigned short int *mask)
void md_assemble (char *op)

Variables

static struct hash_controlcrx_inst_hash
static struct hash_controlreg_hash
static struct hash_controlcopreg_hash
const instinstruction
long output_opcode [2]
int relocatable
char ins_parse [MAX_INST_LEN]
int cur_arg_num
const char comment_chars [] = "#"
const char line_comment_chars [] = "#"
const char line_separator_chars [] = ";"
const char EXP_CHARS [] = "eE"
const char FLT_CHARS [] = "f'"
const char * md_shortopts = ""
size_t md_longopts_size = sizeof (md_longopts)
const pseudo_typeS md_pseudo_table []
const relax_typeS md_relax_table []

Define Documentation

#define CRX_PRINT (   BYTE,
  NUM,
  SHIFT 
)    output_opcode[BYTE] |= (NUM << SHIFT)

Definition at line 49 of file tc-crx.c.

#define GET_CURRENT_DATA (   FUNC,
  ARRAY 
)
Value:
for (i = 0; i < insn->nargs; i++)                         \
    ARRAY[i] = FUNC (instruction->operands[i].op_type)
#define GET_CURRENT_SIZE   GET_CURRENT_DATA(get_opbits, cur_size)
#define GET_CURRENT_TYPE   GET_CURRENT_DATA(get_optype, cur_type)
#define IMAGE_ERR
Value:
as_bad (_("Illegal register (`%s') in Instruction: `%s'"), \
           reg_name, ins_parse);                      \
  break;
#define INSN_MAX_SIZE   3

Definition at line 38 of file tc-crx.c.

#define MAX_REGS_IN_MASK16   8

Definition at line 41 of file tc-crx.c.

#define REG_SIZE   4

Definition at line 35 of file tc-crx.c.

#define streq (   a,
  b 
)    (strcmp (a, b) == 0)

Definition at line 44 of file tc-crx.c.

#define strneq (   a,
  b,
  c 
)    (strncmp (a, b, c) == 0)

Definition at line 45 of file tc-crx.c.

#define SWITCH_TABLE (   fix)
Value:
(   (fix)->fx_addsy != NULL                        \
   && (fix)->fx_subsy != NULL                             \
   && S_GET_SEGMENT ((fix)->fx_addsy) ==           \
      S_GET_SEGMENT ((fix)->fx_subsy)                     \
   && S_GET_SEGMENT (fix->fx_addsy) != undefined_section  \
   && (   (fix)->fx_r_type == BFD_RELOC_CRX_NUM8   \
       || (fix)->fx_r_type == BFD_RELOC_CRX_NUM16         \
       || (fix)->fx_r_type == BFD_RELOC_CRX_NUM32))

Definition at line 280 of file tc-crx.c.

#define WORD_SHIFT   16

Definition at line 32 of file tc-crx.c.


Enumeration Type Documentation

enum op_err
Enumerator:
OP_LEGAL 
OP_OUT_OF_RANGE 
OP_NOT_EVEN 
OP_ILLEGAL_DISPU4 
OP_ILLEGAL_CST4 
OP_NOT_UPPER_64KB 

Definition at line 52 of file tc-crx.c.

  {
    OP_LEGAL = 0,    /* Legal operand.  */
    OP_OUT_OF_RANGE, /* Operand not within permitted range.  */
    OP_NOT_EVEN,     /* Operand is Odd number, should be even.  */
    OP_ILLEGAL_DISPU4,      /* Operand is not within DISPU4 range.  */
    OP_ILLEGAL_CST4, /* Operand is not within CST4 range.  */
    OP_NOT_UPPER_64KB       /* Operand is not within the upper 64KB 
                        (0xFFFF0000-0xFFFFFFFF).  */
  }

Function Documentation

int adjust_if_needed ( ins insn) [static]

Definition at line 1735 of file tc-crx.c.

{
  int ret_value = 0;

  /* Special check for 'addub $0, r0' instruction -
     The opcode '0000 0000 0000 0000' is not allowed.  */
  if (IS_INSN_MNEMONIC ("addub"))
    {
      if ((instruction->operands[0].op_type == cst4)
         && instruction->operands[1].op_type == regr)
        {
          if (insn->arg[0].constant == 0 && insn->arg[1].r == r0)
           {
             instruction++;
             ret_value = 1;
           }
        }
    }

  /* Optimization: Omit a zero displacement in bit operations, 
     saving 2-byte encoding space (e.g., 'cbitw $8, 0(r1)').  */
  if (IS_INSN_TYPE (CSTBIT_INS))
    {
      if ((instruction->operands[1].op_type == rbase_disps12)
          && (insn->arg[1].X_op == O_constant)
          && (insn->arg[1].constant == 0))
            {
              instruction--;
             ret_value = 1;
            }
    }

  return ret_value;
}

Here is the caller graph for this function:

static int assemble_insn ( char *  mnemonic,
ins insn 
) [static]

Definition at line 1493 of file tc-crx.c.

{
  /* Type of each operand in the current template.  */
  argtype cur_type[MAX_OPERANDS];
  /* Size (in bits) of each operand in the current template.  */
  unsigned int cur_size[MAX_OPERANDS];
  /* Flags of each operand in the current template.  */
  unsigned int cur_flags[MAX_OPERANDS];
  /* Instruction type to match.  */
  unsigned int ins_type;
  /* Boolean flag to mark whether a match was found.  */
  int match = 0;
  int i;
  /* Nonzero if an instruction with same number of operands was found.  */
  int found_same_number_of_operands = 0;
  /* Nonzero if an instruction with same argument types was found.  */
  int found_same_argument_types = 0;
  /* Nonzero if a constant was found within the required range.  */
  int found_const_within_range  = 0;
  /* Argument number of an operand with invalid type.  */
  int invalid_optype = -1;
  /* Argument number of an operand with invalid constant value.  */
  int invalid_const  = -1;
  /* Operand error (used for issuing various constant error messages).  */
  op_err op_error, const_err = OP_LEGAL;

/* Retrieve data (based on FUNC) for each operand of a given instruction.  */
#define GET_CURRENT_DATA(FUNC, ARRAY)                            \
  for (i = 0; i < insn->nargs; i++)                              \
    ARRAY[i] = FUNC (instruction->operands[i].op_type)

#define GET_CURRENT_TYPE    GET_CURRENT_DATA(get_optype, cur_type)
#define GET_CURRENT_SIZE    GET_CURRENT_DATA(get_opbits, cur_size)
#define GET_CURRENT_FLAGS   GET_CURRENT_DATA(get_opflags, cur_flags)

  /* Instruction has no operands -> only copy the constant opcode.   */
  if (insn->nargs == 0)
    {
      output_opcode[0] = BIN (instruction->match, instruction->match_bits);
      return 1;
    }

  /* In some case, same mnemonic can appear with different instruction types.
     For example, 'storb' is supported with 3 different types :
     LD_STOR_INS, LD_STOR_INS_INC, STOR_IMM_INS.
     We assume that when reaching this point, the instruction type was 
     pre-determined. We need to make sure that the type stays the same
     during a search for matching instruction.  */
  ins_type = CRX_INS_TYPE(instruction->flags);

  while (/* Check that match is still not found.  */
        match != 1
        /* Check we didn't get to end of table.  */
        && instruction->mnemonic != NULL
        /* Check that the actual mnemonic is still available.  */
        && IS_INSN_MNEMONIC (mnemonic)
        /* Check that the instruction type wasn't changed.  */
        && IS_INSN_TYPE(ins_type))
    {
      /* Check whether number of arguments is legal.  */
      if (get_number_of_operands () != insn->nargs)
       goto next_insn;
      found_same_number_of_operands = 1;

      /* Initialize arrays with data of each operand in current template.  */
      GET_CURRENT_TYPE;
      GET_CURRENT_SIZE;
      GET_CURRENT_FLAGS;

      /* Check for type compatibility.  */
      for (i = 0; i < insn->nargs; i++)
        {
         if (cur_type[i] != insn->arg[i].type)
           {
             if (invalid_optype == -1)
              invalid_optype = i + 1;
             goto next_insn;
           }
       }
      found_same_argument_types = 1;

      for (i = 0; i < insn->nargs; i++)
       {
         /* Reverse the operand indices for certain opcodes:
            Index 0    -->> 1
            Index 1    -->> 0      
            Other index  -->> stays the same.  */
         int j = instruction->flags & REVERSE_MATCH ? 
                i == 0 ? 1 : 
                i == 1 ? 0 : i : 
                i;

         /* Only check range - don't update the constant's value, since the 
            current instruction may not be the last we try to match.  
            The constant's value will be updated later, right before printing 
            it to the object file.  */
         if ((insn->arg[j].X_op == O_constant) 
              && (op_error = check_range (&insn->arg[j].constant, cur_size[j], 
                                      cur_flags[j], 0)))
           {
             if (invalid_const == -1)
             {
              invalid_const = j + 1;
              const_err = op_error;
             }
             goto next_insn;
           }
         /* For symbols, we make sure the relocation size (which was already 
            determined) is sufficient.  */
         else if ((insn->arg[j].X_op == O_symbol)
                  && ((bfd_reloc_type_lookup (stdoutput, insn->rtype))->bitsize 
                      > cur_size[j]))
                goto next_insn;
       }
      found_const_within_range = 1;

      /* If we got till here -> Full match is found.  */
      match = 1;
      break;

/* Try again with next instruction.  */
next_insn:
      instruction++;
    }

  if (!match)
    {
      /* We haven't found a match - instruction can't be assembled.  */
      if (!found_same_number_of_operands)
       as_bad (_("Incorrect number of operands"));
      else if (!found_same_argument_types)
       as_bad (_("Illegal type of operand (arg %d)"), invalid_optype);
      else if (!found_const_within_range)
      {
       switch (const_err)
       {
       case OP_OUT_OF_RANGE:
         as_bad (_("Operand out of range (arg %d)"), invalid_const);
         break;
       case OP_NOT_EVEN:
         as_bad (_("Operand has odd displacement (arg %d)"), invalid_const);
         break;
       case OP_ILLEGAL_DISPU4:
         as_bad (_("Invalid DISPU4 operand value (arg %d)"), invalid_const);
         break;
       case OP_ILLEGAL_CST4:
         as_bad (_("Invalid CST4 operand value (arg %d)"), invalid_const);
         break;
       case OP_NOT_UPPER_64KB:
         as_bad (_("Operand value is not within upper 64 KB (arg %d)"), 
                  invalid_const);
         break;
       default:
         as_bad (_("Illegal operand (arg %d)"), invalid_const);
         break;
       }
      }
      
      return 0;
    }
  else
    /* Full match - print the encoding to output file.  */
    {
      /* Make further checkings (such that couldn't be made earlier).
        Warn the user if necessary.  */
      warn_if_needed (insn);
      
      /* Check whether we need to adjust the instruction pointer.  */
      if (adjust_if_needed (insn))
       /* If instruction pointer was adjusted, we need to update 
          the size of the current template operands.  */
       GET_CURRENT_SIZE;

      for (i = 0; i < insn->nargs; i++)
        {
         int j = instruction->flags & REVERSE_MATCH ? 
                i == 0 ? 1 : 
                i == 1 ? 0 : i : 
                i;

         /* This time, update constant value before printing it.  */
         if ((insn->arg[j].X_op == O_constant) 
              && (check_range (&insn->arg[j].constant, cur_size[j], 
                            cur_flags[j], 1) != OP_LEGAL))
             as_fatal (_("Illegal operand (arg %d)"), j+1);
       }

      /* First, copy the instruction's opcode.  */
      output_opcode[0] = BIN (instruction->match, instruction->match_bits);

      for (i = 0; i < insn->nargs; i++)
        {
         cur_arg_num = i;
          print_operand (cur_size[i], instruction->operands[i].shift, 
                      &insn->arg[i]);
        }
    }

  return 1;
}

Here is the call graph for this function:

static op_err check_range ( long ,
int  ,
unsigned  int,
int   
) [static]
static op_err check_range ( long num,
int  bits,
int unsigned  flags,
int  update 
) [static]

Definition at line 1373 of file tc-crx.c.

{
  long min, max;
  int retval = OP_LEGAL;
  int bin;
  long upper_64kb = 0xFFFF0000;
  long value = *num;

  /* For hosts witah longs bigger than 32-bits make sure that the top 
     bits of a 32-bit negative value read in by the parser are set,
     so that the correct comparisons are made.  */
  if (value & 0x80000000)
    value |= (-1L << 31);

  /* Verify operand value is even.  */
  if (flags & OP_EVEN)
    {
      if (value % 2)
       return OP_NOT_EVEN;
    }

  if (flags & OP_UPPER_64KB)
    {
      /* Check if value is to be mapped to upper 64 KB memory area.  */
      if ((value & upper_64kb) == upper_64kb)
       {
         value -= upper_64kb;
         if (update)
           *num = value;
       }
      else
       return OP_NOT_UPPER_64KB;
    }

  if (flags & OP_SHIFT)
    {
      value >>= 1;
      if (update)
       *num = value;
    }
  else if (flags & OP_SHIFT_DEC)
    {
      value = (value >> 1) - 1;
      if (update)
       *num = value;
    }

  if (flags & OP_ESC)
    {
      /* 0x7e and 0x7f are reserved escape sequences of dispe9.  */
      if (value == 0x7e || value == 0x7f)
       return OP_OUT_OF_RANGE;
    }

  if (flags & OP_DISPU4)
    {
      int is_dispu4 = 0;

      int mul = (instruction->flags & DISPUB4) ? 1 
              : (instruction->flags & DISPUW4) ? 2
              : (instruction->flags & DISPUD4) ? 4 : 0;
      
      for (bin = 0; bin < cst4_maps; bin++)
       {
         if (value == (mul * bin))
           {
             is_dispu4 = 1;
             if (update)
              *num = bin;
             break;
           }
       }
      if (!is_dispu4)
       retval = OP_ILLEGAL_DISPU4;
    }
  else if (flags & OP_CST4)
    {
      int is_cst4 = 0;

      for (bin = 0; bin < cst4_maps; bin++)
       {
         if (value == cst4_map[bin])
           {
             is_cst4 = 1;
             if (update)
              *num = bin;
             break;
           }
       }
      if (!is_cst4)
       retval = OP_ILLEGAL_CST4;
    }
  else if (flags & OP_SIGNED)
    {
      max = (1 << (bits - 1)) - 1;
      min = - (1 << (bits - 1));
      if ((value > max) || (value < min))
       retval = OP_OUT_OF_RANGE;
    }
  else if (flags & OP_UNSIGNED)
    {
      max = ((((1 << (bits - 1)) - 1) << 1) | 1);
      min = 0;
      if (((unsigned long) value > (unsigned long) max) 
           || ((unsigned long) value < (unsigned long) min))
       retval = OP_OUT_OF_RANGE;
    }
  return retval;
}
int crx_force_relocation ( fixS *  fix)

Definition at line 295 of file tc-crx.c.

{
  if (generic_force_reloc (fix) || SWITCH_TABLE (fix))
    return 1;

  return 0;
}

Here is the call graph for this function:

static int exponent2scale ( int  val) [static]

Definition at line 739 of file tc-crx.c.

{
  int exponent;

  /* If 'val' is 0, the following 'for' will be an endless loop.  */
  if (val == 0)
    return 0;

  for (exponent = 0; (val != 1); val >>= 1, exponent++)
    ;

  return exponent;
}

Here is the caller graph for this function:

static int get_cinv_parameters ( char *  operand) [static]

Definition at line 1121 of file tc-crx.c.

{
  char *p = operand;
  int d_used = 0, i_used = 0, u_used = 0, b_used = 0;

  while (*++p != ']')
    {
      if (*p == ',' || *p == ' ')
       continue;

      if (*p == 'd')
       d_used = 1;
      else if (*p == 'i')
       i_used = 1;
      else if (*p == 'u')
       u_used = 1;
      else if (*p == 'b')
       b_used = 1;
      else
       as_bad (_("Illegal `cinv' parameter: `%c'"), *p);
    }

  return ((b_used ? 8 : 0)
       + (d_used ? 4 : 0)
       + (i_used ? 2 : 0)
       + (u_used ? 1 : 0));
}

Here is the call graph for this function:

Here is the caller graph for this function:

static copreg get_copregister ( char *  copreg_name) [static]

Definition at line 221 of file tc-crx.c.

{
  const reg_entry *copreg;

  copreg = (const reg_entry *) hash_find (copreg_hash, copreg_name);

  if (copreg != NULL)
    return copreg->value.copreg_val;
  else
    return nullcopregister;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int get_number_of_operands ( void  ) [static]

Definition at line 1358 of file tc-crx.c.

{
  int i;

  for (i = 0; instruction->operands[i].op_type && i < MAX_OPERANDS; i++)
    ;
  return i;
}

Here is the caller graph for this function:

static int get_opbits ( operand_type  op) [static]

Definition at line 173 of file tc-crx.c.

{
  if (op < MAX_OPRD)
    return crx_optab[op].bit_size;
  else
    return 0;
}
static int get_opflags ( operand_type  op) [static]

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

{
  if (op < MAX_OPRD)
    return crx_optab[op].flags;
  else
    return 0;
}
static argtype get_optype ( operand_type  op) [static]

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

{
  if (op < MAX_OPRD)
    return crx_optab[op].arg_type;
  else
    return nullargs;
}
static reg get_register ( char *  reg_name) [static]

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

{
  const reg_entry *reg;

  reg = (const reg_entry *) hash_find (reg_hash, reg_name);

  if (reg != NULL)
    return reg->value.reg_val;
  else
    return nullregister;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static long getconstant ( long  x,
int  nbits 
) [static]

Definition at line 1220 of file tc-crx.c.

{
  /* The following expression avoids overflow if
     'nbits' is the number of bits in 'bfd_vma'.  */
  return (x & ((((1 << (nbits - 1)) - 1) << 1) | 1));
}

Here is the caller graph for this function:

static int getreg_image ( reg  r) [static]

Definition at line 1154 of file tc-crx.c.

{
  const reg_entry *reg;
  char *reg_name;
  int is_procreg = 0; /* Nonzero means argument should be processor reg.  */

  if (((IS_INSN_MNEMONIC ("mtpr")) && (cur_arg_num == 1))
      || ((IS_INSN_MNEMONIC ("mfpr")) && (cur_arg_num == 0)) )
    is_procreg = 1;

  /* Check whether the register is in registers table.  */
  if (r < MAX_REG)
    reg = &crx_regtab[r];
  /* Check whether the register is in coprocessor registers table.  */
  else if (r < MAX_COPREG)
    reg = &crx_copregtab[r-MAX_REG];
  /* Register not found.  */
  else
    {
      as_bad (_("Unknown register: `%d'"), r);
      return 0;
    }

  reg_name = reg->name;

/* Issue a error message when register is illegal.  */
#define IMAGE_ERR \
  as_bad (_("Illegal register (`%s') in Instruction: `%s'"), \
           reg_name, ins_parse);                      \
  break;

  switch (reg->type)
  {
    case CRX_U_REGTYPE:
      if (is_procreg || (instruction->flags & USER_REG))
       return reg->image;
      else
       IMAGE_ERR;

    case CRX_CFG_REGTYPE:
      if (is_procreg)
       return reg->image;
      else
       IMAGE_ERR;

    case CRX_R_REGTYPE:
      if (! is_procreg)
       return reg->image;
      else
       IMAGE_ERR;

    case CRX_C_REGTYPE:
    case CRX_CS_REGTYPE:
      return reg->image;
      break;

    default:
      IMAGE_ERR;
  }

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int gettrap ( char *  s) [static]

Definition at line 1036 of file tc-crx.c.

{
  const trap_entry *trap;

  for (trap = crx_traps; trap < (crx_traps + NUMTRAPS); trap++)
    if (strcasecmp (trap->name, s) == 0)
      return trap->entry;

  as_bad (_("Unknown exception: `%s'"), s);
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void handle_LoadStor ( char *  operands) [static]

Definition at line 1056 of file tc-crx.c.

{
  /* Post-Increment instructions precede Store-Immediate instructions in 
     CRX instruction table, hence they are handled before. 
     This synchronization should be kept.  */

  /* Assuming Post-Increment insn has the following format :
     'MNEMONIC DISP(REG)+, REG' (e.g. 'loadw 12(r5)+, r6').
     LD_STOR_INS_INC are the only store insns containing a plus sign (+).  */
  if (strstr (operands, ")+") != NULL)
    {
      while (! IS_INSN_TYPE (LD_STOR_INS_INC))
       instruction++;
      return;
    }

  /* Assuming Store-Immediate insn has the following format :
     'MNEMONIC $DISP, ...' (e.g. 'storb $1, 12(r5)').
     STOR_IMM_INS are the only store insns containing a dollar sign ($).  */
  if (strstr (operands, "$") != NULL)
    while (! IS_INSN_TYPE (STOR_IMM_INS))
      instruction++;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void mask_reg ( int  ,
unsigned short *   
) [static]

Here is the caller graph for this function:

static void mask_reg ( int  r,
unsigned short int mask 
) [static]

Definition at line 1775 of file tc-crx.c.

{
  if ((reg)r > (reg)sp)
    {
      as_bad (_("Invalid Register in Register List"));
      return;
    }

  *mask |= (1 << r);
}

Here is the call graph for this function:

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

Definition at line 527 of file tc-crx.c.

{
  valueT val = * valP;
  char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
  fixP->fx_offset = 0;

  switch (fixP->fx_r_type)
    {
    case BFD_RELOC_CRX_NUM8:
      bfd_put_8 (stdoutput, (unsigned char) val, buf);
      break;
    case BFD_RELOC_CRX_NUM16:
      bfd_put_16 (stdoutput, val, buf);
      break;
    case BFD_RELOC_CRX_NUM32:
      bfd_put_32 (stdoutput, val, buf);
      break;
    default:
      /* We shouldn't ever get here because linkrelax is nonzero.  */
      abort ();
      break;
    }

  fixP->fx_done = 0;

  if (fixP->fx_addsy == NULL
      && fixP->fx_pcrel == 0)
    fixP->fx_done = 1;

  if (fixP->fx_pcrel == 1
      && fixP->fx_addsy != NULL
      && S_GET_SEGMENT (fixP->fx_addsy) == seg)
    fixP->fx_done = 1;
}

Here is the call graph for this function:

void md_assemble ( char *  op)

Definition at line 2016 of file tc-crx.c.

{
  ins crx_ins;
  char *param;
  char c;

  /* Reset global variables for a new instruction.  */
  reset_vars (op);

  /* Strip the mnemonic.  */
  for (param = op; *param != 0 && !ISSPACE (*param); param++)
    ;
  c = *param;
  *param++ = '\0';

  /* Find the instruction.  */
  instruction = (const inst *) hash_find (crx_inst_hash, op);
  if (instruction == NULL)
    {
      as_bad (_("Unknown opcode: `%s'"), op);
      return;
    }

  /* Tie dwarf2 debug info to the address at the start of the insn.  */
  dwarf2_emit_insn (0);

  /* Parse the instruction's operands.  */
  parse_insn (&crx_ins, param);

  /* Assemble the instruction - return upon failure.  */
  if (assemble_insn (op, &crx_ins) == 0)
    return;

  /* Print the instruction.  */
  print_insn (&crx_ins);
}

Here is the call graph for this function:

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

Definition at line 472 of file tc-crx.c.

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

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

    case 'd':
      prec = 4;
      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 * 2;

  if (! target_big_endian)
    {
      for (i = prec - 1; i >= 0; i--)
       {
         md_number_to_chars (litP, (valueT) words[i], 2);
         litP += 2;
       }
    }
  else
    {
      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 575 of file tc-crx.c.

{
  const char *hashret = NULL;
  int i = 0;

  /* Set up a hash table for the instructions.  */
  if ((crx_inst_hash = hash_new ()) == NULL)
    as_fatal (_("Virtual memory exhausted"));
  
  while (crx_instruction[i].mnemonic != NULL)
    {
      const char *mnemonic = crx_instruction[i].mnemonic;

      hashret = hash_insert (crx_inst_hash, mnemonic,
       (PTR) &crx_instruction[i]);

      if (hashret != NULL && *hashret != '\0')
       as_fatal (_("Can't hash `%s': %s\n"), crx_instruction[i].mnemonic,
                *hashret == 0 ? _("(unknown reason)") : hashret);

      /* Insert unique names into hash table.  The CRX instruction set
        has many identical opcode names that have different opcodes based
        on the operands.  This hash table then provides a quick index to
        the first opcode with a particular name in the opcode table.  */
      do
       {
         ++i;
       }
      while (crx_instruction[i].mnemonic != NULL
            && streq (crx_instruction[i].mnemonic, mnemonic));
    }

  /* Initialize reg_hash hash table.  */
  if ((reg_hash = hash_new ()) == NULL)
    as_fatal (_("Virtual memory exhausted"));

  {
    const reg_entry *regtab;

    for (regtab = crx_regtab;
        regtab < (crx_regtab + NUMREGS); regtab++)
      {
       hashret = hash_insert (reg_hash, regtab->name, (PTR) regtab);
       if (hashret)
         as_fatal (_("Internal Error:  Can't hash %s: %s"),
                  regtab->name,
                  hashret);
      }
  }

  /* Initialize copreg_hash hash table.  */
  if ((copreg_hash = hash_new ()) == NULL)
    as_fatal (_("Virtual memory exhausted"));

  {
    const reg_entry *copregtab;

    for (copregtab = crx_copregtab; copregtab < (crx_copregtab + NUMCOPREGS);
        copregtab++)
      {
       hashret = hash_insert (copreg_hash, copregtab->name, (PTR) copregtab);
       if (hashret)
         as_fatal (_("Internal Error:  Can't hash %s: %s"),
                  copregtab->name,
                  hashret);
      }
  }
  /*  Set linkrelax here to avoid fixups in most sections.  */
  linkrelax = 1;
}

Here is the call graph for this function:

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

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

{
  /* 'opcode' points to the start of the instruction, whether
     we need to change the instruction's fixed encoding.  */
  char *opcode = fragP->fr_literal + fragP->fr_fix;
  bfd_reloc_code_real_type reloc;

  subseg_change (sec, 0);

  switch (fragP->fr_subtype)
    {
    case 0:
      reloc = BFD_RELOC_CRX_REL8;
      break;
    case 1:
      *opcode = 0x7e;
      reloc = BFD_RELOC_CRX_REL16;
      break;
    case 2:
      *opcode = 0x7f;
      reloc = BFD_RELOC_CRX_REL32;
      break;
    case 3:
      reloc = BFD_RELOC_CRX_REL16;
      break;
    case 4:
      *++opcode = 0x31;
      reloc = BFD_RELOC_CRX_REL32;
      break;
    case 5:
      reloc = BFD_RELOC_CRX_REL8_CMP;
      break;
    case 6:
      *++opcode = 0x31;
      reloc = BFD_RELOC_CRX_REL24;
      break;
    default:
      abort ();
      break;
    }

    fix_new (fragP, fragP->fr_fix,
            bfd_get_reloc_size (bfd_reloc_type_lookup (stdoutput, reloc)),
            fragP->fr_symbol, fragP->fr_offset, 1, reloc);
    fragP->fr_var = 0;
    fragP->fr_fix += md_relax_table[fragP->fr_subtype].rlx_length;
}

Here is the call graph for this function:

int md_estimate_size_before_relax ( fragS *  fragp,
asection * seg   
)

Definition at line 373 of file tc-crx.c.

{
  /* If symbol is undefined or located in a different section,
     select the largest supported relocation.  */
  relax_substateT subtype;
  relax_substateT rlx_state[] = {0, 2,
                             3, 4,
                             5, 6};

  for (subtype = 0; subtype < ARRAY_SIZE (rlx_state); subtype += 2)
    {
      if (fragp->fr_subtype == rlx_state[subtype]
         && (!S_IS_DEFINED (fragp->fr_symbol)
             || seg != S_GET_SEGMENT (fragp->fr_symbol)))
       {
         fragp->fr_subtype = rlx_state[subtype + 1];
         break;
       }
    }

  if (fragp->fr_subtype >= ARRAY_SIZE (md_relax_table))
    abort ();

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

Here is the call graph for this function:

void md_operand ( expressionS exp)

Definition at line 247 of file tc-crx.c.

{
  char c = *input_line_pointer;

  switch (c)
    {
    case '*':
      input_line_pointer++;
      expression (exp);
      break;
    default:
      break;
    }
}
int md_parse_option ( int c  ATTRIBUTE_UNUSED,
char *arg  ATTRIBUTE_UNUSED 
)

Definition at line 453 of file tc-crx.c.

{
  return 0;
}
long md_pcrel_from ( fixS *  fixp)

Definition at line 566 of file tc-crx.c.

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

Definition at line 236 of file tc-crx.c.

{
  /* Round .text section to a multiple of 2.  */
  if (seg == text_section)
    return (val + 1) & ~1;
  return val;
}
void md_show_usage ( FILE *stream  ATTRIBUTE_UNUSED)

Definition at line 461 of file tc-crx.c.

{
  return;
}
static void parse_insn ( ins insn,
char *  operands 
) [static]

Definition at line 1085 of file tc-crx.c.

{
  int i;

  /* Handle instructions with no operands.  */
  for (i = 0; no_op_insn[i] != NULL; i++)
  {
    if (streq (no_op_insn[i], instruction->mnemonic))
    {
      insn->nargs = 0;
      return;
    }
  }

  /* Handle 'excp'/'cinv' instructions.  */
  if (IS_INSN_MNEMONIC ("excp") || IS_INSN_MNEMONIC ("cinv"))
    {
      insn->nargs = 1;
      insn->arg[0].type = arg_ic;
      insn->arg[0].constant = IS_INSN_MNEMONIC ("excp") ?
       gettrap (operands) : get_cinv_parameters (operands);
      insn->arg[0].X_op = O_constant;
      return;
    }

  /* Handle load/stor unique instructions before parsing.  */
  if (IS_INSN_TYPE (LD_STOR_INS))
    handle_LoadStor (operands);

  if (operands != NULL)
    parse_operands (insn, operands);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void parse_operand ( char *  operand,
ins crx_ins 
) [static]

Definition at line 882 of file tc-crx.c.

{
  int ret_val;
  argument *cur_arg = &crx_ins->arg[cur_arg_num]; /* Current argument.  */

  /* Initialize the type to NULL before parsing.  */
  cur_arg->type = nullargs;

  /* Check whether this is a general processor register.  */
  if ((ret_val = get_register (operand)) != nullregister)
    {
      cur_arg->type = arg_r;
      cur_arg->r = ret_val;
      cur_arg->X_op = O_register;
      return;
    }

  /* Check whether this is a core [special] coprocessor register.  */
  if ((ret_val = get_copregister (operand)) != nullcopregister)
    {
      cur_arg->type = arg_copr;
      if (ret_val >= cs0)
       cur_arg->type = arg_copsr;
      cur_arg->cr = ret_val;
      cur_arg->X_op = O_register;
      return;
    }

  /* Deal with special characters.  */
  switch (operand[0])
    {
    case '$':
      if (strchr (operand, '(') != NULL)
       cur_arg->type = arg_icr;
      else
        cur_arg->type = arg_ic;
      goto set_params;
      break;

    case '*':
      cur_arg->type = arg_sc;
      goto set_params;
      break;

    case '(':
      cur_arg->type = arg_rbase;
      goto set_params;
      break;

    default:
       break;
    }
      
  if (strchr (operand, '(') != NULL)
    {
      if (strchr (operand, ',') != NULL
          && (strchr (operand, ',') > strchr (operand, '(')))
           cur_arg->type = arg_idxr;
      else
       cur_arg->type = arg_cr;
    }
  else
    cur_arg->type = arg_c;
  goto set_params;

/* Parse an operand according to its type.  */
set_params:
  cur_arg->constant = 0;
  set_operand (operand, crx_ins);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void parse_operands ( ins crx_ins,
char *  operands 
) [static]

Definition at line 957 of file tc-crx.c.

{
  char *operandS;           /* Operands string.  */
  char *operandH, *operandT;   /* Single operand head/tail pointers.  */
  int allocated = 0;        /* Indicates a new operands string was allocated.  */
  char *operand[MAX_OPERANDS]; /* Separating the operands.  */
  int op_num = 0;           /* Current operand number we are parsing.  */
  int bracket_flag = 0;            /* Indicates a bracket '(' was found.  */
  int sq_bracket_flag = 0;     /* Indicates a square bracket '[' was found.  */

  /* Preprocess the list of registers, if necessary.  */
  operandS = operandH = operandT = (INST_HAS_REG_LIST) ?
    preprocess_reglist (operands, &allocated) : operands;

  while (*operandT != '\0')
    {
      if (*operandT == ',' && bracket_flag != 1 && sq_bracket_flag != 1)
        {
         *operandT++ = '\0';
         operand[op_num++] = strdup (operandH);
          operandH = operandT;
          continue;
        }

      if (*operandT == ' ')
       as_bad (_("Illegal operands (whitespace): `%s'"), ins_parse);

      if (*operandT == '(')
       bracket_flag = 1;
      else if (*operandT == '[')
       sq_bracket_flag = 1;

      if (*operandT == ')')
       {
         if (bracket_flag)
           bracket_flag = 0;
         else
           as_fatal (_("Missing matching brackets : `%s'"), ins_parse);
       }
      else if (*operandT == ']')
       {
         if (sq_bracket_flag)
           sq_bracket_flag = 0;
         else
           as_fatal (_("Missing matching brackets : `%s'"), ins_parse);
       }

      if (bracket_flag == 1 && *operandT == ')')
       bracket_flag = 0;
      else if (sq_bracket_flag == 1 && *operandT == ']')
       sq_bracket_flag = 0;

      operandT++;
    }

  /* Adding the last operand.  */
  operand[op_num++] = strdup (operandH);
  crx_ins->nargs = op_num;

  /* Verifying correct syntax of operands (all brackets should be closed).  */
  if (bracket_flag || sq_bracket_flag)
    as_fatal (_("Missing matching brackets : `%s'"), ins_parse);

  /* Now we parse each operand separately.  */
  for (op_num = 0; op_num < crx_ins->nargs; op_num++)
    {
      cur_arg_num = op_num;
      parse_operand (operand[op_num], crx_ins);
      free (operand[op_num]);
    }

  if (allocated)
    free (operandS);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char * preprocess_reglist ( char *  param,
int allocated 
) [static]

Definition at line 1791 of file tc-crx.c.

{
  char reg_name[MAX_REGNAME_LEN]; /* Current parsed register name.  */
  char *regP;                 /* Pointer to 'reg_name' string.  */
  int reg_counter = 0;               /* Count number of parsed registers.  */
  unsigned short int mask = 0;       /* Mask for 16 general purpose registers.  */
  char *new_param;            /* New created operands string.  */
  char *paramP = param;              /* Pointer to original opearands string.  */
  char maskstring[10];               /* Array to print the mask as a string.  */
  int hi_found = 0, lo_found = 0; /* Boolean flags for hi/lo registers.  */
  reg r;
  copreg cr;

  /* If 'param' is already in form of a number, no need to preprocess.  */
  if (strchr (paramP, '{') == NULL)
    return param;

  /* Verifying correct syntax of operand.  */
  if (strchr (paramP, '}') == NULL)
    as_fatal (_("Missing matching brackets : `%s'"), ins_parse);

  while (*paramP++ != '{');

  new_param = (char *)xcalloc (MAX_INST_LEN, sizeof (char));
  *allocated = 1;
  strncpy (new_param, param, paramP - param - 1);

  while (*paramP != '}')
    {
      regP = paramP;
      memset (&reg_name, '\0', sizeof (reg_name));

      while (ISALNUM (*paramP))
       paramP++;

      strncpy (reg_name, regP, paramP - regP);

      /* Coprocessor register c<N>.  */
      if (IS_INSN_TYPE (COP_REG_INS))
        {
          if (((cr = get_copregister (reg_name)) == nullcopregister)
             || (crx_copregtab[cr-MAX_REG].type != CRX_C_REGTYPE))
           as_fatal (_("Illegal register `%s' in cop-register list"), reg_name);
         mask_reg (getreg_image (cr - c0), &mask);
        }
      /* Coprocessor Special register cs<N>.  */
      else if (IS_INSN_TYPE (COPS_REG_INS))
        {
          if (((cr = get_copregister (reg_name)) == nullcopregister)
             || (crx_copregtab[cr-MAX_REG].type != CRX_CS_REGTYPE))
           as_fatal (_("Illegal register `%s' in cop-special-register list"), 
                    reg_name);
         mask_reg (getreg_image (cr - cs0), &mask);
        }
      /* User register u<N>.  */
      else if (instruction->flags & USER_REG)
       {
         if (streq(reg_name, "uhi"))
           {
             hi_found = 1;
             goto next_inst;
           }
         else if (streq(reg_name, "ulo"))
           {
             lo_found = 1;
             goto next_inst;
           }
          else if (((r = get_register (reg_name)) == nullregister)
             || (crx_regtab[r].type != CRX_U_REGTYPE))
           as_fatal (_("Illegal register `%s' in user register list"), reg_name);
         
         mask_reg (getreg_image (r - u0), &mask);         
       }
      /* General purpose register r<N>.  */
      else
        {
         if (streq(reg_name, "hi"))
           {
             hi_found = 1;
             goto next_inst;
           }
         else if (streq(reg_name, "lo"))
           {
             lo_found = 1;
             goto next_inst;
           }
          else if (((r = get_register (reg_name)) == nullregister)
             || (crx_regtab[r].type != CRX_R_REGTYPE))
           as_fatal (_("Illegal register `%s' in register list"), reg_name);

         mask_reg (getreg_image (r - r0), &mask);
        }

      if (++reg_counter > MAX_REGS_IN_MASK16)
       as_bad (_("Maximum %d bits may be set in `mask16' operand"),
              MAX_REGS_IN_MASK16);

next_inst:
      while (!ISALNUM (*paramP) && *paramP != '}')
         paramP++;
    }

  if (*++paramP != '\0')
    as_warn (_("rest of line ignored; first ignored character is `%c'"),
            *paramP);

  switch (hi_found + lo_found)
    {
    case 0:
      /* At least one register should be specified.  */
      if (mask == 0)
       as_bad (_("Illegal `mask16' operand, operation is undefined - `%s'"),
              ins_parse);
      break;

    case 1:
      /* HI can't be specified without LO (and vise-versa).  */
      as_bad (_("HI/LO registers should be specified together"));
      break;

    case 2:
      /* HI/LO registers mustn't be masked with additional registers.  */
      if (mask != 0)
       as_bad (_("HI/LO registers should be specified without additional registers"));

    default:
      break;
    }

  sprintf (maskstring, "$0x%x", mask);
  strcat (new_param, maskstring);
  return new_param;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void print_constant ( int  nbits,
int  shift,
argument arg 
) [static]

Definition at line 1233 of file tc-crx.c.

{
  unsigned long mask = 0;

  long constant = getconstant (arg->constant, nbits);

  switch (nbits)
  {
    case 32:
    case 28:
    case 24:
    case 22:
      /* mask the upper part of the constant, that is, the bits
        going to the lowest byte of output_opcode[0].
        The upper part of output_opcode[1] is always filled,
        therefore it is always masked with 0xFFFF.  */
      mask = (1 << (nbits - 16)) - 1;
      /* Divide the constant between two consecutive words :
               0        1        2        3
           +---------+---------+---------+---------+
           |        | X X X X | X X X X |     |
           +---------+---------+---------+---------+
             output_opcode[0]    output_opcode[1]     */

      CRX_PRINT (0, (constant >> WORD_SHIFT) & mask, 0);
      CRX_PRINT (1, (constant & 0xFFFF), WORD_SHIFT);
      break;

    case 16:
    case 12:
      /* Special case - in arg_cr, the SHIFT represents the location
        of the REGISTER, not the constant, which is itself not shifted.  */
      if (arg->type == arg_cr)
       {
         CRX_PRINT (0, constant,  0);
         break;
       }

      /* When instruction size is 3 and 'shift' is 16, a 16-bit constant is 
        always filling the upper part of output_opcode[1]. If we mistakenly 
        write it to output_opcode[0], the constant prefix (that is, 'match')
        will be overridden.
               0        1        2        3
           +---------+---------+---------+---------+
           | 'match' |         | X X X X |           |
           +---------+---------+---------+---------+
             output_opcode[0]    output_opcode[1]     */

      if ((instruction->size > 2) && (shift == WORD_SHIFT))
       CRX_PRINT (1, constant, WORD_SHIFT);
      else
       CRX_PRINT (0, constant, shift);
      break;

    default:
      CRX_PRINT (0, constant,  shift);
      break;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void print_insn ( ins insn) [static]

Definition at line 1929 of file tc-crx.c.

{
  unsigned int i, j, insn_size;
  char *this_frag;
  unsigned short words[4];
  int addr_mod;

  /* Arrange the insn encodings in a WORD size array.  */
  for (i = 0, j = 0; i < 2; i++)
    {
      words[j++] = (output_opcode[i] >> 16) & 0xFFFF;
      words[j++] = output_opcode[i] & 0xFFFF;
    }

  /* Handle relaxtion.  */
  if ((instruction->flags & RELAXABLE) && relocatable)
    {
      int relax_subtype;

      /* Write the maximal instruction size supported.  */
      insn_size = INSN_MAX_SIZE;

      /* bCC  */
      if (IS_INSN_TYPE (BRANCH_INS))
       relax_subtype = 0;
      /* bal  */
      else if (IS_INSN_TYPE (DCR_BRANCH_INS) || IS_INSN_MNEMONIC ("bal"))
       relax_subtype = 3;
      /* cmpbr/bcop  */
      else if (IS_INSN_TYPE (CMPBR_INS) || IS_INSN_TYPE (COP_BRANCH_INS))
       relax_subtype = 5;
      else
       abort ();

      this_frag = frag_var (rs_machine_dependent, insn_size * 2,
                         4, relax_subtype,
                         insn->exp.X_add_symbol,
                         insn->exp.X_add_number,
                         0);
    }
  else
    {
      insn_size = instruction->size;
      this_frag = frag_more (insn_size * 2);

      /* Handle relocation.  */
      if ((relocatable) && (insn->rtype != BFD_RELOC_NONE))
       {
         reloc_howto_type *reloc_howto;
         int size;

         reloc_howto = bfd_reloc_type_lookup (stdoutput, insn->rtype);

         if (!reloc_howto)
           abort ();

         size = bfd_get_reloc_size (reloc_howto);

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

         fix_new_exp (frag_now, this_frag - frag_now->fr_literal,
                     size, &insn->exp, reloc_howto->pc_relative,
                     insn->rtype);
       }
    }

  /* Verify a 2-byte code alignment.  */
  addr_mod = frag_now_fix () & 1;
  if (frag_now->has_code && frag_now->insn_addr != addr_mod)
    as_bad (_("instruction address is not a multiple of 2"));
  frag_now->insn_addr = addr_mod;
  frag_now->has_code = 1;

  /* Write the instruction encoding to frag.  */
  for (i = 0; i < insn_size; i++)
    {
      md_number_to_chars (this_frag, (valueT) words[i], 2);
      this_frag += 2;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void print_operand ( int  nbits,
int  shift,
argument arg 
) [static]

Definition at line 1300 of file tc-crx.c.

{
  switch (arg->type)
    {
    case arg_r:
      CRX_PRINT (0, getreg_image (arg->r), shift);
      break;

    case arg_copr:
      if (arg->cr < c0 || arg->cr > c15)
       as_bad (_("Illegal Co-processor register in Instruction `%s' "),
              ins_parse);
      CRX_PRINT (0, getreg_image (arg->cr), shift);
      break;

    case arg_copsr:
      if (arg->cr < cs0 || arg->cr > cs15)
       as_bad (_("Illegal Co-processor special register in Instruction `%s' "),
              ins_parse);
      CRX_PRINT (0, getreg_image (arg->cr), shift);
      break;

    case arg_idxr:
      /*    16      12            8    6         0
           +--------------------------------+
           | r_base | r_idx  | scl|  disp   |
           +--------------------------------+      */
      CRX_PRINT (0, getreg_image (arg->r), 12);
      CRX_PRINT (0, getreg_image (arg->i_r), 8);
      CRX_PRINT (0, arg->scale, 6);
    case arg_ic:
    case arg_c:
      print_constant (nbits, shift, arg);
      break;

    case arg_rbase:
      CRX_PRINT (0, getreg_image (arg->r), shift);
      break;

    case arg_cr:
      /* case base_cst4.  */
      if (instruction->flags & DISPU4MAP)
       print_constant (nbits, shift + REG_SIZE, arg);
      else
       /* rbase_disps<NN> and other such cases.  */
       print_constant (nbits, shift, arg);
      /* Add the register argument to the output_opcode.  */
      CRX_PRINT (0, getreg_image (arg->r), shift);
      break;

    default:
      break;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void process_label_constant ( char *  str,
ins crx_ins 
) [static]

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

{
  char *saved_input_line_pointer;
  argument *cur_arg = &crx_ins->arg[cur_arg_num];  /* Current argument.  */

  saved_input_line_pointer = input_line_pointer;
  input_line_pointer = str;

  expression (&crx_ins->exp);
  
  switch (crx_ins->exp.X_op)
    {
    case O_big:
    case O_absent:
      /* Missing or bad expr becomes absolute 0.  */
      as_bad (_("missing or invalid displacement expression `%s' taken as 0"),
             str);
      crx_ins->exp.X_op = O_constant;
      crx_ins->exp.X_add_number = 0;
      crx_ins->exp.X_add_symbol = (symbolS *) 0;
      crx_ins->exp.X_op_symbol = (symbolS *) 0;
      /* Fall through.  */

    case O_constant:
      cur_arg->X_op = O_constant;
      cur_arg->constant = crx_ins->exp.X_add_number;
      break;

    case O_symbol:
    case O_subtract:
    case O_add:
      cur_arg->X_op = O_symbol;
      crx_ins->rtype = BFD_RELOC_NONE;
      relocatable = 1;

      switch (cur_arg->type)
       {
       case arg_cr:
          if (IS_INSN_TYPE (LD_STOR_INS_INC))
           crx_ins->rtype = BFD_RELOC_CRX_REGREL12;
          else if (IS_INSN_TYPE (CSTBIT_INS)
                 || IS_INSN_TYPE (STOR_IMM_INS))
           crx_ins->rtype = BFD_RELOC_CRX_REGREL28;
          else
           crx_ins->rtype = BFD_RELOC_CRX_REGREL32;
         break;

       case arg_idxr:
           crx_ins->rtype = BFD_RELOC_CRX_REGREL22;
         break;
       
       case arg_c:
          if (IS_INSN_MNEMONIC ("bal") || IS_INSN_TYPE (DCR_BRANCH_INS))
           crx_ins->rtype = BFD_RELOC_CRX_REL16;
         else if (IS_INSN_TYPE (BRANCH_INS))
           crx_ins->rtype = BFD_RELOC_CRX_REL8;
          else if (IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (STOR_IMM_INS)
                 || IS_INSN_TYPE (CSTBIT_INS))
           crx_ins->rtype = BFD_RELOC_CRX_ABS32;
         else if (IS_INSN_TYPE (BRANCH_NEQ_INS))
           crx_ins->rtype = BFD_RELOC_CRX_REL4;
          else if (IS_INSN_TYPE (CMPBR_INS) || IS_INSN_TYPE (COP_BRANCH_INS))
           crx_ins->rtype = BFD_RELOC_CRX_REL8_CMP;
         break;
       
       case arg_ic:
          if (IS_INSN_TYPE (ARITH_INS))
           crx_ins->rtype = BFD_RELOC_CRX_IMM32;
         else if (IS_INSN_TYPE (ARITH_BYTE_INS))
           crx_ins->rtype = BFD_RELOC_CRX_IMM16;
         break;
       default:
         break;
      }
      break;

    default:
      cur_arg->X_op = crx_ins->exp.X_op;
      break;
    }

  input_line_pointer = saved_input_line_pointer;
  return;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void reset_vars ( char *  op) [static]

Definition at line 265 of file tc-crx.c.

{
  cur_arg_num = relocatable = 0;
  memset (& output_opcode, '\0', sizeof (output_opcode));

  /* Save a copy of the original OP (used in error messages).  */
  strncpy (ins_parse, op, sizeof ins_parse - 1);
  ins_parse [sizeof ins_parse - 1] = 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void set_operand ( char *  operand,
ins crx_ins 
) [static]

Definition at line 762 of file tc-crx.c.

{
  char *operandS; /* Pointer to start of sub-opearand.  */
  char *operandE; /* Pointer to end of sub-opearand.  */
  expressionS scale;
  int scale_val;
  char *input_save, c;
  argument *cur_arg = &crx_ins->arg[cur_arg_num]; /* Current argument.  */

  /* Initialize pointers.  */
  operandS = operandE = operand;

  switch (cur_arg->type)
    {
    case arg_sc:    /* Case *+0x18.  */
    case arg_ic:    /* Case $0x18.  */
      operandS++;
    case arg_c:          /* Case 0x18.  */
      /* Set constant.  */
      process_label_constant (operandS, crx_ins);
      
      if (cur_arg->type != arg_ic)
       cur_arg->type = arg_c;
      break;

    case arg_icr:   /* Case $0x18(r1).  */
      operandS++;
    case arg_cr:    /* Case 0x18(r1).   */
      /* Set displacement constant.  */
      while (*operandE != '(')
       operandE++;
      *operandE = '\0';
      process_label_constant (operandS, crx_ins);
      operandS = operandE;    
    case arg_rbase: /* Case (r1).  */
      operandS++;
      /* Set register base.  */
      while (*operandE != ')')
       operandE++;
      *operandE = '\0';
      if ((cur_arg->r = get_register (operandS)) == nullregister)
       as_bad (_("Illegal register `%s' in Instruction `%s'"),
              operandS, ins_parse);

      if (cur_arg->type != arg_rbase)
       cur_arg->type = arg_cr;
      break;

    case arg_idxr:
      /* Set displacement constant.  */
      while (*operandE != '(')
       operandE++;
      *operandE = '\0';
      process_label_constant (operandS, crx_ins);
      operandS = ++operandE;
      
      /* Set register base.  */
      while ((*operandE != ',') && (! ISSPACE (*operandE)))
       operandE++;
      *operandE++ = '\0';
      if ((cur_arg->r = get_register (operandS)) == nullregister)
       as_bad (_("Illegal register `%s' in Instruction `%s'"),
              operandS, ins_parse);

      /* Skip leading white space.  */
      while (ISSPACE (*operandE))
       operandE++;
      operandS = operandE;

      /* Set register index.  */
      while ((*operandE != ')') && (*operandE != ','))
       operandE++;
      c = *operandE;
      *operandE++ = '\0';

      if ((cur_arg->i_r = get_register (operandS)) == nullregister)
       as_bad (_("Illegal register `%s' in Instruction `%s'"),
              operandS, ins_parse);

      /* Skip leading white space.  */
      while (ISSPACE (*operandE))
       operandE++;
      operandS = operandE;

      /* Set the scale.  */
      if (c == ')')
       cur_arg->scale = 0;
      else
        {
         while (*operandE != ')')
           operandE++;
         *operandE = '\0';

         /* Preprocess the scale string.  */
         input_save = input_line_pointer;
         input_line_pointer = operandS;
         expression (&scale);
         input_line_pointer = input_save;

         scale_val = scale.X_add_number;

         /* Check if the scale value is legal.  */
          if (scale_val != 1 && scale_val != 2
              && scale_val != 4 && scale_val != 8)
           as_bad (_("Illegal Scale - `%d'"), scale_val);

         cur_arg->scale = exponent2scale (scale_val);
        }
      break;

    default:
      break;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 306 of file tc-crx.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->addend = fixP->fx_offset;

  if (fixP->fx_subsy != NULL)
    {
      if (SWITCH_TABLE (fixP))
       {
         /* Keep the current difference in the addend.  */
         reloc->addend = (S_GET_VALUE (fixP->fx_addsy)
                        - S_GET_VALUE (fixP->fx_subsy) + fixP->fx_offset);

         switch (fixP->fx_r_type)
           {
           case BFD_RELOC_CRX_NUM8:
             fixP->fx_r_type = BFD_RELOC_CRX_SWITCH8;
             break;
           case BFD_RELOC_CRX_NUM16:
             fixP->fx_r_type = BFD_RELOC_CRX_SWITCH16;
             break;
           case BFD_RELOC_CRX_NUM32:
             fixP->fx_r_type = BFD_RELOC_CRX_SWITCH32;
             break;
           default:
             abort ();
             break;
           }
       }
      else
       {
         /* We only resolve difference expressions in the same section.  */
         as_bad_where (fixP->fx_file, fixP->fx_line,
                     _("can't resolve `%s' {%s section} - `%s' {%s section}"),
                     fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : "0",
                     segment_name (fixP->fx_addsy
                                  ? S_GET_SEGMENT (fixP->fx_addsy)
                                  : absolute_section),
                     S_GET_NAME (fixP->fx_subsy),
                     segment_name (S_GET_SEGMENT (fixP->fx_addsy)));
       }
    }

  assert ((int) fixP->fx_r_type > 0);
  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,
                  _("internal error: reloc %d (`%s') not supported by object file format"),
                  fixP->fx_r_type,
                  bfd_get_reloc_code_name (fixP->fx_r_type));
      return NULL;
    }
  assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);

  return reloc;
}

Here is the call graph for this function:

void warn_if_needed ( ins insn) [static]

Definition at line 1698 of file tc-crx.c.

{
  /* If the post-increment address mode is used and the load/store 
     source register is the same as rbase, the result of the 
     instruction is undefined.  */
  if (IS_INSN_TYPE (LD_STOR_INS_INC))
    {
      /* Enough to verify that one of the arguments is a simple reg.  */
      if ((insn->arg[0].type == arg_r) || (insn->arg[1].type == arg_r))
       if (insn->arg[0].r == insn->arg[1].r)
         as_bad (_("Same src/dest register is used (`r%d'), result is undefined"), 
                 insn->arg[0].r);
    }

  /* Some instruction assume the stack pointer as rptr operand.
     Issue an error when the register to be loaded is also SP.  */
  if (instruction->flags & NO_SP)
    {
      if (getreg_image (insn->arg[0].r) == getreg_image (sp))
       as_bad (_("`%s' has undefined result"), ins_parse);
    }

  /* If the rptr register is specified as one of the registers to be loaded, 
     the final contents of rptr are undefined. Thus, we issue an error.  */
  if (instruction->flags & NO_RPTR)
    {
      if ((1 << getreg_image (insn->arg[0].r)) & insn->arg[1].constant)
       as_bad (_("Same src/dest register is used (`r%d'), result is undefined"), 
        getreg_image (insn->arg[0].r));
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

const char comment_chars[] = "#"

Definition at line 90 of file tc-crx.c.

Definition at line 69 of file tc-crx.c.

Definition at line 65 of file tc-crx.c.

Definition at line 85 of file tc-crx.c.

const char EXP_CHARS[] = "eE"

Definition at line 99 of file tc-crx.c.

const char FLT_CHARS[] = "f'"

Definition at line 102 of file tc-crx.c.

Definition at line 82 of file tc-crx.c.

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

const char line_comment_chars[] = "#"

Definition at line 93 of file tc-crx.c.

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

size_t md_longopts_size = sizeof (md_longopts)

Definition at line 110 of file tc-crx.c.

const pseudo_typeS md_pseudo_table[]
Initial value:
{
  
  {"align", s_align_bytes, 0},
  {0, 0, 0}
}

Definition at line 118 of file tc-crx.c.

const relax_typeS md_relax_table[]
Initial value:
{
  
  {0xfa, -0x100, 2, 1},                   
  {0xfffe, -0x10000, 4, 2},        
  {0xfffffffe, -0xfffffffe, 6, 0}, 

  
  {0xfffe, -0x10000, 4, 4},        
  {0xfffffffe, -0xfffffffe, 6, 0}, 

  
  {0xfe, -0x100, 4, 6},                   
  {0xfffffe, -0x1000000, 6, 0}            
}

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

const char* md_shortopts = ""

Definition at line 105 of file tc-crx.c.

Definition at line 76 of file tc-crx.c.

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

Definition at line 79 of file tc-crx.c.