Back to index

cell-binutils  2.17cvs20070401
Classes | Defines | Enumerations | Functions | Variables
tc-mcore.c File Reference
#include "as.h"
#include "subsegs.h"
#include "../opcodes/mcore-opc.h"
#include "safe-ctype.h"

Go to the source code of this file.

Classes

struct  literal
struct  Cregs

Defines

#define DEFINE_TABLE
#define streq(a, b)   (strcmp (a, b) == 0)
#define INST_BYTE0(x)   (target_big_endian ? (((x) >> 8) & 0xFF) : ((x) & 0xFF))
#define INST_BYTE1(x)   (target_big_endian ? ((x) & 0xFF) : (((x) >> 8) & 0xFF))
#define C(what, length)   (((what) << 2) + (length))
#define GET_WHAT(x)   ((x >> 2))
#define COND_JUMP   1
#define UNCD_JUMP   2
#define UNDEF_DISP   0
#define DISP12   1
#define DISP32   2
#define UNDEF_WORD_DISP   3
#define C12_LEN   2
#define C32_LEN   10 /* Allow for align. */
#define U12_LEN   2
#define U32_LEN   8 /* Allow for align. */
#define MAX_POOL_SIZE   (1024/4)
#define SPANPANIC   (1016) /* 1024 - 1 entry - 2 byte rounding. */
#define SPANCLOSE   (900)
#define SPANEXIT   (600)
#define POOL_END_LABEL   ".LE"
#define POOL_START_LABEL   ".LS"
#define MAX_LITTLENUMS   6
#define F(SZ, PCREL)   (((SZ) << 1) + (PCREL))
#define MAP(SZ, PCREL, TYPE)   case F (SZ, PCREL): code = (TYPE); break

Enumerations

enum  cpu_type { M210, M340 }
enum  options {
  OPTION_EB = OPTION_MD_BASE, OPTION_EL, OPTION_ARC5, OPTION_ARC6,
  OPTION_ARC7, OPTION_ARC8, OPTION_ARC, OPTION_ALL_OPCODES = OPTION_MD_BASE + 1,
  OPTION_NO_SKIP_BUG, OPTION_NO_WRAP, OPTION_NOWARNSWAP = OPTION_MD_BASE, OPTION_GSTABSPACKING,
  OPTION_NOGSTABSPACKING, OPTION_CPU_IP2022 = OPTION_MD_BASE, OPTION_CPU_IP2022EXT, OPTION_JSRI2BSR_ON = OPTION_MD_BASE,
  OPTION_JSRI2BSR_OFF, OPTION_SIFILTER_ON, OPTION_SIFILTER_OFF, OPTION_CPU,
  OPTION_EB, OPTION_EL, OPTION_RELAX = OPTION_MD_BASE, OPTION_BIG,
  OPTION_LITTLE, OPTION_SMALL, OPTION_DSP, OPTION_ISA,
  OPTION_RENESAS, OPTION_ALLOW_REG_PREFIX, OPTION_DUMMY, OPTION_MACH_Z80 = OPTION_MD_BASE,
  OPTION_MACH_R800, OPTION_MACH_IUD, OPTION_MACH_WUD, OPTION_MACH_FUD,
  OPTION_MACH_IUP, OPTION_MACH_WUP, OPTION_MACH_FUP
}

Functions

static void make_name (char *s, char *p, int n)
static void dump_literals (int isforce)
static void mcore_s_literals (int ignore ATTRIBUTE_UNUSED)
static void mcore_pool_count (void(*func)(int), int arg)
static void check_literals (int kind, int offset)
static void mcore_cons (int nbytes)
static void mcore_float_cons (int float_type)
static void mcore_stringer (int append_zero)
static void mcore_fill (int unused)
static void mcore_s_text (int ignore)
static void mcore_s_data (int ignore)
static void mcore_s_section (int ignore)
static void mcore_s_bss (int needs_align)
void md_begin (void)
static int mylog2 (unsigned int val)
static char * parse_reg (char *s, unsigned *reg)
static char * parse_creg (char *s, unsigned *reg)
static char * parse_psrmod (char *s, unsigned *reg)
static char * parse_exp (char *s, expressionS *e)
static int enter_literal (expressionS *e, int ispcrel)
static char * parse_rt (char *s, char **outputp, int ispcrel, expressionS *ep)
static char * parse_imm (char *s, unsigned *val, unsigned min, unsigned max)
static char * parse_mem (char *s, unsigned *reg, unsigned *off, unsigned siz)
void md_assemble (char *str)
symbolS * md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
void md_mcore_end (void)
char * md_atof (int type, char *litP, int *sizeP)
int md_parse_option (int c, char *arg)
void md_show_usage (FILE *stream)
void md_create_short_jump (char *ptr ATTRIBUTE_UNUSED, addressT from_Nddr ATTRIBUTE_UNUSED, addressT to_Nddr ATTRIBUTE_UNUSED, fragS *frag ATTRIBUTE_UNUSED, symbolS *to_symbol ATTRIBUTE_UNUSED)
void md_create_long_jump (char *ptr ATTRIBUTE_UNUSED, addressT from_Nddr ATTRIBUTE_UNUSED, addressT to_Nddr ATTRIBUTE_UNUSED, fragS *frag ATTRIBUTE_UNUSED, symbolS *to_symbol ATTRIBUTE_UNUSED)
void md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS *fragP)
void md_apply_fix (fixS *fixP, valueT *valP, segT segment ATTRIBUTE_UNUSED)
void md_operand (expressionS *expressionP)
int md_estimate_size_before_relax (fragS *fragP, segT segment_type)
void md_number_to_chars (char *ptr, valueT use, int nbytes)
valueT md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
long md_pcrel_from_section (fixS *fixp, segT sec ATTRIBUTE_UNUSED)
arelenttc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)

Variables

const char comment_chars [] = "#/"
const char line_separator_chars [] = ";"
const char line_comment_chars [] = "#/"
static int do_jsri2bsr = 0
static int sifilter_mode = 0
const char EXP_CHARS [] = "eE"
const char FLT_CHARS [] = "rRsSfFdDxXpP"
cpu_type cpu = M340
const relax_typeS md_relax_table []
static struct literal [MAX_POOL_SIZE]
static unsigned poolsize
static unsigned poolnumber
static unsigned long poolspan
static symbolS * poolsym
static char poolname [8]
static struct hash_controlopcode_hash_control
const pseudo_typeS md_pseudo_table []
static struct Cregs cregs []
const char * md_shortopts = ""
size_t md_longopts_size = sizeof (md_longopts)
int md_short_jump_size
int md_long_jump_size

Class Documentation

struct literal

Definition at line 108 of file tc-mcore.c.

Collaboration diagram for literal:
Class Members
expressionS e
unsigned char ispcrel
unsigned short refcnt
unsigned char unused
struct Cregs

Definition at line 525 of file tc-mcore.c.

Class Members
unsigned int crnum
char * name

Define Documentation

#define C (   what,
  length 
)    (((what) << 2) + (length))

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

#define C12_LEN   2

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

#define C32_LEN   10 /* Allow for align. */

Definition at line 72 of file tc-mcore.c.

#define COND_JUMP   1

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

#define DEFINE_TABLE

Definition at line 24 of file tc-mcore.c.

#define DISP12   1

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

#define DISP32   2

Definition at line 68 of file tc-mcore.c.

#define F (   SZ,
  PCREL 
)    (((SZ) << 1) + (PCREL))

Definition at line 2213 of file tc-mcore.c.

#define GET_WHAT (   x)    ((x >> 2))

Definition at line 60 of file tc-mcore.c.

#define INST_BYTE0 (   x)    (target_big_endian ? (((x) >> 8) & 0xFF) : ((x) & 0xFF))

Definition at line 42 of file tc-mcore.c.

#define INST_BYTE1 (   x)    (target_big_endian ? ((x) & 0xFF) : (((x) >> 8) & 0xFF))

Definition at line 43 of file tc-mcore.c.

#define MAP (   SZ,
  PCREL,
  TYPE 
)    case F (SZ, PCREL): code = (TYPE); break

Definition at line 2214 of file tc-mcore.c.

#define MAX_LITTLENUMS   6

Definition at line 1620 of file tc-mcore.c.

#define MAX_POOL_SIZE   (1024/4)

Definition at line 116 of file tc-mcore.c.

#define POOL_END_LABEL   ".LE"

