(root)/
binutils-2.41/
gas/
config/
tc-ft32.c
       1  /* tc-ft32.c -- Assemble code for ft32
       2     Copyright (C) 2008-2023 Free Software Foundation, Inc.
       3  
       4     This file is part of GAS, the GNU Assembler.
       5  
       6     GAS is free software; you can redistribute it and/or modify
       7     it under the terms of the GNU General Public License as published by
       8     the Free Software Foundation; either version 3, or (at your option)
       9     any later version.
      10  
      11     GAS is distributed in the hope that it will be useful,
      12     but WITHOUT ANY WARRANTY; without even the implied warranty of
      13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14     GNU General Public License for more details.
      15  
      16     You should have received a copy of the GNU General Public License
      17     along with GAS; see the file COPYING.  If not, write to
      18     the Free Software Foundation, 51 Franklin Street - Fifth Floor,
      19     Boston, MA 02110-1301, USA.  */
      20  
      21  /* Contributed by Anthony Green <green@spindazzle.org>.  */
      22  
      23  #include "as.h"
      24  #include "safe-ctype.h"
      25  #include "opcode/ft32.h"
      26  
      27  extern const ft32_opc_info_t ft32_opc_info[128];
      28  
      29  /* See md_parse_option() for meanings of these options.  */
      30  static char norelax;			/* True if -norelax switch seen.  */
      31  
      32  const char comment_chars[]        = "#";
      33  const char line_separator_chars[] = ";";
      34  const char line_comment_chars[]   = "#";
      35  
      36  static int pending_reloc;
      37  static htab_t opcode_hash_control;
      38  
      39  static valueT md_chars_to_number (char * buf, int n);
      40  
      41  const pseudo_typeS md_pseudo_table[] =
      42  {
      43    {0, 0, 0}
      44  };
      45  
      46  const char FLT_CHARS[] = "rRsSfFdDxXpP";
      47  const char EXP_CHARS[] = "eE";
      48  
      49  /* This function is called once, at assembler startup time.  It sets
      50     up the hash table with all the opcodes in it, and also initializes
      51     some aliases for compatibility with other assemblers.  */
      52  
      53  void
      54  md_begin (void)
      55  {
      56    const ft32_opc_info_t *opcode;
      57    opcode_hash_control = str_htab_create ();
      58  
      59    /* Insert names into hash table.  */
      60    for (opcode = ft32_opc_info; opcode->name; opcode++)
      61      str_hash_insert (opcode_hash_control, opcode->name, opcode, 0);
      62  
      63    bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
      64    if (!norelax)
      65      linkrelax = 1;
      66  }
      67  
      68  /* Parse an expression and then restore the input line pointer.  */
      69  
      70  static char *
      71  parse_exp_save_ilp (char *s, expressionS *op)
      72  {
      73    char *save = input_line_pointer;
      74  
      75    input_line_pointer = s;
      76    expression (op);
      77    s = input_line_pointer;
      78    input_line_pointer = save;
      79    return s;
      80  }
      81  
      82  static int
      83  parse_condition (char **ptr)
      84  {
      85    char *s = *ptr;
      86    static const struct
      87    {
      88      const char *name;
      89      int bits;
      90    }
      91    ccs[] =
      92    {
      93      { "gt,"   , (2 << FT32_FLD_CR_BIT) | (5 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)},
      94      { "gte,"  , (2 << FT32_FLD_CR_BIT) | (4 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)},
      95      { "lt,"   , (2 << FT32_FLD_CR_BIT) | (4 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)},
      96      { "lte,"  , (2 << FT32_FLD_CR_BIT) | (5 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)},
      97      { "a,"    , (2 << FT32_FLD_CR_BIT) | (6 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)},
      98      { "ae,"   , (2 << FT32_FLD_CR_BIT) | (1 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)},
      99      { "be,"   , (2 << FT32_FLD_CR_BIT) | (6 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)},
     100      { "b,"    , (2 << FT32_FLD_CR_BIT) | (1 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)},
     101      { "nz,"   , (2 << FT32_FLD_CR_BIT) | (0 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)},
     102      { "z,"    , (2 << FT32_FLD_CR_BIT) | (0 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)},
     103      { "nc,"   , (2 << FT32_FLD_CR_BIT) | (1 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)},
     104      { "c,"    , (2 << FT32_FLD_CR_BIT) | (1 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)},
     105      { "no,"   , (2 << FT32_FLD_CR_BIT) | (2 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)},
     106      { "o,"    , (2 << FT32_FLD_CR_BIT) | (2 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)},
     107      { "ns,"   , (2 << FT32_FLD_CR_BIT) | (3 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)},
     108      { "s,"    , (2 << FT32_FLD_CR_BIT) | (3 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)},
     109      { NULL, 0}
     110    }, *pc;
     111  
     112    for (pc = ccs; pc->name; pc++)
     113      {
     114        if (memcmp(pc->name, s, strlen(pc->name)) == 0)
     115          {
     116            *ptr += strlen(pc->name) - 1;
     117            return pc->bits;
     118          }
     119      }
     120    return -1;
     121  }
     122  
     123  static int
     124  parse_decimal (char **ptr)
     125  {
     126    int r = 0;
     127    char *s = *ptr;
     128  
     129    while (('0' <= *s) && (*s <= '9'))
     130      {
     131        r *= 10;
     132        r += (*s++ - '0');
     133      }
     134    *ptr = s;
     135    return r;
     136  }
     137  
     138  static int
     139  parse_register_operand (char **ptr)
     140  {
     141    int reg;
     142    char *s = *ptr;
     143  
     144    if (*s != '$')
     145      {
     146        as_bad (_("expecting register"));
     147        ignore_rest_of_line ();
     148        return -1;
     149      }
     150    if ((s[1] == 's') && (s[2] == 'p'))
     151      {
     152        reg = 31;
     153      }
     154    else if ((s[1] == 'c') && (s[2] == 'c'))
     155      {
     156        reg = 30;
     157      }
     158    else if ((s[1] == 'f') && (s[2] == 'p'))
     159      {
     160        reg = 29;
     161      }
     162    else if (s[1] == 'r')
     163      {
     164        reg = s[2] - '0';
     165        if ((reg < 0) || (reg > 9))
     166  	{
     167  	  as_bad (_("illegal register number"));
     168  	  ignore_rest_of_line ();
     169  	  return -1;
     170  	}
     171        if ((reg == 1) || (reg == 2) || (reg == 3))
     172  	{
     173  	  int r2 = s[3] - '0';
     174  	  if ((r2 >= 0) && (r2 <= 9))
     175  	    {
     176  	      reg = (reg * 10) + r2;
     177  	      *ptr += 1;
     178  	    }
     179  	}
     180      }
     181    else
     182      {
     183        as_bad (_("illegal register number"));
     184        ignore_rest_of_line ();
     185        return -1;
     186      }
     187  
     188    *ptr += 3;
     189  
     190    return reg;
     191  }
     192  
     193  /* This is the guts of the machine-dependent assembler.  STR points to
     194     a machine dependent instruction.  This function is supposed to emit
     195     the frags/bytes it assembles to.  */
     196  
     197  void
     198  md_assemble (char *str)
     199  {
     200    char *op_start;
     201    char *op_end;
     202    ft32_opc_info_t *opcode;
     203    char *output;
     204    int idx = 0;
     205    char pend;
     206    int nlen = 0;
     207    unsigned int b;
     208    int f;
     209    expressionS arg;
     210    bool fixed = false;
     211    unsigned int sc;
     212    bool can_sc;
     213  
     214    /* Drop leading whitespace.  */
     215    while (*str == ' ')
     216      str++;
     217  
     218    /* Find the op code end.  */
     219    op_start = str;
     220    for (op_end = str;
     221         *op_end
     222         && !is_end_of_line[*op_end & 0xff]
     223         && *op_end != ' '
     224         && *op_end != '.';
     225         op_end++)
     226      nlen++;
     227  
     228    pend = *op_end;
     229    *op_end = 0;
     230  
     231    if (nlen == 0)
     232      as_bad (_("can't find opcode "));
     233  
     234    opcode = (ft32_opc_info_t *) str_hash_find (opcode_hash_control, op_start);
     235    *op_end = pend;
     236  
     237    if (opcode == NULL)
     238      {
     239        as_bad (_("unknown opcode %s"), op_start);
     240        return;
     241      }
     242  
     243    b = opcode->bits;
     244    f = opcode->fields;
     245  
     246    if (opcode->dw)
     247      {
     248        int dw;
     249  
     250        if (*op_end == '.')
     251          {
     252            switch (op_end[1])
     253              {
     254                case 'b':
     255                  dw = 0;
     256                  break;
     257                case 's':
     258                  dw = 1;
     259                  break;
     260                case 'l':
     261                  dw = 2;
     262                  break;
     263                default:
     264                  as_bad (_("unknown width specifier '.%c'"), op_end[1]);
     265                  return;
     266              }
     267            op_end += 2;
     268          }
     269        else
     270          {
     271            dw = 2; /* default is ".l" */
     272          }
     273        b |= dw << FT32_FLD_DW_BIT;
     274      }
     275  
     276    while (ISSPACE (*op_end))
     277      op_end++;
     278  
     279    output = frag_more (4);
     280  
     281    while (f)
     282      {
     283        int lobit = f & -f;
     284  
     285        if (f & lobit)
     286          {
     287            switch (lobit)
     288  	    {
     289  	    case  FT32_FLD_CBCRCV:
     290  	      b |= parse_condition( &op_end);
     291  	      break;
     292  	    case  FT32_FLD_CB:
     293  	      b |= parse_decimal (&op_end) << FT32_FLD_CB_BIT;
     294  	      break;
     295  	    case  FT32_FLD_R_D:
     296  	      b |= parse_register_operand (&op_end) << FT32_FLD_R_D_BIT;
     297  	      break;
     298  	    case  FT32_FLD_CR:
     299  	      b |= (parse_register_operand (&op_end) - 28) << FT32_FLD_CR_BIT;
     300  	      break;
     301  	    case  FT32_FLD_CV:
     302  	      b |= parse_decimal (&op_end) << FT32_FLD_CV_BIT;
     303  	      break;
     304  	    case  FT32_FLD_R_1:
     305  	      b |= parse_register_operand (&op_end) << FT32_FLD_R_1_BIT;
     306  	      break;
     307  	    case  FT32_FLD_RIMM:
     308  	      if (*op_end == '$')
     309  		{
     310  		  b |= parse_register_operand (&op_end) << FT32_FLD_RIMM_BIT;
     311  		}
     312  	      else
     313  		{
     314  		  b |= 0x400 << FT32_FLD_RIMM_BIT;
     315  		  op_end = parse_exp_save_ilp (op_end, &arg);
     316  		  fixed = true;
     317  		  fix_new_exp (frag_now,
     318  			       (output - frag_now->fr_literal),
     319  			       2,
     320  			       &arg,
     321  			       0,
     322  			       BFD_RELOC_FT32_10);
     323  		}
     324  	      break;
     325  	    case  FT32_FLD_R_2:
     326  	      b |= parse_register_operand (&op_end) << FT32_FLD_R_2_BIT;
     327  	      break;
     328  	    case  FT32_FLD_K20:
     329  	      op_end = parse_exp_save_ilp (op_end, &arg);
     330  	      fixed = true;
     331  	      fix_new_exp (frag_now,
     332  			   (output - frag_now->fr_literal),
     333  			   3,
     334  			   &arg,
     335  			   0,
     336  			   BFD_RELOC_FT32_20);
     337  	      break;
     338  	    case  FT32_FLD_PA:
     339  	      op_end = parse_exp_save_ilp (op_end, &arg);
     340  	      fixed = true;
     341  	      fix_new_exp (frag_now,
     342  			   (output - frag_now->fr_literal),
     343  			   3,
     344  			   &arg,
     345  			   0,
     346  			   BFD_RELOC_FT32_18);
     347  	      break;
     348  	    case  FT32_FLD_AA:
     349  	      op_end = parse_exp_save_ilp (op_end, &arg);
     350  	      fixed = true;
     351  	      fix_new_exp (frag_now,
     352  			   (output - frag_now->fr_literal),
     353  			   3,
     354  			   &arg,
     355  			   0,
     356  			   BFD_RELOC_FT32_17);
     357  	      break;
     358  	    case  FT32_FLD_K16:
     359  	      op_end = parse_exp_save_ilp (op_end, &arg);
     360  	      fixed = true;
     361  	      fix_new_exp (frag_now,
     362  			   (output - frag_now->fr_literal),
     363  			   2,
     364  			   &arg,
     365  			   0,
     366  			   BFD_RELOC_16);
     367  	      break;
     368  	    case  FT32_FLD_K15:
     369  	      op_end = parse_exp_save_ilp (op_end, &arg);
     370  	      if (arg.X_add_number & 0x80)
     371  		arg.X_add_number ^= 0x7f00;
     372  	      fixed = true;
     373  	      fix_new_exp (frag_now,
     374  			   (output - frag_now->fr_literal),
     375  			   2,
     376  			   &arg,
     377  			   0,
     378  			   BFD_RELOC_FT32_15);
     379  	      break;
     380  	    case  FT32_FLD_R_D_POST:
     381  	      b |= parse_register_operand (&op_end) << FT32_FLD_R_D_BIT;
     382  	      break;
     383  	    case  FT32_FLD_R_1_POST:
     384  	      b |= parse_register_operand (&op_end) << FT32_FLD_R_1_BIT;
     385  	      break;
     386  	    default:
     387  	      as_bad (_("internal error in argument parsing"));
     388  	      break;
     389  	    }
     390  
     391            f &= ~lobit;
     392  
     393            if (f)
     394              {
     395                while (ISSPACE (*op_end))
     396                  op_end++;
     397  
     398                if (*op_end != ',')
     399                  {
     400                    as_bad (_("expected comma separator"));
     401                    ignore_rest_of_line ();
     402                  }
     403  
     404                op_end++;
     405                while (ISSPACE (*op_end))
     406                  op_end++;
     407              }
     408          }
     409      }
     410  
     411    if (*op_end != 0)
     412      as_warn (_("extra stuff on line ignored"));
     413  
     414    can_sc = ft32_shortcode (b, &sc);
     415  
     416    if (!fixed && can_sc)
     417      {
     418        arg.X_op = O_constant;
     419        arg.X_add_number = 0;
     420        arg.X_add_symbol = NULL;
     421        arg.X_op_symbol = NULL;
     422        fix_new_exp (frag_now,
     423                     (output - frag_now->fr_literal),
     424                     2,
     425                     &arg,
     426                     0,
     427                     BFD_RELOC_FT32_RELAX);
     428      }
     429  
     430    output[idx++] = 0xff & (b >> 0);
     431    output[idx++] = 0xff & (b >> 8);
     432    output[idx++] = 0xff & (b >> 16);
     433    output[idx++] = 0xff & (b >> 24);
     434  
     435    dwarf2_emit_insn (4);
     436  
     437    while (ISSPACE (*op_end))
     438      op_end++;
     439  
     440    if (*op_end != 0)
     441      as_warn ("extra stuff on line ignored");
     442  
     443    if (pending_reloc)
     444      as_bad ("Something forgot to clean up\n");
     445  }
     446  
     447  /* Turn a string in input_line_pointer into a floating point constant
     448     of type type, and store the appropriate bytes in *LITP.  The number
     449     of LITTLENUMS emitted is stored in *SIZEP .  An error message is
     450     returned, or NULL on OK.  */
     451  
     452  const char *
     453  md_atof (int type, char *litP, int *sizeP)
     454  {
     455    int prec;
     456    LITTLENUM_TYPE words[4];
     457    char *t;
     458    int i;
     459  
     460    switch (type)
     461      {
     462      case 'f':
     463        prec = 2;
     464        break;
     465  
     466      case 'd':
     467        prec = 4;
     468        break;
     469  
     470      default:
     471        *sizeP = 0;
     472        return _("bad call to md_atof");
     473      }
     474  
     475    t = atof_ieee (input_line_pointer, type, words);
     476    if (t)
     477      input_line_pointer = t;
     478  
     479    *sizeP = prec * 2;
     480  
     481    for (i = prec - 1; i >= 0; i--)
     482      {
     483        md_number_to_chars (litP, (valueT) words[i], 2);
     484        litP += 2;
     485      }
     486  
     487    return NULL;
     488  }
     489  
     490  const char *md_shortopts = "";
     491  
     492  struct option md_longopts[] =
     493  {
     494  #define OPTION_NORELAX (OPTION_MD_BASE)
     495    {"norelax", no_argument, NULL, OPTION_NORELAX},
     496    {"no-relax", no_argument, NULL, OPTION_NORELAX},
     497    {NULL, no_argument, NULL, 0}
     498  };
     499  size_t md_longopts_size = sizeof (md_longopts);
     500  
     501  /* We have no target specific options yet, so these next
     502     two functions are empty.  */
     503  int
     504  md_parse_option (int c ATTRIBUTE_UNUSED, const char *arg ATTRIBUTE_UNUSED)
     505  {
     506    switch (c)
     507      {
     508      case OPTION_NORELAX:
     509        norelax = 1;
     510        break;
     511  
     512      default:
     513        return 0;
     514      }
     515  
     516    return 1;
     517  }
     518  
     519  void
     520  md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
     521  {
     522    fprintf (stream, _("FT32 options:\n"));
     523    fprintf (stream, _("\n\
     524  -no-relax		don't relax relocations\n\
     525  			\n"));
     526  }
     527  
     528  /* Convert from target byte order to host byte order.  */
     529  
     530  static valueT
     531  md_chars_to_number (char * buf, int n)
     532  {
     533    valueT result = 0;
     534    unsigned char * where = (unsigned char *) buf;
     535  
     536    while (n--)
     537      {
     538        result <<= 8;
     539        result |= (where[n] & 255);
     540      }
     541  
     542    return result;
     543  }
     544  
     545  /* Apply a fixup to the object file.  */
     546  
     547  void
     548  md_apply_fix (fixS *fixP ATTRIBUTE_UNUSED,
     549  	      valueT * valP ATTRIBUTE_UNUSED, segT seg ATTRIBUTE_UNUSED)
     550  {
     551    char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
     552    long val = *valP;
     553    long newval;
     554  
     555    if (linkrelax && fixP->fx_subsy)
     556      {
     557        /* For a subtraction relocation expression, generate one
     558           of the DIFF relocs, with the value being the difference.
     559           Note that a sym1 - sym2 expression is adjusted into a
     560           section_start_sym + sym4_offset_from_section_start - sym1
     561           expression. fixP->fx_addsy holds the section start symbol,
     562           fixP->fx_offset holds sym2's offset, and fixP->fx_subsy
     563           holds sym1. Calculate the current difference and write value,
     564           but leave fx_offset as is - during relaxation,
     565           fx_offset - value gives sym1's value.  */
     566  
     567         switch (fixP->fx_r_type)
     568           {
     569             case BFD_RELOC_32:
     570               fixP->fx_r_type = BFD_RELOC_FT32_DIFF32;
     571               break;
     572             default:
     573               as_bad_subtract (fixP);
     574               break;
     575           }
     576  
     577        val = S_GET_VALUE (fixP->fx_addsy) +
     578            fixP->fx_offset - S_GET_VALUE (fixP->fx_subsy);
     579        *valP = val;
     580  
     581        fixP->fx_subsy = NULL;
     582    }
     583  
     584    /* We don't actually support subtracting a symbol.  */
     585    if (fixP->fx_subsy != (symbolS *) NULL)
     586      as_bad_subtract (fixP);
     587  
     588    switch (fixP->fx_r_type)
     589      {
     590      case BFD_RELOC_FT32_DIFF32:
     591      case BFD_RELOC_32:
     592        buf[3] = val >> 24;
     593        buf[2] = val >> 16;
     594        buf[1] = val >> 8;
     595        buf[0] = val >> 0;
     596        break;
     597  
     598      case BFD_RELOC_16:
     599        buf[1] = val >> 8;
     600        buf[0] = val >> 0;
     601        break;
     602  
     603      case BFD_RELOC_8:
     604        *buf = val;
     605        break;
     606  
     607      case BFD_RELOC_FT32_10:
     608        if (!val)
     609  	break;
     610        newval = md_chars_to_number (buf, 2);
     611        newval |= (val & ((1 << 10) - 1)) << FT32_FLD_RIMM_BIT;
     612        md_number_to_chars (buf, newval, 2);
     613        break;
     614  
     615      case BFD_RELOC_FT32_20:
     616        if (!val)
     617  	break;
     618        newval = md_chars_to_number (buf, 3);
     619        newval |= val & ((1 << 20) - 1);
     620        md_number_to_chars (buf, newval, 3);
     621        break;
     622  
     623      case BFD_RELOC_FT32_15:
     624        if (!val)
     625  	break;
     626        newval = md_chars_to_number (buf, 2);
     627        newval |= val & ((1 << 15) - 1);
     628        md_number_to_chars (buf, newval, 2);
     629        break;
     630  
     631      case BFD_RELOC_FT32_17:
     632        if (!val)
     633  	break;
     634        newval = md_chars_to_number (buf, 3);
     635        newval |= val & ((1 << 17) - 1);
     636        md_number_to_chars (buf, newval, 3);
     637        break;
     638  
     639      case BFD_RELOC_FT32_18:
     640        if (!val)
     641  	break;
     642        newval = md_chars_to_number (buf, 4);
     643        newval |= (val >> 2) & ((1 << 18) - 1);
     644        md_number_to_chars (buf, newval, 4);
     645        break;
     646  
     647      case BFD_RELOC_FT32_RELAX:
     648        break;
     649  
     650      default:
     651        abort ();
     652      }
     653  
     654    if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
     655      fixP->fx_done = 1;
     656  }
     657  
     658  void
     659  md_number_to_chars (char *ptr, valueT use, int nbytes)
     660  {
     661    number_to_chars_littleendian (ptr, use, nbytes);
     662  }
     663  
     664  /* Generate a machine-dependent relocation.  */
     665  
     666  arelent *
     667  tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
     668  {
     669    arelent *relP;
     670    bfd_reloc_code_real_type code;
     671  
     672    switch (fixP->fx_r_type)
     673      {
     674      case BFD_RELOC_32:
     675      case BFD_RELOC_16:
     676      case BFD_RELOC_8:
     677      case BFD_RELOC_FT32_10:
     678      case BFD_RELOC_FT32_20:
     679      case BFD_RELOC_FT32_15:
     680      case BFD_RELOC_FT32_17:
     681      case BFD_RELOC_FT32_18:
     682      case BFD_RELOC_FT32_RELAX:
     683      case BFD_RELOC_FT32_DIFF32:
     684        code = fixP->fx_r_type;
     685        break;
     686      default:
     687        as_bad_where (fixP->fx_file, fixP->fx_line,
     688  		    _("Semantics error.  This type of operand can not be "
     689                        "relocated, it must be an assembly-time constant"));
     690        return NULL;
     691      }
     692  
     693    relP = XNEW (arelent);
     694    gas_assert (relP != 0);
     695    relP->sym_ptr_ptr = XNEW (asymbol *);
     696    *relP->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
     697    relP->address = fixP->fx_frag->fr_address + fixP->fx_where;
     698  
     699    relP->addend = fixP->fx_offset;
     700  
     701    relP->howto = bfd_reloc_type_lookup (stdoutput, code);
     702    if (! relP->howto)
     703      {
     704        const char *name;
     705  
     706        name = S_GET_NAME (fixP->fx_addsy);
     707        if (name == NULL)
     708  	name = _("<unknown>");
     709        as_fatal (_("Cannot generate relocation type for symbol %s, code %s"),
     710  		name, bfd_get_reloc_code_name (code));
     711      }
     712  
     713    return relP;
     714  }
     715  
     716  /* TC_FORCE_RELOCATION hook */
     717  
     718  static bool
     719  relaxable_section (asection *sec)
     720  {
     721    return ((sec->flags & SEC_DEBUGGING) == 0
     722            && (sec->flags & SEC_CODE) != 0
     723            && (sec->flags & SEC_ALLOC) != 0);
     724  }
     725  
     726  /* Does whatever the xtensa port does.  */
     727  
     728  int
     729  ft32_validate_fix_sub (fixS *fix)
     730  {
     731    segT add_symbol_segment, sub_symbol_segment;
     732  
     733    /* The difference of two symbols should be resolved by the assembler when
     734       linkrelax is not set.  If the linker may relax the section containing
     735       the symbols, then an Xtensa DIFF relocation must be generated so that
     736       the linker knows to adjust the difference value.  */
     737    if (!linkrelax || fix->fx_addsy == NULL)
     738      return 0;
     739  
     740    /* Make sure both symbols are in the same segment, and that segment is
     741       "normal" and relaxable.  If the segment is not "normal", then the
     742       fix is not valid.  If the segment is not "relaxable", then the fix
     743       should have been handled earlier.  */
     744    add_symbol_segment = S_GET_SEGMENT (fix->fx_addsy);
     745    if (! SEG_NORMAL (add_symbol_segment) ||
     746        ! relaxable_section (add_symbol_segment))
     747      return 0;
     748  
     749    sub_symbol_segment = S_GET_SEGMENT (fix->fx_subsy);
     750    return (sub_symbol_segment == add_symbol_segment);
     751  }
     752  
     753  /* TC_FORCE_RELOCATION hook */
     754  
     755  /* If linkrelax is turned on, and the symbol to relocate
     756     against is in a relaxable segment, don't compute the value -
     757     generate a relocation instead.  */
     758  
     759  int
     760  ft32_force_relocation (fixS *fix)
     761  {
     762    if (linkrelax && fix->fx_addsy
     763        && relaxable_section (S_GET_SEGMENT (fix->fx_addsy)))
     764      {
     765        return 1;
     766      }
     767  
     768    return generic_force_reloc (fix);
     769  }
     770  
     771  bool
     772  ft32_allow_local_subtract (expressionS * left,
     773  			   expressionS * right,
     774  			   segT section)
     775  {
     776    /* If we are not in relaxation mode, subtraction is OK.  */
     777    if (!linkrelax)
     778      return true;
     779  
     780    /* If the symbols are not in a code section then they are OK.  */
     781    if ((section->flags & SEC_CODE) == 0)
     782      return true;
     783  
     784    if (left->X_add_symbol == right->X_add_symbol)
     785      return true;
     786  
     787    /* We have to assume that there may be instructions between the
     788       two symbols and that relaxation may increase the distance between
     789       them.  */
     790    return false;
     791  }