(root)/
binutils-2.41/
gas/
config/
tc-epiphany.c
       1  /* tc-epiphany.c -- Assembler for the Adapteva EPIPHANY
       2     Copyright (C) 2009-2023 Free Software Foundation, Inc.
       3     Contributed by Embecosm on behalf of Adapteva, Inc.
       4  
       5     This file is part of GAS, the GNU Assembler.
       6  
       7     GAS is free software; you can redistribute it and/or modify
       8     it under the terms of the GNU General Public License as published by
       9     the Free Software Foundation; either version 3, or (at your option)
      10     any later version.
      11  
      12     GAS is distributed in the hope that it will be useful,
      13     but WITHOUT ANY WARRANTY; without even the implied warranty of
      14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15     GNU General Public License for more details.
      16  
      17     You should have received a copy of the GNU General Public License
      18     along with GAS; see the file COPYING.  If not, write to
      19     the Free Software Foundation, 51 Franklin Street - Fifth Floor,
      20     Boston, MA 02110-1301, USA.  */
      21  
      22  #include "as.h"
      23  #include "subsegs.h"
      24  #include "symcat.h"
      25  #include "opcodes/epiphany-desc.h"
      26  #include "opcodes/epiphany-opc.h"
      27  #include "cgen.h"
      28  #include "elf/common.h"
      29  #include "elf/epiphany.h"
      30  #include "dwarf2dbg.h"
      31  
      32  /* Structure to hold all of the different components describing
      33     an individual instruction.  */
      34  typedef struct
      35  {
      36    const CGEN_INSN *	insn;
      37    const CGEN_INSN *	orig_insn;
      38    CGEN_FIELDS		fields;
      39  #if CGEN_INT_INSN_P
      40    CGEN_INSN_INT         buffer [1];
      41  #define INSN_VALUE(buf) (*(buf))
      42  #else
      43    unsigned char         buffer [CGEN_MAX_INSN_SIZE];
      44  #define INSN_VALUE(buf) (buf)
      45  #endif
      46    char *		addr;
      47    fragS *		frag;
      48    int                   num_fixups;
      49    fixS *                fixups [GAS_CGEN_MAX_FIXUPS];
      50    int                   indices [MAX_OPERAND_INSTANCES];
      51  }
      52  epiphany_insn;
      53  
      54  const char comment_chars[]        = ";";
      55  const char line_comment_chars[]   = "#";
      56  const char line_separator_chars[] = "`";
      57  const char EXP_CHARS[]            = "eE";
      58  const char FLT_CHARS[]            = "fFdD";
      59  
      60  /* Flag to detect when switching to code section where insn alignment is
      61     implied.  */
      62  static bool force_code_align = false;
      63  
      64  static void
      65  epiphany_elf_section_rtn (int i)
      66  {
      67    obj_elf_section (i);
      68  
      69    if (force_code_align)
      70      {
      71        do_align (1, NULL, 0, 0);
      72        force_code_align = false;
      73      }
      74  }
      75  
      76  static void
      77  epiphany_elf_section_text (int i)
      78  {
      79    obj_elf_text (i);
      80  
      81    do_align (1, NULL, 0, 0);
      82    force_code_align = false;
      83  }
      84  
      85  /* The target specific pseudo-ops which we support.  */
      86  const pseudo_typeS md_pseudo_table[] =
      87  {
      88      { "text",   epiphany_elf_section_text,  0 },
      89      { "sect",   epiphany_elf_section_rtn,   0 },
      90      /* .word should be 32 bits.  */
      91      { "word",       cons, 4 },
      92      { "cpu",        s_ignore,         0 },
      93      { "thumb_func", s_ignore,         0 },
      94      { "code",       s_ignore,         0 },
      95      { NULL,         NULL,             0 }
      96  };
      97  
      98  
      99  
     100  enum options
     101  {
     102    OPTION_CPU_EPIPHANY = OPTION_MD_BASE,
     103    OPTION_CPU_EPIPHANY16
     104  };
     105  
     106  struct option md_longopts[] =
     107  {
     108    { "mepiphany ",  no_argument, NULL, OPTION_CPU_EPIPHANY },
     109    { "mepiphany16", no_argument, NULL, OPTION_CPU_EPIPHANY16 },
     110    { NULL,          no_argument, NULL, 0 },
     111  };
     112  
     113  size_t md_longopts_size = sizeof (md_longopts);
     114  
     115  const char * md_shortopts = "";
     116  
     117  int
     118  md_parse_option (int c ATTRIBUTE_UNUSED, const char * arg ATTRIBUTE_UNUSED)
     119  {
     120    return 0;	/* No target-specific options.  */
     121  }
     122  
     123  void
     124  md_show_usage (FILE * stream)
     125  {
     126    fprintf (stream, _("EPIPHANY specific command line options:\n"));
     127  }
     128  
     129  
     130  void
     131  md_begin (void)
     132  {
     133    /* Initialize the `cgen' interface.  */
     134  
     135    /* Set the machine number and endian.  */
     136    gas_cgen_cpu_desc = epiphany_cgen_cpu_open (CGEN_CPU_OPEN_MACHS,
     137  					   bfd_mach_epiphany32,
     138  					   CGEN_CPU_OPEN_ENDIAN,
     139  					   CGEN_ENDIAN_LITTLE,
     140  					   CGEN_CPU_OPEN_END);
     141    epiphany_cgen_init_asm (gas_cgen_cpu_desc);
     142  
     143    /* This is a callback from cgen to gas to parse operands.  */
     144    cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
     145  
     146    /* Set the machine type.  */
     147    bfd_default_set_arch_mach (stdoutput, bfd_arch_epiphany, bfd_mach_epiphany32);
     148  
     149    literal_prefix_dollar_hex = true;
     150  }
     151  
     152  valueT
     153  md_section_align (segT segment, valueT size)
     154  {
     155    int align = bfd_section_alignment (segment);
     156  
     157    return ((size + (1 << align) - 1) & -(1 << align));
     158  }
     159  
     160  
     161  /* Functions concerning relocs.  */
     162  
     163  long
     164  md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED)
     165  {
     166    abort ();
     167  }
     168  
     169  /* Write a value out to the object file, using the appropriate endianness.  */
     170  
     171  void
     172  md_number_to_chars (char * buf, valueT val, int n)
     173  {
     174    number_to_chars_littleendian (buf, val, n);
     175  }
     176  
     177  int
     178  epiphany_elf_section_flags (int flags,
     179  			    int attr ATTRIBUTE_UNUSED,
     180  			    int type ATTRIBUTE_UNUSED)
     181  {
     182    /* This is used to detect when the section changes to an executable section.
     183       This function is called by the elf section processing.  When we note an
     184       executable section specifier we set an internal flag to denote when
     185       word alignment should be forced.  */
     186    if (flags & SEC_CODE)
     187      force_code_align = true;
     188  
     189    return flags;
     190  }
     191  
     192  /* Non-zero if we are generating PIC code.  */
     193  int pic_code;
     194  
     195  /* Epiphany er_flags.  */
     196  static int epiphany_flags = 0;
     197  
     198  /* Relocations against symbols are done in two
     199     parts, with a HI relocation and a LO relocation.  Each relocation
     200     has only 16 bits of space to store an addend.  This means that in
     201     order for the linker to handle carries correctly, it must be able
     202     to locate both the HI and the LO relocation.  This means that the
     203     relocations must appear in order in the relocation table.
     204  
     205     In order to implement this, we keep track of each unmatched HI
     206     relocation.  We then sort them so that they immediately precede the
     207     corresponding LO relocation.  */
     208  
     209  struct epiphany_hi_fixup
     210  {
     211    /* Next HI fixup.  */
     212    struct epiphany_hi_fixup *next;
     213  
     214    /* This fixup.  */
     215    fixS *fixp;
     216  
     217    /* The section this fixup is in.  */
     218    segT seg;
     219  };
     220  
     221  
     222  #define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
     223  static symbolS * GOT_symbol;
     224  
     225  static inline bool
     226  epiphany_PIC_related_p (symbolS *sym)
     227  {
     228    expressionS *exp;
     229  
     230    if (! sym)
     231      return false;
     232  
     233    if (sym == GOT_symbol)
     234      return true;
     235  
     236    exp = symbol_get_value_expression (sym);
     237  
     238    return (exp->X_op == O_PIC_reloc
     239  	  || exp->X_md == BFD_RELOC_EPIPHANY_SIMM24
     240  	  || exp->X_md == BFD_RELOC_EPIPHANY_SIMM8
     241  	  || epiphany_PIC_related_p (exp->X_add_symbol)
     242  	  || epiphany_PIC_related_p (exp->X_op_symbol));
     243  }
     244  
     245  /* Perform target dependent relocations that are done at compile time.
     246     There aren't very many of these.  */
     247  
     248  void
     249  epiphany_apply_fix (fixS *fixP, valueT *valP, segT seg)
     250  {
     251    if (fixP->fx_addsy == (symbolS *) NULL)
     252      fixP->fx_done = 1;
     253  
     254    if (((int) fixP->fx_r_type < (int) BFD_RELOC_UNUSED)
     255        && fixP->fx_done)
     256      {
     257        /* Install EPIPHANY-dependent relocations HERE because nobody else
     258  	 will.  */
     259        char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
     260        unsigned char *insn = (unsigned char *)where;
     261        valueT value = * valP;
     262  
     263        switch (fixP->fx_r_type)
     264  	{
     265  	default:
     266  	  break;
     267  
     268  	case BFD_RELOC_NONE:
     269  	  return;
     270  
     271  	case BFD_RELOC_EPIPHANY_SIMM11:
     272  	  where[0] = where[0] | ((value & 1) << 7);
     273  	  where[1] = where[1] | ((value & 6) >> 1);
     274  	  where[2] = (value >> 3) & 0xff;
     275  	  return;
     276  
     277  	case BFD_RELOC_EPIPHANY_IMM11:
     278  	  where[0] = where[0] | ((value & 1) << 7);
     279  	  where[1] = where[1] | ((value & 6) >> 1);
     280  	  where[2] = (value >> 3) & 0xff;
     281  	  return;
     282  
     283  	case BFD_RELOC_EPIPHANY_SIMM8:
     284  	  md_number_to_chars (where+1, value>>1, 1);
     285  	  return;
     286  
     287  	case BFD_RELOC_EPIPHANY_SIMM24:
     288  	  md_number_to_chars (where+1, value>>1, 3);
     289  	  return;
     290  
     291  	case BFD_RELOC_EPIPHANY_HIGH:
     292  	  value >>= 16;
     293  	  /* fallthru */
     294  	case BFD_RELOC_EPIPHANY_LOW:
     295  	  value = (((value & 0xff) << 5) | insn[0])
     296  	    | (insn[1] << 8)
     297  	    | ((value & 0xff00) << 12)
     298  	    | (insn[2] << 16);
     299  	  md_number_to_chars (where, value, 3);
     300  	  return;
     301  	}
     302      }
     303  
     304    /* Just do the default if we can't special case.  */
     305    return gas_cgen_md_apply_fix (fixP, valP, seg);
     306  }
     307  
     308  
     309  /* This is called from HANDLE_ALIGN in write.c.  Fill in the contents
     310     of an rs_align_code fragment.  0x01a2 is 16-bit pattern for a "nop".  */
     311  
     312  static const unsigned char nop_pattern[] = { 0xa2, 0x01 };
     313  
     314  void
     315  epiphany_handle_align (fragS *fragp)
     316  {
     317    int bytes, fix;
     318    char *p;
     319  
     320    if (fragp->fr_type != rs_align_code)
     321      return;
     322  
     323    bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
     324    p = fragp->fr_literal + fragp->fr_fix;
     325    fix = 0;
     326  
     327    if (bytes & 1)
     328      {
     329        fix = 1;
     330        *p++ = 0;
     331        bytes--;
     332      }
     333  
     334    if (bytes & 2)
     335      {
     336        memcpy (p, nop_pattern, 2);
     337        p += 2;
     338        bytes -= 2;
     339        fix += 2;
     340      }
     341    fragp->fr_fix += fix;
     342  }
     343  
     344  /* Read a comma separated incrementing list of register names
     345     and form a bit mask of up to 15 registers 0..14.  */
     346  
     347  static const char *
     348  parse_reglist (const char * s, int * mask)
     349  {
     350    int regmask = 0;
     351  
     352    while (*s)
     353      {
     354        long value;
     355  
     356        while (*s == ' ')
     357  	++s;
     358  
     359        /* Parse a list with "," or "}" as limiters.  */
     360        const char *errmsg
     361  	= cgen_parse_keyword (gas_cgen_cpu_desc, &s,
     362  			      &epiphany_cgen_opval_gr_names, &value);
     363        if (errmsg)
     364  	return errmsg;
     365  
     366        if (value > 15)
     367  	return _("register number too large for push/pop");
     368  
     369        regmask |= 1 << value;
     370        if (regmask < *mask)
     371  	return _("register is out of order");
     372        *mask |= regmask;
     373  
     374        while (*s==' ')
     375  	++s;
     376  
     377        if (*s == '}')
     378  	return NULL;
     379        else if (*s++ == ',')
     380  	continue;
     381        else
     382  	return _("bad register list");
     383      }
     384  
     385    return _("malformed reglist in push/pop");
     386  }
     387  
     388  
     389  /* Assemble an instruction,  push and pop pseudo instructions should have
     390     already been expanded.  */
     391  
     392  static void
     393  epiphany_assemble (const char *str)
     394      {
     395    epiphany_insn insn;
     396    char *errmsg = 0;
     397  
     398    memset (&insn, 0, sizeof (insn));
     399  
     400    /* Initialize GAS's cgen interface for a new instruction.  */
     401    gas_cgen_init_parse ();
     402  
     403    insn.insn = epiphany_cgen_assemble_insn
     404      (gas_cgen_cpu_desc, str, &insn.fields, insn.buffer, & errmsg);
     405  
     406    if (!insn.insn)
     407      {
     408        as_bad ("%s", errmsg);
     409        return;
     410      }
     411  
     412    if (CGEN_INSN_BITSIZE (insn.insn) == 32)
     413      {
     414        /* Doesn't really matter what we pass for RELAX_P here.  */
     415        gas_cgen_finish_insn (insn.insn, insn.buffer,
     416  			    CGEN_FIELDS_BITSIZE (&insn.fields), 1, NULL);
     417      }
     418    else
     419      {
     420        if (CGEN_INSN_BITSIZE (insn.insn) != 16)
     421  	abort ();
     422  
     423        insn.orig_insn = insn.insn;
     424  
     425        gas_cgen_finish_insn (insn.orig_insn, insn.buffer,
     426  			    CGEN_FIELDS_BITSIZE (&insn.fields),
     427  			    1 /* relax_p  */, NULL);
     428      }
     429  
     430    /* Checks for behavioral restrictions on LD/ST instructions.  */
     431  #define DISPMOD _("destination register modified by displacement-post-modified address")
     432  #define LDSTODD _("ldrd/strd requires even:odd register pair")
     433  
     434    /* Helper macros for splitting apart instruction fields.  */
     435  #define ADDR_POST_MODIFIED(i) (((i) >> 25) & 0x1)
     436  #define ADDR_SIZE(i)          (((i) >>  5) &   3)
     437  #define ADDR_LOADSTORE(i)     (((i) >>  4) & 0x1)
     438  
     439    switch (insn.buffer[0] & 0xf)
     440      {
     441        /* Post-modify registers cannot be destinations.  */
     442      case OP4_LDSTR16P:
     443        {
     444  	if (ADDR_LOADSTORE (insn.buffer[0]) ==  OP_LOAD)
     445  	  if (insn.fields.f_rd == insn.fields.f_rn /* Postmodify dest.  */
     446  	      || (insn.fields.f_rd+1 == insn.fields.f_rn
     447  		  && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE))
     448  	    {
     449  	      as_bad ("%s", DISPMOD);
     450  	      return;
     451  	    }
     452  	if ((insn.fields.f_rd & 1) /* Odd-numbered register...  */
     453  	    && insn.fields.f_wordsize == OPW_DOUBLE) /* ...and 64 bit transfer.  */
     454  	  {
     455  	    as_bad ("%s", LDSTODD);
     456  	    return;
     457  	  }
     458  	break;
     459        }
     460  
     461      case OP4_LDSTRP:
     462        {
     463  	if (ADDR_LOADSTORE (insn.buffer[0]) == OP_LOAD) /* A load.  */
     464  	  if (insn.fields.f_rd6 == insn.fields.f_rn6 /* Postmodify dest.  */
     465  	      /* Check for regpair postindexed.  */
     466  	      || (insn.fields.f_rd6 + 1 == insn.fields.f_rn6
     467  		  && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE))
     468  	    {
     469  	      as_bad ("%s", DISPMOD);
     470  	      return;
     471  	    }
     472  	if ((insn.fields.f_rd6 & 1) && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)
     473  	  /* Lsb of RD odd and 64 bit transfer.  */
     474  	  {
     475  	    as_bad ("%s", LDSTODD);
     476  	    return;
     477  	  }
     478  	break;
     479        }
     480  
     481      case OP4_LDSTR16X:
     482      case OP4_LDSTR16D:
     483        {
     484  	/* Check for unaligned load/store double.  */
     485  	if ((insn.fields.f_rd & 1) && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)
     486  	  /* Lsb of RD odd and 64 bit transfer.  */
     487  	  {
     488  	    as_bad ("%s", LDSTODD);
     489  	    return;
     490  	  }
     491  	break;
     492        }
     493  
     494      case OP4_LDSTRD:
     495        {
     496  	/* Check for load to post-modified register.  */
     497  	if (ADDR_LOADSTORE (insn.buffer[0]) == OP_LOAD /* A load.  */
     498  	    && ADDR_POST_MODIFIED (insn.buffer[0]) == PMOD_POST /* Post-mod.  */
     499  	    && (insn.fields.f_rd6 == insn.fields.f_rn6
     500  		|| (insn.fields.f_rd6+1 == insn.fields.f_rn6
     501  		    && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)))
     502  	  {
     503  	    as_bad ("%s", DISPMOD);
     504  	    return;
     505  	  }
     506        }
     507        /* fallthru */
     508  
     509      case OP4_LDSTRX:
     510        {
     511  	/* Check for unaligned load/store double.  */
     512  	if ((insn.fields.f_rd6 & 1) && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)
     513  	  {
     514  	    as_bad ("%s", LDSTODD);
     515  	    return;
     516  	  }
     517  	break;
     518        }
     519  
     520      default:
     521        break;
     522      }
     523  }
     524  
     525  void
     526  md_assemble (char *str)
     527  {
     528    const char * pperr = 0;
     529    int regmask=0, push=0, pop=0;
     530  
     531    /* Special-case push/pop instruction macros.  */
     532    if (startswith (str, "push {"))
     533      {
     534        char * s = str + 6;
     535        push = 1;
     536        pperr = parse_reglist (s, &regmask);
     537      }
     538    else if (startswith (str, "pop {"))
     539      {
     540        char * s = str + 5;
     541        pop = 1;
     542        pperr = parse_reglist (s, &regmask);
     543      }
     544  
     545    if (pperr)
     546      {
     547        as_bad ("%s", pperr);
     548        return;
     549      }
     550  
     551    if (push && regmask)
     552      {
     553        char buff[32];
     554        int i,p ATTRIBUTE_UNUSED;
     555  
     556        epiphany_assemble ("mov r15,4");
     557        epiphany_assemble ("sub sp,sp,r15");
     558  
     559        for (i = 0, p = 1; i <= 15; ++i, regmask >>= 1)
     560  	{
     561  	  if (regmask == 1)
     562  	    sprintf (buff, "str r%d,[sp]", i); /* Last one.  */
     563  	  else if (regmask & 1)
     564  	    sprintf (buff, "str r%d,[sp],-r15", i);
     565  	  else
     566  	    continue;
     567  	  epiphany_assemble (buff);
     568  	}
     569        return;
     570      }
     571    else if (pop && regmask)
     572      {
     573        char buff[32];
     574        int i,p;
     575  
     576        epiphany_assemble ("mov r15,4");
     577  
     578        for (i = 15, p = 1 << 15; i >= 0; --i, p >>= 1)
     579  	if (regmask & p)
     580  	  {
     581  	    sprintf (buff, "ldr r%d,[sp],+r15", i);
     582  	    epiphany_assemble (buff);
     583  	  }
     584        return;
     585      }
     586  
     587    epiphany_assemble (str);
     588  }
     589  
     590  /* The syntax in the manual says constants begin with '#'.
     591     We just ignore it.  */
     592  
     593  void
     594  md_operand (expressionS *expressionP)
     595  {
     596    if (*input_line_pointer == '#')
     597      {
     598        input_line_pointer++;
     599        expression (expressionP);
     600      }
     601  }
     602  
     603  symbolS *
     604  md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
     605  {
     606    return NULL;
     607  }
     608  
     609  /* Interface to relax_segment.  */
     610  
     611  /* FIXME: Build table by hand, get it working, then machine generate.  */
     612  
     613  const relax_typeS md_relax_table[] =
     614  {
     615    /* The fields are:
     616       1) most positive reach of this state,
     617       2) most negative reach of this state,
     618       3) how many bytes this mode will add to the size of the current frag
     619       4) which index into the table to try if we can't fit into this one.  */
     620  
     621    /* The first entry must be unused because an `rlx_more' value of zero ends
     622       each list.  */
     623    {1, 1, 0, EPIPHANY_RELAX_NONE},
     624    {0, 0, 0, EPIPHANY_RELAX_NONE},    /* Also a dummy entry to indicate we need to expand codes.  */
     625  
     626    /* The displacement used by GAS is from the end of the 2 byte insn,
     627       so we subtract 2 from the following.  */
     628    /* 16 bit insn, 8 bit disp -> +127 words, -128 words.  */
     629    {0x00000100 - 1 - 2, -0x00000100 - 2, 0, EPIPHANY_RELAX_BRANCH_LONG },
     630    /* 32 bit insn, 24 bit disp -> 25 bit range.  */
     631    {0x01000000 - 1 - 2, -0x01000000 - 2, 2, EPIPHANY_RELAX_NONE },
     632  
     633    /* addi/subi 3 bits -4..+3.  */
     634    {    3,           -4,0, EPIPHANY_RELAX_ARITH_SIMM11 },
     635    /* addi/subi 11 bits.  */
     636    {  1023,       -1024,2, EPIPHANY_RELAX_NONE },
     637  
     638    /* mov r,imm8.  */
     639    {   255,           0,0, EPIPHANY_RELAX_MOV_IMM16 },
     640    /* mov r,imm16. */
     641    { 65535,           0,2, EPIPHANY_RELAX_NONE },
     642  
     643    /* ld/st rd,[rn,imm3].  */
     644    {     7,           0,0, EPIPHANY_RELAX_LDST_IMM11},
     645    /* ld/st rd,[rn,imm11].  */
     646    {  2047,           0,2, EPIPHANY_RELAX_NONE }
     647  
     648  };
     649  
     650  static const EPIPHANY_RELAX_TYPES relax_insn[] =
     651  {
     652    EPIPHANY_RELAX_BRANCH_SHORT,	/* OP4_BRANCH16 */
     653    EPIPHANY_RELAX_NONE,		/* OP4_LDSTR16X */
     654    EPIPHANY_RELAX_NONE,		/* OP4_FLOW16 */
     655    EPIPHANY_RELAX_ARITH_SIMM3,	/* OP4_IMM16 - special */
     656    EPIPHANY_RELAX_LDST_IMM3,	/* OP4_LDSTR16D */
     657    EPIPHANY_RELAX_NONE,		/* OP4_LDSTR126P */
     658    EPIPHANY_RELAX_NONE,		/* OP4_LSHIFT16 */
     659    EPIPHANY_RELAX_NONE,		/* OP4_DSP16 */
     660    EPIPHANY_RELAX_BRANCH_LONG,	/* OP4_BRANCH */
     661    EPIPHANY_RELAX_NONE,		/* OP4_LDSTRX */
     662    EPIPHANY_RELAX_NONE,		/* OP4_ALU16 */
     663    EPIPHANY_RELAX_ARITH_SIMM11,	/* OP4_IMM32 - special */
     664    EPIPHANY_RELAX_LDST_IMM11,	/* OP4_LDSTRD */
     665    EPIPHANY_RELAX_NONE,		/* OP4_LDSTRP */
     666    EPIPHANY_RELAX_NONE,		/* OP4_ASHIFT16 */
     667    EPIPHANY_RELAX_NONE		/* OP4_MISC */
     668  };
     669  
     670  long
     671  epiphany_relax_frag (segT segment, fragS *fragP, long stretch)
     672  {
     673    /* Address of branch insn.  */
     674    long address ATTRIBUTE_UNUSED = fragP->fr_address + fragP->fr_fix - 2;
     675    long growth = 0;
     676  
     677    if (fragP->fr_subtype == EPIPHANY_RELAX_NEED_RELAXING)
     678      {
     679        EPIPHANY_RELAX_TYPES subtype = relax_insn [*fragP->fr_opcode & 0xf];
     680  
     681        /* Special cases add/sub vs mov immediates.  */
     682        if (subtype == EPIPHANY_RELAX_ARITH_SIMM3)
     683  	{
     684  	  if ((*fragP->fr_opcode & 0x10) == 0)
     685  	    subtype = EPIPHANY_RELAX_MOV_IMM8;
     686  	}
     687        else if (subtype == EPIPHANY_RELAX_ARITH_SIMM11)
     688  	{
     689  	  if ((*fragP->fr_opcode & 0x10) == 0)
     690  	    subtype = EPIPHANY_RELAX_MOV_IMM16;
     691  	}
     692  
     693        /* Remember refinements for the future.  */
     694        fragP->fr_subtype = subtype;
     695      }
     696  
     697    growth = relax_frag (segment, fragP, stretch);
     698  
     699    return growth;
     700  }
     701  
     702  /* Return an initial guess of the length by which a fragment must grow to
     703     hold a branch to reach its destination.
     704     Also updates fr_type/fr_subtype as necessary.
     705  
     706     Called just before doing relaxation.
     707     Any symbol that is now undefined will not become defined.
     708     The guess for fr_var is ACTUALLY the growth beyond fr_fix.
     709     Whatever we do to grow fr_fix or fr_var contributes to our returned value.
     710     Although it may not be explicit in the frag, pretend fr_var starts
     711     with a 0 value.  */
     712  
     713  int
     714  md_estimate_size_before_relax (fragS *fragP, segT segment)
     715  {
     716    /* The only thing we have to handle here are symbols outside of the
     717       current segment.  They may be undefined or in a different segment in
     718       which case linker scripts may place them anywhere.
     719       However, we can't finish the fragment here and emit the reloc as insn
     720       alignment requirements may move the insn about.  */
     721    if (S_GET_SEGMENT (fragP->fr_symbol) != segment
     722        || S_IS_EXTERNAL (fragP->fr_symbol)
     723        || S_IS_WEAK (fragP->fr_symbol))
     724      {
     725        /* The symbol is undefined in this segment.  Change the
     726  	 relaxation subtype to the max allowable and leave all further
     727  	 handling to md_convert_frag.  */
     728  
     729        EPIPHANY_RELAX_TYPES subtype;
     730        const CGEN_INSN *insn;
     731        int i;
     732        /* We haven't relaxed this at all, so the relaxation type may be
     733  	 completely wrong.  Set the subtype correctly.  */
     734        epiphany_relax_frag (segment, fragP, 0);
     735        subtype = fragP->fr_subtype;
     736  
     737        switch (subtype)
     738  	{
     739  	case EPIPHANY_RELAX_LDST_IMM3:
     740  	  subtype = EPIPHANY_RELAX_LDST_IMM11;
     741  	  break;
     742  	case EPIPHANY_RELAX_BRANCH_SHORT:
     743  	  subtype = EPIPHANY_RELAX_BRANCH_LONG;
     744  	  break;
     745  	case EPIPHANY_RELAX_MOV_IMM8:
     746  	  subtype = EPIPHANY_RELAX_MOV_IMM16;
     747  	  break;
     748  	case EPIPHANY_RELAX_ARITH_SIMM3:
     749  	  subtype = EPIPHANY_RELAX_ARITH_SIMM11;
     750  	  break;
     751  
     752  	default:
     753  	  break;
     754  	}
     755  
     756        fragP->fr_subtype = subtype;
     757  
     758        /* Update the recorded insn.  */
     759        for (i = 0, insn = fragP->fr_cgen.insn; i < 4; i++, insn++)
     760  	{
     761  	  if (strcmp (CGEN_INSN_MNEMONIC (insn),
     762  		      CGEN_INSN_MNEMONIC (fragP->fr_cgen.insn)) == 0
     763  	      && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED))
     764  	    break;
     765  	}
     766  
     767        if (i == 4)
     768  	abort ();
     769  
     770        /* When changing from a 2-byte to 4-byte insn, don't leave
     771  	 opcode bytes uninitialised.  */
     772        if (CGEN_INSN_BITSIZE (fragP->fr_cgen.insn) < CGEN_INSN_BITSIZE (insn))
     773  	{
     774  	  gas_assert (CGEN_INSN_BITSIZE (fragP->fr_cgen.insn) == 16);
     775  	  gas_assert (CGEN_INSN_BITSIZE (insn) == 32);
     776  	  fragP->fr_opcode[2] = 0;
     777  	  fragP->fr_opcode[3] = 0;
     778  	}
     779  
     780        fragP->fr_cgen.insn = insn;
     781      }
     782  
     783    return md_relax_table[fragP->fr_subtype].rlx_length;
     784  }
     785  
     786  /* *FRAGP has been relaxed to its final size, and now needs to have
     787     the bytes inside it modified to conform to the new size.
     788  
     789     Called after relaxation is finished.
     790     fragP->fr_type == rs_machine_dependent.
     791     fragP->fr_subtype is the subtype of what the address relaxed to.  */
     792  
     793  void
     794  md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
     795  		 segT sec,
     796  		 fragS *fragP)
     797  {
     798    char *opcode;
     799    char *displacement;
     800    int target_address;
     801    int opcode_address;
     802    int extension;
     803    int addend;
     804    int opindx = -1;
     805  
     806    opcode = fragP->fr_opcode;
     807  
     808    /* Address opcode resides at in file space.  */
     809    opcode_address = fragP->fr_address + fragP->fr_fix - 2;
     810    extension = 0;
     811    displacement = &opcode[1];
     812  
     813    /* Set up any addend necessary for branches.  */
     814    if (S_GET_SEGMENT (fragP->fr_symbol) != sec
     815        || S_IS_EXTERNAL (fragP->fr_symbol)
     816        || S_IS_WEAK (fragP->fr_symbol))
     817      {
     818        /* Symbol must be resolved by linker.  */
     819        if (fragP->fr_offset & 1)
     820  	as_warn (_("Addend to unresolved symbol not on word boundary."));
     821        addend = 0;
     822      }
     823    else
     824      {
     825        /* Address we want to reach in file space.  */
     826        target_address = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset;
     827        addend = (target_address - (opcode_address & -2));
     828      }
     829  
     830    /* Do all the housekeeping for frag conversions. */
     831    switch (fragP->fr_subtype)
     832      {
     833      case EPIPHANY_RELAX_ARITH_SIMM11:
     834        *opcode |= OP4_IMM32;
     835        displacement = &opcode[0];
     836        extension += 3;
     837  
     838        addend
     839  	= (((addend & 0x7) << 7)
     840  	   | opcode[0]
     841  	   | ((addend & 0x7f8) << 13)
     842  	   | (opcode[1] << 8)
     843  	   | (opcode[2] << 16));
     844  
     845        opindx = EPIPHANY_OPERAND_SIMM11;
     846        break;
     847  
     848      case EPIPHANY_RELAX_BRANCH_LONG:
     849        /* Branches differ only in low nibble of instruction being 8 not 0.
     850  	 24 bit displacement goes to bytes 1..3 .  */
     851        *opcode |= OP4_BRANCH;
     852        extension += 2;
     853  
     854        addend >>= 1;		/* Convert to word offset.  */
     855        opindx = EPIPHANY_OPERAND_SIMM24;
     856        break;
     857  
     858      case EPIPHANY_RELAX_MOV_IMM16:
     859        *opcode |=  OP4_IMM32;
     860        extension += 3;
     861  
     862        addend
     863  	= (((addend & 0xff00) << 12)
     864  	   | (opcode[2] << 16)
     865  	   | ((addend & 0x00ff) << 5)
     866  	   | (opcode[1] << 8)
     867  	   | opcode[0]);
     868        displacement = &opcode[0];
     869        opindx = EPIPHANY_OPERAND_IMM16;
     870        break;
     871  
     872      case EPIPHANY_RELAX_LDST_IMM11:
     873        *opcode |= OP4_LDSTRD;
     874        displacement = &opcode[0];
     875        extension += 3;
     876  
     877        if (addend < 0)
     878  	/* Convert twos-complement address value to sign-magnitude.  */
     879  	addend = (-addend & 0x7ff) | 0x800;
     880  
     881        addend
     882  	= (((addend & 0x7) << 5)
     883  	   | opcode[0]
     884  	   | ((addend & 0xff8) << 13)
     885  	   | (opcode[1] << 8)
     886  	   | (opcode[2] << 16));
     887  
     888        opindx = EPIPHANY_OPERAND_DISP11;
     889        break;
     890  
     891      case EPIPHANY_RELAX_ARITH_SIMM3:
     892        addend = ((addend & 7) << 5) | opcode[0];
     893        opindx = EPIPHANY_OPERAND_SIMM3;
     894        break;
     895  
     896      case EPIPHANY_RELAX_LDST_IMM3:
     897        addend = ((addend & 7) << 5) | opcode[0];
     898        opindx = EPIPHANY_OPERAND_DISP3;
     899        break;
     900  
     901      case EPIPHANY_RELAX_BRANCH_SHORT:
     902        addend >>= 1;		/* Convert to a word offset.  */
     903        displacement = & opcode[1];
     904        opindx = EPIPHANY_OPERAND_SIMM8;
     905        break;
     906  
     907      case EPIPHANY_RELAX_MOV_IMM8:
     908        addend
     909  	= (((addend & 0xff) << 5)
     910  	   | opcode[0]
     911  	   | (opcode[1] << 8));
     912        opindx = EPIPHANY_OPERAND_IMM8;
     913        break;
     914  
     915      case EPIPHANY_RELAX_NONE:
     916      case EPIPHANY_RELAX_NEED_RELAXING:
     917      default:			/* Anything else?  */
     918        as_bad ("unrecognized fragment subtype");
     919        break;
     920      }
     921  
     922    /* Create a relocation for symbols that must be resolved by the linker.
     923       Otherwise output the completed insn.  */
     924  
     925    if (S_GET_SEGMENT (fragP->fr_symbol) != sec
     926        || S_IS_EXTERNAL (fragP->fr_symbol)
     927        || S_IS_WEAK (fragP->fr_symbol))
     928      {
     929        fixS *fixP;
     930        const CGEN_OPERAND *operand
     931  	= cgen_operand_lookup_by_num (gas_cgen_cpu_desc, opindx);
     932        bfd_reloc_code_real_type reloc_type;
     933  
     934        gas_assert (fragP->fr_cgen.insn != 0);
     935  
     936        reloc_type = md_cgen_lookup_reloc (fragP->fr_cgen.insn, operand, NULL);
     937  
     938        fixP = gas_cgen_record_fixup (fragP,
     939  				    /* Offset of insn in frag.  */
     940  				    (opcode - fragP->fr_literal),
     941  				    fragP->fr_cgen.insn,
     942  				    CGEN_INSN_BITSIZE (fragP->fr_cgen.insn) / 8,
     943  				    operand,
     944  				    reloc_type,
     945  				    fragP->fr_symbol, fragP->fr_offset);
     946        fixP->fx_r_type = fixP->fx_cgen.opinfo;
     947      }
     948  
     949    md_number_to_chars (displacement, (valueT) addend, extension + 1);
     950  
     951    fragP->fr_fix += (extension & -2); /* 0,2 or 4 bytes added.  */
     952  }
     953  
     954  
     955  /* Functions concerning relocs.  */
     956  
     957  /* The location from which a PC relative jump should be calculated,
     958     given a PC relative reloc.  */
     959  
     960  long
     961  md_pcrel_from_section (fixS *fixP, segT sec)
     962  {
     963    if (fixP->fx_addsy != (symbolS *) NULL
     964        && (!S_IS_DEFINED (fixP->fx_addsy)
     965  	  || (S_GET_SEGMENT (fixP->fx_addsy) != sec)
     966  	  || S_IS_EXTERNAL (fixP->fx_addsy)
     967  	  || S_IS_WEAK (fixP->fx_addsy)))
     968      return 0;
     969  
     970    return fixP->fx_frag->fr_address + fixP->fx_where;
     971  }
     972  
     973  /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
     974     Returns BFD_RELOC_NONE if no reloc type can be found.
     975     *FIXP may be modified if desired.  */
     976  
     977  bfd_reloc_code_real_type
     978  md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
     979  		      const CGEN_OPERAND *operand,
     980  		      fixS *fixP ATTRIBUTE_UNUSED)
     981  {
     982    switch (operand->type)
     983      {
     984      case EPIPHANY_OPERAND_SIMM11:
     985        return BFD_RELOC_EPIPHANY_SIMM11;
     986      case EPIPHANY_OPERAND_DISP11:
     987        return BFD_RELOC_EPIPHANY_IMM11;
     988  
     989      case EPIPHANY_OPERAND_SIMM8:
     990        return BFD_RELOC_EPIPHANY_SIMM8;
     991      case EPIPHANY_OPERAND_SIMM24:
     992        return BFD_RELOC_EPIPHANY_SIMM24;
     993  
     994      case EPIPHANY_OPERAND_IMM8:
     995        return BFD_RELOC_EPIPHANY_IMM8;
     996  
     997      case EPIPHANY_OPERAND_IMM16:
     998        if (0 == strcmp ("movt", CGEN_INSN_MNEMONIC (insn)))
     999  	return BFD_RELOC_EPIPHANY_HIGH;
    1000        else if (0 == strcmp ("mov", CGEN_INSN_MNEMONIC (insn)))
    1001  	return BFD_RELOC_EPIPHANY_LOW;
    1002        else
    1003  	as_bad ("unknown imm16 operand");
    1004        /* fallthru */
    1005  
    1006      default:
    1007        break;
    1008      }
    1009    return BFD_RELOC_NONE;
    1010  }
    1011  
    1012  
    1013  /* Turn a string in input_line_pointer into a floating point constant
    1014     of type TYPE, and store the appropriate bytes in *LITP.  The number
    1015     of LITTLENUMS emitted is stored in *SIZEP.  An error message is
    1016     returned, or NULL on OK.  */
    1017  
    1018  const char *
    1019  md_atof (int type, char *litP, int *sizeP)
    1020  {
    1021    return ieee_md_atof (type, litP, sizeP, false);
    1022  }
    1023  
    1024  /* Return true if can adjust the reloc to be relative to its section
    1025     (such as .data) instead of relative to some symbol.  */
    1026  
    1027  bool
    1028  epiphany_fix_adjustable (fixS *fixP)
    1029  {
    1030   bfd_reloc_code_real_type reloc_type;
    1031  
    1032    if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
    1033      {
    1034        const CGEN_INSN *insn = fixP->fx_cgen.insn;
    1035        int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
    1036        const CGEN_OPERAND *operand =
    1037  	cgen_operand_lookup_by_num (gas_cgen_cpu_desc, opindex);
    1038  
    1039        reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
    1040      }
    1041    else
    1042      reloc_type = fixP->fx_r_type;
    1043  
    1044    if (fixP->fx_addsy == NULL)
    1045      return true;
    1046  
    1047    /* Prevent all adjustments to global symbols.  */
    1048    if (S_IS_EXTERNAL (fixP->fx_addsy))
    1049      return false;
    1050  
    1051    if (S_IS_WEAK (fixP->fx_addsy))
    1052      return false;
    1053  
    1054    if (pic_code
    1055        && (reloc_type == BFD_RELOC_EPIPHANY_SIMM24
    1056  	  || reloc_type == BFD_RELOC_EPIPHANY_SIMM8
    1057  	  || reloc_type == BFD_RELOC_EPIPHANY_HIGH
    1058  	  || reloc_type == BFD_RELOC_EPIPHANY_LOW))
    1059      return false;
    1060  
    1061    /* Since we don't use partial_inplace, we must not reduce symbols in
    1062       mergeable sections to their section symbol.  */
    1063    if ((S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE) != 0)
    1064      return false;
    1065  
    1066    return true;
    1067  }
    1068  
    1069  void
    1070  epiphany_elf_final_processing (void)
    1071  {
    1072    elf_elfheader (stdoutput)->e_flags |= epiphany_flags;
    1073  }
    1074  
    1075  int
    1076  epiphany_cgen_parse_fix_exp (int opinfo, expressionS *exp ATTRIBUTE_UNUSED)
    1077  {
    1078    LITTLENUM_TYPE words[2];
    1079  
    1080    switch (opinfo)
    1081      {
    1082      case BFD_RELOC_EPIPHANY_LOW:
    1083      case BFD_RELOC_EPIPHANY_HIGH:
    1084        break;
    1085      default:
    1086        return opinfo;
    1087      }
    1088  
    1089    /* Doing a %LOW or %HIGH.  */
    1090    switch (exp->X_op)
    1091      {
    1092      default:
    1093        return opinfo;
    1094      case O_big:				/* Bignum.  */
    1095        if (exp->X_add_number > 0)	/* Integer value too large.  */
    1096  	return opinfo;
    1097      }
    1098  
    1099    /* Convert to SP number.  */
    1100    gen_to_words (words, 2, 8L);
    1101    exp->X_add_number = words[1] | (words[0] << 16);
    1102    exp->X_op = O_constant;
    1103    return opinfo;
    1104  }