Definition at line 141 of file tc-mcore.c.

#define POOL_START_LABEL   ".LS"

Definition at line 142 of file tc-mcore.c.

#define SPANCLOSE   (900)

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

#define SPANEXIT   (600)

Definition at line 136 of file tc-mcore.c.

#define SPANPANIC   (1016) /* 1024 - 1 entry - 2 byte rounding. */

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

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

Definition at line 33 of file tc-mcore.c.

#define U12_LEN   2

Definition at line 73 of file tc-mcore.c.

#define U32_LEN   8 /* Allow for align. */

Definition at line 74 of file tc-mcore.c.

#define UNCD_JUMP   2

Definition at line 64 of file tc-mcore.c.

#define UNDEF_DISP   0

Definition at line 66 of file tc-mcore.c.

#define UNDEF_WORD_DISP   3

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


Enumeration Type Documentation

enum cpu_type
Enumerator:
M210 
M340 

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

{
  M210,
  M340
}
enum options
Enumerator:
OPTION_EB 
OPTION_EL 
OPTION_ARC5 
OPTION_ARC6 
OPTION_ARC7 
OPTION_ARC8 
OPTION_ARC 
OPTION_ALL_OPCODES 
OPTION_NO_SKIP_BUG 
OPTION_NO_WRAP 
OPTION_NOWARNSWAP 
OPTION_GSTABSPACKING 
OPTION_NOGSTABSPACKING 
OPTION_CPU_IP2022 
OPTION_CPU_IP2022EXT 
OPTION_JSRI2BSR_ON 
OPTION_JSRI2BSR_OFF 
OPTION_SIFILTER_ON 
OPTION_SIFILTER_OFF 
OPTION_CPU 
OPTION_EB 
OPTION_EL 
OPTION_RELAX 
OPTION_BIG 
OPTION_LITTLE 
OPTION_SMALL 
OPTION_DSP 
OPTION_ISA 
OPTION_RENESAS 
OPTION_ALLOW_REG_PREFIX 
OPTION_DUMMY 
OPTION_MACH_Z80 
OPTION_MACH_R800 
OPTION_MACH_IUD 
OPTION_MACH_WUD 
OPTION_MACH_FUD 
OPTION_MACH_IUP 
OPTION_MACH_WUP 
OPTION_MACH_FUP 

Definition at line 1694 of file tc-mcore.c.


Function Documentation

static void check_literals ( int  kind,
int  offset 
) [static]

Definition at line 233 of file tc-mcore.c.

{
  poolspan += offset;

  /* SPANCLOSE and SPANEXIT are smaller numbers than SPANPANIC.
     SPANPANIC means that we must dump now.
     kind == 0 is any old instruction.
     kind  > 0 means we just had a control transfer instruction.
     kind == 1 means within a function
     kind == 2 means we just left a function

     The dump_literals (1) call inserts a branch around the table, so
     we first look to see if its a situation where we won't have to
     insert a branch (e.g., the previous instruction was an unconditional
     branch).

     SPANPANIC is the point where we must dump a single-entry pool.
     it accounts for alignments and an inserted branch.
     the 'poolsize*2' accounts for the scenario where we do:
       lrw r1,lit1; lrw r2,lit2; lrw r3,lit3
     Note that the 'lit2' reference is 2 bytes further along
     but the literal it references will be 4 bytes further along,
     so we must consider the poolsize into this equation.
     This is slightly over-cautious, but guarantees that we won't
     panic because a relocation is too distant.  */

  if (poolspan > SPANCLOSE && kind > 0)
    dump_literals (0);
  else if (poolspan > SPANEXIT && kind > 1)
    dump_literals (0);
  else if (poolspan >= (SPANPANIC - poolsize * 2))
    dump_literals (1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void dump_literals ( int  isforce) [static]

Definition at line 160 of file tc-mcore.c.

{
  unsigned int i;
  struct literal * p;
  symbolS * brarsym = NULL;

  if (poolsize == 0)
    return;

  /* Must we branch around the literal table?  */
  if (isforce)
    {
      char * output;
      char brarname[8];

      make_name (brarname, POOL_END_LABEL, poolnumber);

      brarsym = symbol_make (brarname);

      symbol_table_insert (brarsym);

      output = frag_var (rs_machine_dependent,
                      md_relax_table[C (UNCD_JUMP, DISP32)].rlx_length,
                      md_relax_table[C (UNCD_JUMP, DISP12)].rlx_length,
                      C (UNCD_JUMP, 0), brarsym, 0, 0);
      output[0] = INST_BYTE0 (MCORE_INST_BR);    /* br .+xxx */
      output[1] = INST_BYTE1 (MCORE_INST_BR);
    }

  /* Make sure that the section is sufficiently aligned and that
     the literal table is aligned within it.  */
  record_alignment (now_seg, 2);
  frag_align (2, 0, 0);

  colon (S_GET_NAME (poolsym));

  for (i = 0, p = litpool; i < poolsize; i++, p++)
    emit_expr (& p->e, 4);

  if (brarsym != NULL)
    colon (S_GET_NAME (brarsym));

   poolsize = 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int enter_literal ( expressionS e,
int  ispcrel 
) [static]

Definition at line 671 of file tc-mcore.c.

{
  unsigned int i;
  struct literal * p;

  if (poolsize >= MAX_POOL_SIZE - 2)
    /* The literal pool is as full as we can handle. We have
       to be 2 entries shy of the 1024/4=256 entries because we
       have to allow for the branch (2 bytes) and the alignment
       (2 bytes before the first insn referencing the pool and
       2 bytes before the pool itself) == 6 bytes, rounds up
       to 2 entries.  */
    dump_literals (1);

  if (poolsize == 0)
    {
      /* Create new literal pool.  */
      if (++ poolnumber > 0xFFFF)
       as_fatal (_("more than 65K literal pools"));

      make_name (poolname, POOL_START_LABEL, poolnumber);
      poolsym = symbol_make (poolname);
      symbol_table_insert (poolsym);
      poolspan = 0;
    }

  /* Search pool for value so we don't have duplicates.  */
  for (p = litpool, i = 0; i < poolsize; i++, p++)
    {
      if (e->X_op == p->e.X_op
         && e->X_add_symbol == p->e.X_add_symbol
         && e->X_add_number == p->e.X_add_number
         && ispcrel == p->ispcrel)
       {
         p->refcnt ++;
         return i;
       }
    }

  p->refcnt  = 1;
  p->ispcrel = ispcrel;
  p->e       = * e;

  poolsize ++;

  return i;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void make_name ( char *  s,
char *  p,
int  n 
) [static]

Definition at line 145 of file tc-mcore.c.

{
  static const char hex[] = "0123456789ABCDEF";

  s[0] = p[0];
  s[1] = p[1];
  s[2] = p[2];
  s[3] = hex[(n >> 12) & 0xF];
  s[4] = hex[(n >>  8) & 0xF];
  s[5] = hex[(n >>  4) & 0xF];
  s[6] = hex[(n)       & 0xF];
  s[7] = 0;
}

Here is the caller graph for this function:

static void mcore_cons ( int  nbytes) [static]

Definition at line 268 of file tc-mcore.c.

{
  if (now_seg == text_section)
    mcore_pool_count (cons, nbytes);
  else
    cons (nbytes);

  /* In theory we ought to call check_literals (2,0) here in case
     we need to dump the literal table.  We cannot do this however,
     as the directives that we are intercepting may be being used
     to build a switch table, and we must not interfere with its
     contents.  Instead we cross our fingers and pray...  */
}

Here is the call graph for this function:

static void mcore_fill ( int  unused) [static]

Definition at line 314 of file tc-mcore.c.

Here is the call graph for this function:

static void mcore_float_cons ( int  float_type) [static]

Definition at line 283 of file tc-mcore.c.

{
  if (now_seg == text_section)
    mcore_pool_count (float_cons, float_type);
  else
    float_cons (float_type);

  /* See the comment in mcore_cons () about calling check_literals.
     It is unlikely that a switch table will be constructed using
     floating point values, but it is still likely that an indexed
     table of floating point constants is being created by these
     directives, so again we must not interfere with their placement.  */
}

Here is the call graph for this function:

static void mcore_pool_count ( void(*)(int func,
int  arg 
) [static]

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

{
  const fragS *curr_frag = frag_now;
  offsetT added = -frag_now_fix_octets ();

  (*func) (arg);

  while (curr_frag != frag_now)
    {
      added += curr_frag->fr_fix;
      curr_frag = curr_frag->fr_next;
    }

  added += frag_now_fix_octets ();
  poolspan += added;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void mcore_s_bss ( int  needs_align) [static]

Definition at line 380 of file tc-mcore.c.

{
  dump_literals (0);

  s_lcomm_bytes (needs_align);
}

Here is the call graph for this function:

static void mcore_s_data ( int  ignore) [static]

Definition at line 340 of file tc-mcore.c.

{
  dump_literals (0);

#ifdef OBJ_ELF
  obj_elf_data (ignore);
#else
  s_data (ignore);
#endif
}

Here is the call graph for this function:

static void mcore_s_literals ( int ignore  ATTRIBUTE_UNUSED) [static]

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

Here is the call graph for this function:

static void mcore_s_section ( int  ignore) [static]

Definition at line 352 of file tc-mcore.c.

{
  /* Scan forwards to find the name of the section.  If the section
     being switched to is ".line" then this is a DWARF1 debug section
     which is arbitrarily placed inside generated code.  In this case
     do not dump the literal pool because it is a) inefficient and
     b) would require the generation of extra code to jump around the
     pool.  */
  char * ilp = input_line_pointer;

  while (*ilp != 0 && ISSPACE (*ilp))
    ++ ilp;

  if (strncmp (ilp, ".line", 5) == 0
      && (ISSPACE (ilp[5]) || *ilp == '\n' || *ilp == '\r'))
    ;
  else
    dump_literals (0);

#ifdef OBJ_ELF
  obj_elf_section (ignore);
#endif
#ifdef OBJ_COFF
  obj_coff_section (ignore);
#endif
}

Here is the call graph for this function:

static void mcore_s_text ( int  ignore) [static]

Definition at line 328 of file tc-mcore.c.

{
  dump_literals (0);

#ifdef OBJ_ELF
  obj_elf_text (ignore);
#else
  s_text (ignore);
#endif
}

Here is the call graph for this function:

static void mcore_stringer ( int  append_zero) [static]

Definition at line 298 of file tc-mcore.c.

{
  if (now_seg == text_section)
    mcore_pool_count (stringer, append_zero);
  else
    stringer (append_zero);

  /* We call check_literals here in case a large number of strings are
     being placed into the text section with a sequence of stringer
     directives.  In theory we could be upsetting something if these
     strings are actually in an indexed table instead of referenced by
     individual labels.  Let us hope that that never happens.  */
  check_literals (2, 0);
}

Here is the call graph for this function:

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

Definition at line 1982 of file tc-mcore.c.

{
  char *       buf  = fixP->fx_where + fixP->fx_frag->fr_literal;
  char *       file = fixP->fx_file ? fixP->fx_file : _("unknown");
  const char * symname;
  /* Note: use offsetT because it is signed, valueT is unsigned.  */
  offsetT      val  = *valP;

  symname = fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : _("<unknown>");
  /* Save this for the addend in the relocation record.  */
  fixP->fx_addnumber = val;

  if (fixP->fx_addsy != NULL)
    {
#ifdef OBJ_ELF
      /* For ELF we can just return and let the reloc that will be generated
        take care of everything.  For COFF we still have to insert 'val'
        into the insn since the addend field will be ignored.  */
      return;
#endif
    }
  else
    fixP->fx_done = 1;

  switch (fixP->fx_r_type)
    {
      /* Second byte of 2 byte opcode.  */
    case BFD_RELOC_MCORE_PCREL_IMM11BY2:
      if ((val & 1) != 0)
       as_bad_where (file, fixP->fx_line,
                    _("odd distance branch (0x%lx bytes)"), (long) val);
      val /= 2;
      if (((val & ~0x3ff) != 0) && ((val | 0x3ff) != -1))
       as_bad_where (file, fixP->fx_line,
                    _("pcrel for branch to %s too far (0x%lx)"),
                    symname, (long) val);
      if (target_big_endian)
       {
         buf[0] |= ((val >> 8) & 0x7);
         buf[1] |= (val & 0xff);
       }
      else
       {
         buf[1] |= ((val >> 8) & 0x7);
         buf[0] |= (val & 0xff);
       }
      break;

      /* Lower 8 bits of 2 byte opcode.  */
    case BFD_RELOC_MCORE_PCREL_IMM8BY4:
      val += 3;
      val /= 4;
      if (val & ~0xff)
       as_bad_where (file, fixP->fx_line,
                    _("pcrel for lrw/jmpi/jsri to %s too far (0x%lx)"),
                    symname, (long) val);
      else if (! target_big_endian)
       buf[0] |= (val & 0xff);
      else
       buf[1] |= (val & 0xff);
      break;

      /* Loopt instruction.  */
    case BFD_RELOC_MCORE_PCREL_IMM4BY2:
      if ((val < -32) || (val > -2))
       as_bad_where (file, fixP->fx_line,
                    _("pcrel for loopt too far (0x%lx)"), (long) val);
      val /= 2;
      if (! target_big_endian)
       buf[0] |= (val & 0xf);
      else
       buf[1] |= (val & 0xf);
      break;

    case BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2:
      /* Conditional linker map jsri to bsr.  */
      /* If its a local target and close enough, fix it.
        NB: >= -2k for backwards bsr; < 2k for forwards...  */
      if (fixP->fx_addsy == 0 && val >= -2048  && val < 2048)
       {
         long nval = (val / 2) & 0x7ff;
         nval |= MCORE_INST_BSR;

         /* REPLACE the instruction, don't just modify it.  */
         buf[0] = INST_BYTE0 (nval);
         buf[1] = INST_BYTE1 (nval);
       }
      else
       fixP->fx_done = 0;
      break;

    case BFD_RELOC_MCORE_PCREL_32:
    case BFD_RELOC_VTABLE_INHERIT:
    case BFD_RELOC_VTABLE_ENTRY:
      fixP->fx_done = 0;
      break;

    default:
      if (fixP->fx_addsy != NULL)
       {
         /* If the fix is an absolute reloc based on a symbol's
            address, then it cannot be resolved until the final link.  */
         fixP->fx_done = 0;
       }
#ifdef OBJ_ELF
      else
#endif
       {
         if (fixP->fx_size == 4)
           ;
         else if (fixP->fx_size == 2 && val >= -32768 && val <= 32767)
           ;
         else if (fixP->fx_size == 1 && val >= -256 && val <= 255)
           ;
         else
           abort ();
         md_number_to_chars (buf, val, fixP->fx_size);
       }
      break;
    }
}

Here is the call graph for this function:

void md_assemble ( char *  str)

Definition at line 850 of file tc-mcore.c.

{
  char * op_start;
  char * op_end;
  mcore_opcode_info * opcode;
  char * output;
  int nlen = 0;
  unsigned short inst;
  unsigned reg;
  unsigned off;
  unsigned isize;
  expressionS e;
  char name[20];

  /* Drop leading whitespace.  */
  while (ISSPACE (* str))
    str ++;

  /* Find the op code end.  */
  for (op_start = op_end = str;
       nlen < 20 && !is_end_of_line [(unsigned char) *op_end] && *op_end != ' ';
       op_end++)
    {
      name[nlen] = op_start[nlen];
      nlen++;
    }

  name [nlen] = 0;

  if (nlen == 0)
    {
      as_bad (_("can't find opcode "));
      return;
    }

  opcode = (mcore_opcode_info *) hash_find (opcode_hash_control, name);
  if (opcode == NULL)
    {
      as_bad (_("unknown opcode \"%s\""), name);
      return;
    }

  inst = opcode->inst;
  isize = 2;

  switch (opcode->opclass)
    {
    case O0:
      output = frag_more (2);
      break;

    case OT:
      op_end = parse_imm (op_end + 1, & reg, 0, 3);
      inst |= reg;
      output = frag_more (2);
      break;

    case O1:
      op_end = parse_reg (op_end + 1, & reg);
      inst |= reg;
      output = frag_more (2);
      break;

    case JMP:
      op_end = parse_reg (op_end + 1, & reg);
      inst |= reg;
      output = frag_more (2);
      /* In a sifilter mode, we emit this insn 2 times,
        fixes problem of an interrupt during a jmp..  */
      if (sifilter_mode)
       {
         output[0] = INST_BYTE0 (inst);
         output[1] = INST_BYTE1 (inst);
         output = frag_more (2);
       }
      break;

    case JSR:
      op_end = parse_reg (op_end + 1, & reg);

      if (reg == 15)
       as_bad (_("invalid register: r15 illegal"));

      inst |= reg;
      output = frag_more (2);

      if (sifilter_mode)
       {
         /* Replace with:  bsr .+2 ; addi r15,6; jmp rx ; jmp rx.  */
         inst = MCORE_INST_BSR;    /* With 0 displacement.  */
         output[0] = INST_BYTE0 (inst);
         output[1] = INST_BYTE1 (inst);

         output = frag_more (2);
         inst = MCORE_INST_ADDI;
         inst |= 15;               /* addi r15,6  */
         inst |= (6 - 1) << 4;            /* Over the jmp's.  */
         output[0] = INST_BYTE0 (inst);
         output[1] = INST_BYTE1 (inst);

         output = frag_more (2);
         inst = MCORE_INST_JMP | reg;
         output[0] = INST_BYTE0 (inst);
         output[1] = INST_BYTE1 (inst);

         /* 2nd emitted in fallthrough.  */
         output = frag_more (2);
       }
      break;

    case OC:
      op_end = parse_reg (op_end + 1, & reg);
      inst |= reg;

      /* Skip whitespace.  */
      while (ISSPACE (* op_end))
       ++ op_end;

      if (*op_end == ',')
       {
         op_end = parse_creg (op_end + 1, & reg);
         inst |= reg << 4;
       }

      output = frag_more (2);
      break;

    case MULSH:
      if (cpu == M210)
       {
         as_bad (_("M340 specific opcode used when assembling for M210"));
         break;
       }
      /* drop through...  */
    case O2:
      op_end = parse_reg (op_end + 1, & reg);
      inst |= reg;

      /* Skip whitespace.  */
      while (ISSPACE (* op_end))
       ++ op_end;

      if (* op_end == ',')
       {
         op_end = parse_reg (op_end + 1, & reg);
         inst |= reg << 4;
       }
      else
       as_bad (_("second operand missing"));

      output = frag_more (2);
      break;

    case X1:
      /* Handle both syntax-> xtrb- r1,rx OR xtrb- rx.  */
      op_end = parse_reg (op_end + 1, & reg);

      /* Skip whitespace.  */
      while (ISSPACE (* op_end))
       ++ op_end;

      if (* op_end == ',')  /* xtrb- r1,rx.  */
       {
         if (reg != 1)
           as_bad (_("destination register must be r1"));

         op_end = parse_reg (op_end + 1, & reg);
       }

      inst |= reg;
      output = frag_more (2);
      break;

    case O1R1:  /* div- rx,r1.  */
      op_end = parse_reg (op_end + 1, & reg);
      inst |= reg;

      /* Skip whitespace.  */
      while (ISSPACE (* op_end))
       ++ op_end;

      if (* op_end == ',')
       {
         op_end = parse_reg (op_end + 1, & reg);
         if (reg != 1)
           as_bad (_("source register must be r1"));
       }
      else
       as_bad (_("second operand missing"));

      output = frag_more (2);
      break;

    case OI:
      op_end = parse_reg (op_end + 1, & reg);
      inst |= reg;

      /* Skip whitespace.  */
      while (ISSPACE (* op_end))
       ++ op_end;

      if (* op_end == ',')
       {
         op_end = parse_imm (op_end + 1, & reg, 1, 32);
         inst |= (reg - 1) << 4;
       }
      else
       as_bad (_("second operand missing"));

      output = frag_more (2);
      break;

    case OB:
      op_end = parse_reg (op_end + 1, & reg);
      inst |= reg;

      /* Skip whitespace.  */
      while (ISSPACE (* op_end))
       ++ op_end;

      if (* op_end == ',')
       {
         op_end = parse_imm (op_end + 1, & reg, 0, 31);
         inst |= reg << 4;
       }
      else
       as_bad (_("second operand missing"));

      output = frag_more (2);
      break;

    case OB2:
      /* Like OB, but arg is 2^n instead of n.  */
      op_end = parse_reg (op_end + 1, & reg);
      inst |= reg;

      /* Skip whitespace.  */
      while (ISSPACE (* op_end))
       ++ op_end;

      if (* op_end == ',')
       {
         op_end = parse_imm (op_end + 1, & reg, 1, 1 << 31);
         /* Further restrict the immediate to a power of two.  */
         if ((reg & (reg - 1)) == 0)
           reg = mylog2 (reg);
         else
           {
             reg = 0;
             as_bad (_("immediate is not a power of two"));
           }
         inst |= (reg) << 4;
       }
      else
       as_bad (_("second operand missing"));

      output = frag_more (2);
      break;

    case OBRa:       /* Specific for bgeni: imm of 0->6 translate to movi.  */
    case OBRb:
    case OBRc:
      op_end = parse_reg (op_end + 1, & reg);
      inst |= reg;

      /* Skip whitespace.  */
      while (ISSPACE (* op_end))
       ++ op_end;

      if (* op_end == ',')
       {
         op_end = parse_imm (op_end + 1, & reg, 0, 31);
         /* Immediate values of 0 -> 6 translate to movi.  */
         if (reg <= 6)
           {
             inst = (inst & 0xF) | MCORE_INST_BGENI_ALT;
             reg = 0x1 << reg;
             as_warn (_("translating bgeni to movi"));
           }
         inst &= ~ 0x01f0;
         inst |= reg << 4;
       }
      else
       as_bad (_("second operand missing"));

      output = frag_more (2);
      break;

    case OBR2:       /* Like OBR, but arg is 2^n instead of n.  */
      op_end = parse_reg (op_end + 1, & reg);
      inst |= reg;

      /* Skip whitespace.  */
      while (ISSPACE (* op_end))
       ++ op_end;

      if (* op_end == ',')
       {
         op_end = parse_imm (op_end + 1, & reg, 1, 1 << 31);

         /* Further restrict the immediate to a power of two.  */
         if ((reg & (reg - 1)) == 0)
           reg = mylog2 (reg);
         else
           {
             reg = 0;
             as_bad (_("immediate is not a power of two"));
           }

         /* Immediate values of 0 -> 6 translate to movi.  */
         if (reg <= 6)
           {
             inst = (inst & 0xF) | MCORE_INST_BGENI_ALT;
             reg = 0x1 << reg;
             as_warn (_("translating mgeni to movi"));
           }

         inst |= reg << 4;
       }
      else
       as_bad (_("second operand missing"));

      output = frag_more (2);
      break;

    case OMa: /* Specific for bmaski: imm 1->7 translate to movi.  */
    case OMb:
    case OMc:
      op_end = parse_reg (op_end + 1, & reg);
      inst |= reg;

      /* Skip whitespace.  */
      while (ISSPACE (* op_end))
       ++ op_end;

      if (* op_end == ',')
       {
         op_end = parse_imm (op_end + 1, & reg, 1, 32);

         /* Immediate values of 1 -> 7 translate to movi.  */
         if (reg <= 7)
           {
             inst = (inst & 0xF) | MCORE_INST_BMASKI_ALT;
             reg = (0x1 << reg) - 1;
             inst |= reg << 4;

             as_warn (_("translating bmaski to movi"));
           }
         else
           {
             inst &= ~ 0x01F0;
             inst |= (reg & 0x1F) << 4;
           }
       }
      else
       as_bad (_("second operand missing"));

      output = frag_more (2);
      break;

    case SI:
      op_end = parse_reg (op_end + 1, & reg);
      inst |= reg;

      /* Skip whitespace.  */
      while (ISSPACE (* op_end))
       ++ op_end;

      if (* op_end == ',')
       {
         op_end = parse_imm (op_end + 1, & reg, 1, 31);
         inst |= reg << 4;
       }
      else
       as_bad (_("second operand missing"));

      output = frag_more (2);
      break;

    case I7:
      op_end = parse_reg (op_end + 1, & reg);
      inst |= reg;

      /* Skip whitespace.  */
      while (ISSPACE (* op_end))
       ++ op_end;

      if (* op_end == ',')
       {
         op_end = parse_imm (op_end + 1, & reg, 0, 0x7F);
         inst |= reg << 4;
       }
      else
       as_bad (_("second operand missing"));

      output = frag_more (2);
      break;

    case LS:
      op_end = parse_reg (op_end + 1, & reg);
      inst |= reg << 8;

      /* Skip whitespace.  */
      while (ISSPACE (* op_end))
       ++ op_end;

      if (* op_end == ',')
       {
         int size;

         if ((inst & 0x6000) == 0)
           size = 4;
         else if ((inst & 0x6000) == 0x4000)
           size = 2;
         else if ((inst & 0x6000) == 0x2000)
           size = 1;
         else
           abort ();

         op_end = parse_mem (op_end + 1, & reg, & off, size);

         if (off > 16)
           as_bad (_("displacement too large (%d)"), off);
         else
           inst |= (reg) | (off << 4);
       }
      else
       as_bad (_("second operand missing"));

      output = frag_more (2);
      break;

    case LR:
      op_end = parse_reg (op_end + 1, & reg);

      if (reg == 0 || reg == 15)
       as_bad (_("Invalid register: r0 and r15 illegal"));

      inst |= (reg << 8);

      /* Skip whitespace.  */
      while (ISSPACE (* op_end))
       ++ op_end;

      if (* op_end == ',')
       {
         /* parse_rt calls frag_more() for us.  */
         input_line_pointer = parse_rt (op_end + 1, & output, 0, 0);
         op_end = input_line_pointer;
       }
      else
       {
         as_bad (_("second operand missing"));
         output = frag_more (2);          /* save its space */
       }
      break;

    case LJ:
      input_line_pointer = parse_rt (op_end + 1, & output, 1, 0);
      /* parse_rt() calls frag_more() for us.  */
      op_end = input_line_pointer;
      break;

    case RM:
      op_end = parse_reg (op_end + 1, & reg);

      if (reg == 0 || reg == 15)
       as_bad (_("bad starting register: r0 and r15 invalid"));

      inst |= reg;

      /* Skip whitespace.  */
      while (ISSPACE (* op_end))
       ++ op_end;

      if (* op_end == '-')
       {
         op_end = parse_reg (op_end + 1, & reg);

         if (reg != 15)
           as_bad (_("ending register must be r15"));

         /* Skip whitespace.  */
         while (ISSPACE (* op_end))
           ++ op_end;
       }

      if (* op_end == ',')
       {
         op_end ++;

         /* Skip whitespace.  */
         while (ISSPACE (* op_end))
           ++ op_end;

         if (* op_end == '(')
           {
             op_end = parse_reg (op_end + 1, & reg);

             if (reg != 0)
              as_bad (_("bad base register: must be r0"));

             if (* op_end == ')')
              op_end ++;
           }
         else
           as_bad (_("base register expected"));
       }
      else
       as_bad (_("second operand missing"));

      output = frag_more (2);
      break;

    case RQ:
      op_end = parse_reg (op_end + 1, & reg);

      if (reg != 4)
       as_fatal (_("first register must be r4"));

      /* Skip whitespace.  */
      while (ISSPACE (* op_end))
       ++ op_end;

      if (* op_end == '-')
       {
         op_end = parse_reg (op_end + 1, & reg);

         if (reg != 7)
           as_fatal (_("last register must be r7"));

         /* Skip whitespace.  */
         while (ISSPACE (* op_end))
           ++ op_end;

         if (* op_end == ',')
           {
             op_end ++;

             /* Skip whitespace.  */
             while (ISSPACE (* op_end))
              ++ op_end;

             if (* op_end == '(')
              {
                op_end = parse_reg (op_end + 1, & reg);

                if (reg >= 4 && reg <= 7)
                  as_fatal ("base register cannot be r4, r5, r6, or r7");

                inst |= reg;

                /* Skip whitespace.  */
                while (ISSPACE (* op_end))
                  ++ op_end;

                if (* op_end == ')')
                  op_end ++;
              }
             else
              as_bad (_("base register expected"));
           }
         else
           as_bad (_("second operand missing"));
       }
      else
       as_bad (_("reg-reg expected"));

      output = frag_more (2);
      break;

    case BR:
      input_line_pointer = parse_exp (op_end + 1, & e);
      op_end = input_line_pointer;

      output = frag_more (2);

      fix_new_exp (frag_now, output-frag_now->fr_literal,
                 2, & e, 1, BFD_RELOC_MCORE_PCREL_IMM11BY2);
      break;

    case BL:
      op_end = parse_reg (op_end + 1, & reg);
      inst |= reg << 4;

      /* Skip whitespace.  */
      while (ISSPACE (* op_end))
       ++ op_end;

      if (* op_end == ',')
       {
         op_end = parse_exp (op_end + 1, & e);
         output = frag_more (2);

         fix_new_exp (frag_now, output-frag_now->fr_literal,
                     2, & e, 1, BFD_RELOC_MCORE_PCREL_IMM4BY2);
       }
      else
       {
         as_bad (_("second operand missing"));
         output = frag_more (2);
       }
      break;

    case JC:
      input_line_pointer = parse_exp (op_end + 1, & e);
      op_end = input_line_pointer;

      output = frag_var (rs_machine_dependent,
                      md_relax_table[C (COND_JUMP, DISP32)].rlx_length,
                      md_relax_table[C (COND_JUMP, DISP12)].rlx_length,
                      C (COND_JUMP, 0), e.X_add_symbol, e.X_add_number, 0);
      isize = C32_LEN;
      break;

    case JU:
      input_line_pointer = parse_exp (op_end + 1, & e);
      op_end = input_line_pointer;

      output = frag_var (rs_machine_dependent,
                      md_relax_table[C (UNCD_JUMP, DISP32)].rlx_length,
                      md_relax_table[C (UNCD_JUMP, DISP12)].rlx_length,
                      C (UNCD_JUMP, 0), e.X_add_symbol, e.X_add_number, 0);
      isize = U32_LEN;
      break;

    case JL:
      inst = MCORE_INST_JSRI;             /* jsri */
      input_line_pointer = parse_rt (op_end + 1, & output, 1, & e);
      /* parse_rt() calls frag_more for us.  */
      op_end = input_line_pointer;

      /* Only do this if we know how to do it ...  */
      if (e.X_op != O_absent && do_jsri2bsr)
       {
         /* Look at adding the R_PCREL_JSRIMM11BY2.  */
         fix_new_exp (frag_now, output-frag_now->fr_literal,
                     2, & e, 1, BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2);
       }
      break;

    case RSI:
      /* SI, but imm becomes 32-imm.  */
      op_end = parse_reg (op_end + 1, & reg);
      inst |= reg;

      /* Skip whitespace.  */
      while (ISSPACE (* op_end))
       ++ op_end;

      if (* op_end == ',')
       {
         op_end = parse_imm (op_end + 1, & reg, 1, 31);

         reg = 32 - reg;
         inst |= reg << 4;
       }
      else
       as_bad (_("second operand missing"));

      output = frag_more (2);
      break;

    case DO21:                     /* O2, dup rd, lit must be 1 */
      op_end = parse_reg (op_end + 1, & reg);
      inst |= reg;
      inst |= reg << 4;

      /* Skip whitespace.  */
      while (ISSPACE (* op_end))
       ++ op_end;

      if (* op_end == ',')
       {
         op_end = parse_imm (op_end + 1, & reg, 1, 31);

         if (reg != 1)
           as_bad (_("second operand must be 1"));
       }
      else
       as_bad (_("second operand missing"));

      output = frag_more (2);
      break;

    case SIa:
      op_end = parse_reg (op_end + 1, & reg);
      inst |= reg;

      /* Skip whitespace.  */
      while (ISSPACE (* op_end))
       ++ op_end;

      if (* op_end == ',')
       {
         op_end = parse_imm (op_end + 1, & reg, 1, 31);

         if (reg == 0)
           as_bad (_("zero used as immediate value"));

         inst |= reg << 4;
       }
      else
       as_bad (_("second operand missing"));

      output = frag_more (2);
      break;

    case OPSR:
      if (cpu == M210)
       {
         as_bad (_("M340 specific opcode used when assembling for M210"));
         break;
       }

      op_end = parse_psrmod (op_end + 1, & reg);

      /* Look for further selectors.  */
      while (* op_end == ',')
       {
         unsigned value;

         op_end = parse_psrmod (op_end + 1, & value);

         if (value & reg)
           as_bad (_("duplicated psr bit specifier"));

         reg |= value;
       }

      if (reg > 8)
       as_bad (_("`af' must appear alone"));

      inst |= (reg & 0x7);
      output = frag_more (2);
      break;

    default:
      as_bad (_("unimplemented opcode \"%s\""), name);
    }

  /* Drop whitespace after all the operands have been parsed.  */
  while (ISSPACE (* op_end))
    op_end ++;

  /* Give warning message if the insn has more operands than required.  */
  if (strcmp (op_end, opcode->name) && strcmp (op_end, ""))
    as_warn (_("ignoring operands: %s "), op_end);

  output[0] = INST_BYTE0 (inst);
  output[1] = INST_BYTE1 (inst);

  check_literals (opcode->transfer, isize);
}

Here is the call graph for this function:

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

Definition at line 1627 of file tc-mcore.c.

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

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

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

    case 'x':
    case 'X':
      prec = 6;
      break;

    case 'p':
    case 'P':
      prec = 6;
      break;

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

  t = atof_ieee (input_line_pointer, type, words);

  if (t)
    input_line_pointer = t;

  *sizeP = prec * sizeof (LITTLENUM_TYPE);

  if (! target_big_endian)
    {
      for (i = prec - 1; i >= 0; i--)
       {
         md_number_to_chars (litP, (valueT) words[i],
                           sizeof (LITTLENUM_TYPE));
         litP += sizeof (LITTLENUM_TYPE);
       }
    }
  else
    for (i = 0; i < prec; i++)
      {
       md_number_to_chars (litP, (valueT) words[i],
                         sizeof (LITTLENUM_TYPE));
       litP += sizeof (LITTLENUM_TYPE);
      }

  return 0;
}

Here is the call graph for this function:

void md_begin ( void  )

Definition at line 456 of file tc-mcore.c.

{
  const mcore_opcode_info * opcode;
  char * prev_name = "";

  opcode_hash_control = hash_new ();

  /* Insert unique names into hash table.  */
  for (opcode = mcore_table; opcode->name; opcode ++)
    {
      if (! streq (prev_name, opcode->name))
       {
         prev_name = opcode->name;
         hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
       }
    }
}

Here is the call graph for this function:

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

Definition at line 1785 of file tc-mcore.c.

{
  char *buffer;
  int targ_addr = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset;

  buffer = fragP->fr_fix + fragP->fr_literal;

  switch (fragP->fr_subtype)
    {
    case C (COND_JUMP, DISP12):
    case C (UNCD_JUMP, DISP12):
      {
       /* Get the address of the end of the instruction.  */
       int next_inst = fragP->fr_fix + fragP->fr_address + 2;
       unsigned char t0;
       int disp = targ_addr - next_inst;

       if (disp & 1)
         as_bad (_("odd displacement at %x"), next_inst - 2);

       disp >>= 1;

       if (! target_big_endian)
         {
           t0 = buffer[1] & 0xF8;

           md_number_to_chars (buffer, disp, 2);

           buffer[1] = (buffer[1] & 0x07) | t0;
         }
       else
         {
           t0 = buffer[0] & 0xF8;

           md_number_to_chars (buffer, disp, 2);

           buffer[0] = (buffer[0] & 0x07) | t0;
         }

       fragP->fr_fix += 2;
      }
      break;

    case C (COND_JUMP, DISP32):
    case C (COND_JUMP, UNDEF_WORD_DISP):
      {
       /* A conditional branch wont fit into 12 bits so:
              b!cond 1f
              jmpi   0f
              .align 2
          0:  .long disp
          1:
         
          If the b!cond is 4 byte aligned, the literal which would
          go at x+4 will also be aligned.  */
       int first_inst = fragP->fr_fix + fragP->fr_address;
       int needpad = (first_inst & 3);

       if (! target_big_endian)
         buffer[1] ^= 0x08;
       else
         buffer[0] ^= 0x08; /* Toggle T/F bit.  */

       buffer[2] = INST_BYTE0 (MCORE_INST_JMPI); /* Build jmpi.  */
       buffer[3] = INST_BYTE1 (MCORE_INST_JMPI);

       if (needpad)
         {
           if (! target_big_endian)
             {
              buffer[0] = 4;       /* Branch over jmpi, pad, and ptr.  */
              buffer[2] = 1;       /* Jmpi offset of 1 gets the pointer.  */
             }
           else
             {
              buffer[1] = 4;       /* Branch over jmpi, pad, and ptr.  */
              buffer[3] = 1;       /* Jmpi offset of 1 gets the pointer.  */
             }

           buffer[4] = 0;   /* Alignment/pad.  */
           buffer[5] = 0;
           buffer[6] = 0;   /* Space for 32 bit address.  */
           buffer[7] = 0;
           buffer[8] = 0;
           buffer[9] = 0;

           /* Make reloc for the long disp.  */
           fix_new (fragP, fragP->fr_fix + 6, 4,
                   fragP->fr_symbol, fragP->fr_offset, 0, BFD_RELOC_32);

           fragP->fr_fix += C32_LEN;
         }
       else
         {
           /* See comment below about this given gas' limitations for
              shrinking the fragment. '3' is the amount of code that
              we inserted here, but '4' is right for the space we reserved
              for this fragment.  */
           if (! target_big_endian)
             {
              buffer[0] = 3;       /* Branch over jmpi, and ptr.  */
              buffer[2] = 0;       /* Jmpi offset of 0 gets the pointer.  */
             }
           else
             {
              buffer[1] = 3;       /* Branch over jmpi, and ptr.  */
              buffer[3] = 0;       /* Jmpi offset of 0 gets the pointer.  */
             }

           buffer[4] = 0;   /* Space for 32 bit address.  */
           buffer[5] = 0;
           buffer[6] = 0;
           buffer[7] = 0;

           /* Make reloc for the long disp.  */
           fix_new (fragP, fragP->fr_fix + 4, 4,
                   fragP->fr_symbol, fragP->fr_offset, 0, BFD_RELOC_32);
           fragP->fr_fix += C32_LEN;

           /* Frag is actually shorter (see the other side of this ifdef)
              but gas isn't prepared for that.  We have to re-adjust
              the branch displacement so that it goes beyond the
              full length of the fragment, not just what we actually
              filled in.  */
           if (! target_big_endian)
             buffer[0] = 4; /* Jmpi, ptr, and the 'tail pad'.  */
           else
             buffer[1] = 4; /* Jmpi, ptr, and the 'tail pad'.  */
         }
      }
      break;

    case C (UNCD_JUMP, DISP32):
    case C (UNCD_JUMP, UNDEF_WORD_DISP):
      {
       /* An unconditional branch will not fit in 12 bits, make code which
          looks like:
              jmpi   0f
              .align 2
            0:       .long disp
          we need a pad if "first_inst" is 4 byte aligned.
          [because the natural literal place is x + 2].  */
       int first_inst = fragP->fr_fix + fragP->fr_address;
       int needpad = !(first_inst & 3);

       buffer[0] = INST_BYTE0 (MCORE_INST_JMPI); /* Build jmpi.  */
       buffer[1] = INST_BYTE1 (MCORE_INST_JMPI);

       if (needpad)
         {
           if (! target_big_endian)
             buffer[0] = 1; /* Jmpi offset of 1 since padded.  */
           else
             buffer[1] = 1; /* Jmpi offset of 1 since padded.  */
           buffer[2] = 0;   /* Alignment.  */
           buffer[3] = 0;
           buffer[4] = 0;   /* Space for 32 bit address.  */
           buffer[5] = 0;
           buffer[6] = 0;
           buffer[7] = 0;

           /* Make reloc for the long disp.  */
           fix_new (fragP, fragP->fr_fix + 4, 4,
                   fragP->fr_symbol, fragP->fr_offset, 0, BFD_RELOC_32);

           fragP->fr_fix += U32_LEN;
         }
       else
         {
           if (! target_big_endian)
             buffer[0] = 0; /* Jmpi offset of 0 if no pad.  */
           else
             buffer[1] = 0; /* Jmpi offset of 0 if no pad.  */
           buffer[2] = 0;   /* Space for 32 bit address.  */
           buffer[3] = 0;
           buffer[4] = 0;
           buffer[5] = 0;

           /* Make reloc for the long disp.  */
           fix_new (fragP, fragP->fr_fix + 2, 4,
                   fragP->fr_symbol, fragP->fr_offset, 0, BFD_RELOC_32);
           fragP->fr_fix += U32_LEN;
         }
      }
      break;

    default:
      abort ();
    }
}

Here is the call graph for this function:

void md_create_long_jump ( char *ptr  ATTRIBUTE_UNUSED,
addressT from_Nddr  ATTRIBUTE_UNUSED,
addressT to_Nddr  ATTRIBUTE_UNUSED,
fragS *frag  ATTRIBUTE_UNUSED,
symbolS *to_symbol  ATTRIBUTE_UNUSED 
)

Definition at line 1773 of file tc-mcore.c.

{
  as_fatal (_("failed sanity check: long_jump"));
}

Here is the call graph for this function:

void md_create_short_jump ( char *ptr  ATTRIBUTE_UNUSED,
addressT from_Nddr  ATTRIBUTE_UNUSED,
addressT to_Nddr  ATTRIBUTE_UNUSED,
fragS *frag  ATTRIBUTE_UNUSED,
symbolS *to_symbol  ATTRIBUTE_UNUSED 
)

Definition at line 1763 of file tc-mcore.c.

{
  as_fatal (_("failed sanity check: short_jump"));
}

Here is the call graph for this function:

int md_estimate_size_before_relax ( fragS *  fragP,
segT  segment_type 
)

Definition at line 2122 of file tc-mcore.c.

{
  switch (fragP->fr_subtype)
    {
    default:
      abort ();

    case C (UNCD_JUMP, UNDEF_DISP):
      /* Used to be a branch to somewhere which was unknown.  */
      if (!fragP->fr_symbol)
       fragP->fr_subtype = C (UNCD_JUMP, DISP12);
      else if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type)
       fragP->fr_subtype = C (UNCD_JUMP, DISP12);
      else
       fragP->fr_subtype = C (UNCD_JUMP, UNDEF_WORD_DISP);
      break;

    case C (COND_JUMP, UNDEF_DISP):
      /* Used to be a branch to somewhere which was unknown.  */
      if (fragP->fr_symbol
         && S_GET_SEGMENT (fragP->fr_symbol) == segment_type)
       /* Got a symbol and it's defined in this segment, become byte
          sized - maybe it will fix up */
       fragP->fr_subtype = C (COND_JUMP, DISP12);
      else if (fragP->fr_symbol)
       /* Its got a segment, but its not ours, so it will always be long.  */
       fragP->fr_subtype = C (COND_JUMP, UNDEF_WORD_DISP);
      else
       /* We know the abs value.  */
       fragP->fr_subtype = C (COND_JUMP, DISP12);
      break;

    case C (UNCD_JUMP, DISP12):
    case C (UNCD_JUMP, DISP32):
    case C (UNCD_JUMP, UNDEF_WORD_DISP):
    case C (COND_JUMP, DISP12):
    case C (COND_JUMP, DISP32):
    case C (COND_JUMP, UNDEF_WORD_DISP):
      /* When relaxing a section for the second time, we don't need to
        do anything besides return the current size.  */
      break;
    }

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

Here is the call graph for this function:

void md_mcore_end ( void  )

Definition at line 1612 of file tc-mcore.c.

Here is the call graph for this function:

void md_number_to_chars ( char *  ptr,
valueT  use,
int  nbytes 
)

Definition at line 2171 of file tc-mcore.c.

{
  if (target_big_endian)
    number_to_chars_bigendian (ptr, use, nbytes);
  else
    number_to_chars_littleendian (ptr, use, nbytes);
}

Here is the call graph for this function:

void md_operand ( expressionS expressionP)

Definition at line 2107 of file tc-mcore.c.

{
  /* Ignore leading hash symbol, if poresent.  */
  if (* input_line_pointer == '#')
    {
      input_line_pointer ++;
      expression (expressionP);
    }
}
int md_parse_option ( int c  ,
char *  arg 
)

Definition at line 1720 of file tc-mcore.c.

{
  switch (c)
    {
    case OPTION_CPU:
      if (streq (arg, "210"))
       {
         cpu = M210;
         target_big_endian = 1;
       }
      else if (streq (arg, "340"))
       cpu = M340;
      else
       as_warn (_("unrecognised cpu type '%s'"), arg);
      break;

    case OPTION_EB: target_big_endian = 1; break;
    case OPTION_EL: target_big_endian = 0; cpu = M340; break;
    case OPTION_JSRI2BSR_ON:  do_jsri2bsr = 1;   break;
    case OPTION_JSRI2BSR_OFF: do_jsri2bsr = 0;   break;
    case OPTION_SIFILTER_ON:  sifilter_mode = 1; break;
    case OPTION_SIFILTER_OFF: sifilter_mode = 0; break;
    default:                  return 0;
    }

  return 1;
}

Here is the call graph for this function:

long md_pcrel_from_section ( fixS *  fixp,
segT sec  ATTRIBUTE_UNUSED 
)

Definition at line 2193 of file tc-mcore.c.

{
#ifdef OBJ_ELF
  /* If the symbol is undefined or defined in another section
     we leave the add number alone for the linker to fix it later.
     Only account for the PC pre-bump (which is 2 bytes on the MCore).  */
  if (fixp->fx_addsy != (symbolS *) NULL
      && (! S_IS_DEFINED (fixp->fx_addsy)
         || (S_GET_SEGMENT (fixp->fx_addsy) != sec)))

  {
    assert (fixp->fx_size == 2);   /* must be an insn */
    return fixp->fx_size;
  }
#endif

  /* The case where we are going to resolve things...  */
  return  fixp->fx_size + fixp->fx_where + fixp->fx_frag->fr_address;
}

Here is the call graph for this function:

valueT md_section_align ( segT segment  ATTRIBUTE_UNUSED,
valueT size   
)

Definition at line 2182 of file tc-mcore.c.

{
  /* Byte alignment is fine.  */
  return size;
}
void md_show_usage ( FILE *  stream)

Definition at line 1749 of file tc-mcore.c.

{
  fprintf (stream, _("\
MCORE specific options:\n\
  -{no-}jsri2bsr       {dis}able jsri to bsr transformation (def: dis)\n\
  -{no-}sifilter       {dis}able silicon filter behavior (def: dis)\n\
  -cpu=[210|340]          select CPU type\n\
  -EB                     assemble for a big endian system (default)\n\
  -EL                     assemble for a little endian system\n"));
}

Here is the call graph for this function:

symbolS* md_undefined_symbol ( char *name  ATTRIBUTE_UNUSED)

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

{
  return 0;
}
static int mylog2 ( unsigned int  val) [static]

Definition at line 477 of file tc-mcore.c.

{
  int log = -1;

  while (val != 0)
      {
       log ++;
       val >>= 1;
      }

  return log;
}

Here is the caller graph for this function:

static char* parse_creg ( char *  s,
unsigned reg 
) [static]

Definition at line 549 of file tc-mcore.c.

{
  int i;

  /* Strip leading whitespace.  */
  while (ISSPACE (* s))
    ++s;

  if ((TOLOWER (s[0]) == 'c' && TOLOWER (s[1]) == 'r'))
    {
      if (s[2] == '3' && s[3] >= '0' && s[3] <= '1')
       {
         *reg = 30 + s[3] - '0';
         return s + 4;
       }

      if (s[2] == '2' && s[3] >= '0' && s[3] <= '9')
       {
         *reg = 20 + s[3] - '0';
         return s + 4;
       }

      if (s[2] == '1' && s[3] >= '0' && s[3] <= '9')
       {
         *reg = 10 + s[3] - '0';
         return s + 4;
       }

      if (s[2] >= '0' && s[2] <= '9')
       {
         *reg = s[2] - '0';
         return s + 3;
       }
    }

  /* Look at alternate creg names before giving error.  */
  for (i = 0; cregs[i].name[0] != '\0'; i++)
    {
      char buf [10];
      int  length;
      int  j;

      length = strlen (cregs[i].name);

      for (j = 0; j < length; j++)
       buf[j] = TOLOWER (s[j]);

      if (strncmp (cregs[i].name, buf, length) == 0)
       {
         *reg = cregs[i].crnum;
         return s + length;
       }
    }

  as_bad (_("control register expected, but saw '%.6s'"), s);

  return s;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* parse_exp ( char *  s,
expressionS e 
) [static]

Definition at line 647 of file tc-mcore.c.

{
  char * save;
  char * new;

  /* Skip whitespace.  */
  while (ISSPACE (* s))
    ++ s;

  save = input_line_pointer;
  input_line_pointer = s;

  expression (e);

  if (e->X_op == O_absent)
    as_bad (_("missing operand"));

  new = input_line_pointer;
  input_line_pointer = save;

  return new;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* parse_imm ( char *  s,
unsigned val,
unsigned  min,
unsigned  max 
) [static]

Definition at line 769 of file tc-mcore.c.

{
  char * new;
  expressionS e;

  new = parse_exp (s, & e);

  if (e.X_op == O_absent)
    ; /* An error message has already been emitted.  */
  else if (e.X_op != O_constant)
    as_bad (_("operand must be a constant"));
  else if ((addressT) e.X_add_number < min || (addressT) e.X_add_number > max)
    as_bad (_("operand must be absolute in range %u..%u, not %ld"),
           min, max, (long) e.X_add_number);

  * val = e.X_add_number;

  return new;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* parse_mem ( char *  s,
unsigned reg,
unsigned off,
unsigned  siz 
) [static]

Definition at line 793 of file tc-mcore.c.

{
  * off = 0;

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

  if (* s == '(')
    {
      s = parse_reg (s + 1, reg);

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

      if (* s == ',')
       {
         s = parse_imm (s + 1, off, 0, 63);

         if (siz > 1)
           {
             if (siz > 2)
              {
                if (* off & 0x3)
                  as_bad (_("operand must be a multiple of 4"));

                * off >>= 2;
              }
             else
              {
                if (* off & 0x1)
                  as_bad (_("operand must be a multiple of 2"));

                * off >>= 1;
              }
           }
       }

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

      if (* s == ')')
       s ++;
    }
  else
    as_bad (_("base register expected"));

  return s;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* parse_psrmod ( char *  s,
unsigned reg 
) [static]

Definition at line 609 of file tc-mcore.c.

{
  int  i;
  char buf[10];
  static struct psrmods
  {
    char *       name;
    unsigned int value;
  }
  psrmods[] =
  {
    { "ie", 1 },
    { "fe", 2 },
    { "ee", 4 },
    { "af", 8 }      /* Really 0 and non-combinable.  */
  };

  for (i = 0; i < 2; i++)
    buf[i] = TOLOWER (s[i]);

  for (i = sizeof (psrmods) / sizeof (psrmods[0]); i--;)
    {
      if (! strncmp (psrmods[i].name, buf, 2))
       {
         * reg = psrmods[i].value;

         return s + 2;
       }
    }

  as_bad (_("bad/missing psr specifier"));

  * reg = 0;

  return s;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* parse_reg ( char *  s,
unsigned reg 
) [static]

Definition at line 493 of file tc-mcore.c.

{
  /* Strip leading whitespace.  */
  while (ISSPACE (* s))
    ++ s;

  if (TOLOWER (s[0]) == 'r')
    {
      if (s[1] == '1' && s[2] >= '0' && s[2] <= '5')
       {
         *reg = 10 + s[2] - '0';
         return s + 3;
       }

      if (s[1] >= '0' && s[1] <= '9')
       {
         *reg = s[1] - '0';
         return s + 2;
       }
    }
  else if (   TOLOWER (s[0]) == 's'
          && TOLOWER (s[1]) == 'p'
          && ! ISALNUM (s[2]))
    {
      * reg = 0;
      return s + 2;
    }

  as_bad (_("register expected, but saw '%.6s'"), s);
  return s;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* parse_rt ( char *  s,
char **  outputp,
int  ispcrel,
expressionS ep 
) [static]

Definition at line 724 of file tc-mcore.c.

{
  expressionS e;
  int n;

  if (ep)
    /* Indicate nothing there.  */
    ep->X_op = O_absent;

  if (*s == '[')
    {
      s = parse_exp (s + 1, & e);

      if (*s == ']')
       s++;
      else
       as_bad (_("missing ']'"));
    }
  else
    {
      s = parse_exp (s, & e);

      n = enter_literal (& e, ispcrel);

      if (ep)
       *ep = e;

      /* Create a reference to pool entry.  */
      e.X_op         = O_symbol;
      e.X_add_symbol = poolsym;
      e.X_add_number = n << 2;
    }

  * outputp = frag_more (2);

  fix_new_exp (frag_now, (*outputp) - frag_now->fr_literal, 2, & e, 1,
              BFD_RELOC_MCORE_PCREL_IMM8BY4);

  return s;
}

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 2217 of file tc-mcore.c.

{
  arelent * rel;
  bfd_reloc_code_real_type code;

  switch (fixp->fx_r_type)
    {
      /* These confuse the size/pcrel macro approach.  */
    case BFD_RELOC_VTABLE_INHERIT:
    case BFD_RELOC_VTABLE_ENTRY:
    case BFD_RELOC_MCORE_PCREL_IMM4BY2:
    case BFD_RELOC_MCORE_PCREL_IMM8BY4:
    case BFD_RELOC_MCORE_PCREL_IMM11BY2:
    case BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2:
    case BFD_RELOC_RVA:
      code = fixp->fx_r_type;
      break;

    default:
      switch (F (fixp->fx_size, fixp->fx_pcrel))
       {
         MAP (1, 0, BFD_RELOC_8);
         MAP (2, 0, BFD_RELOC_16);
         MAP (4, 0, BFD_RELOC_32);
         MAP (1, 1, BFD_RELOC_8_PCREL);
         MAP (2, 1, BFD_RELOC_16_PCREL);
         MAP (4, 1, BFD_RELOC_32_PCREL);
       default:
         code = fixp->fx_r_type;
         as_bad (_("Can not do %d byte %srelocation"),
                fixp->fx_size,
                fixp->fx_pcrel ? _("pc-relative") : "");
       }
      break;
  }

  rel = xmalloc (sizeof (arelent));
  rel->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
  *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
  rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
  /* Always pass the addend along!  */
  rel->addend = fixp->fx_addnumber;

  rel->howto = bfd_reloc_type_lookup (stdoutput, code);

  if (rel->howto == NULL)
    {
      as_bad_where (fixp->fx_file, fixp->fx_line,
                  _("Cannot represent relocation type %s"),
                  bfd_get_reloc_code_name (code));

      /* Set howto to a garbage value so that we can keep going.  */
      rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
      assert (rel->howto != NULL);
    }

  return rel;
}

Here is the call graph for this function:


Variable Documentation

const char comment_chars[] = "#/"

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

Definition at line 83 of file tc-mcore.c.

struct Cregs cregs[] [static]
int do_jsri2bsr = 0 [static]

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

const char EXP_CHARS[] = "eE"

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

const char FLT_CHARS[] = "rRsSfFdDxXpP"

Definition at line 57 of file tc-mcore.c.

const char line_comment_chars[] = "#/"

Definition at line 47 of file tc-mcore.c.

Definition at line 46 of file tc-mcore.c.

Definition at line 117 of file tc-mcore.c.

Definition at line 2117 of file tc-mcore.c.

size_t md_longopts_size = sizeof (md_longopts)

Definition at line 1717 of file tc-mcore.c.

const pseudo_typeS md_pseudo_table[]

Definition at line 402 of file tc-mcore.c.

const relax_typeS md_relax_table[]
Initial value:
{
  {    0,     0, 0,    0 },
  {    0,     0, 0,    0 },
  {    0,     0, 0,    0 },
  {    0,     0, 0,    0 },

  
  {    0,     0, 0,    0 },                 
  { 2048, -2046, C12_LEN, C(COND_JUMP, DISP32) }, 
  {    0,     0, C32_LEN, 0 },                     
  {    0,     0, C32_LEN, 0 },                     

  
  {    0,     0, 0,    0 },                 
  { 2048, -2046, U12_LEN, C(UNCD_JUMP, DISP32) }, 
  {    0,     0, U32_LEN, 0 },                     
  {    0,     0, U32_LEN, 0 }                      

}

Definition at line 86 of file tc-mcore.c.

Definition at line 1760 of file tc-mcore.c.

const char* md_shortopts = ""

Definition at line 1692 of file tc-mcore.c.

Definition at line 139 of file tc-mcore.c.

char poolname[8] [static]

Definition at line 138 of file tc-mcore.c.

unsigned poolnumber [static]

Definition at line 119 of file tc-mcore.c.

unsigned poolsize [static]

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

Definition at line 120 of file tc-mcore.c.

symbolS* poolsym [static]

Definition at line 137 of file tc-mcore.c.

int sifilter_mode = 0 [static]

Definition at line 50 of file tc-mcore.c.