Home | History | Annotate | Line # | Download | only in config
tc-rl78.c revision 1.1
      1  1.1  christos /* tc-rl78.c -- Assembler for the Renesas RL78
      2  1.1  christos    Copyright 2011
      3  1.1  christos    Free Software Foundation, Inc.
      4  1.1  christos 
      5  1.1  christos    This file is part of GAS, the GNU Assembler.
      6  1.1  christos 
      7  1.1  christos    GAS is free software; you can redistribute it and/or modify
      8  1.1  christos    it under the terms of the GNU General Public License as published by
      9  1.1  christos    the Free Software Foundation; either version 3, or (at your option)
     10  1.1  christos    any later version.
     11  1.1  christos 
     12  1.1  christos    GAS is distributed in the hope that it will be useful,
     13  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15  1.1  christos    GNU General Public License for more details.
     16  1.1  christos 
     17  1.1  christos    You should have received a copy of the GNU General Public License
     18  1.1  christos    along with GAS; see the file COPYING.  If not, write to the Free
     19  1.1  christos    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
     20  1.1  christos    02110-1301, USA.  */
     21  1.1  christos 
     22  1.1  christos #include "as.h"
     23  1.1  christos #include "struc-symbol.h"
     24  1.1  christos #include "obstack.h"
     25  1.1  christos #include "safe-ctype.h"
     26  1.1  christos #include "dwarf2dbg.h"
     27  1.1  christos #include "libbfd.h"
     28  1.1  christos #include "elf/common.h"
     29  1.1  christos #include "elf/rl78.h"
     30  1.1  christos #include "rl78-defs.h"
     31  1.1  christos #include "filenames.h"
     32  1.1  christos #include "listing.h"
     33  1.1  christos #include "sb.h"
     34  1.1  christos #include "macro.h"
     35  1.1  christos 
     36  1.1  christos const char comment_chars[]        = ";";
     37  1.1  christos /* Note that input_file.c hand checks for '#' at the beginning of the
     38  1.1  christos    first line of the input file.  This is because the compiler outputs
     39  1.1  christos    #NO_APP at the beginning of its output.  */
     40  1.1  christos const char line_comment_chars[]   = "#";
     41  1.1  christos const char line_separator_chars[] = "|";
     42  1.1  christos 
     43  1.1  christos const char EXP_CHARS[]            = "eE";
     44  1.1  christos const char FLT_CHARS[]            = "dD";
     45  1.1  christos 
     46  1.1  christos /*------------------------------------------------------------------*/
     47  1.1  christos 
     48  1.1  christos char * rl78_lex_start;
     49  1.1  christos char * rl78_lex_end;
     50  1.1  christos 
     51  1.1  christos typedef struct rl78_bytesT
     52  1.1  christos {
     53  1.1  christos   char prefix[1];
     54  1.1  christos   int n_prefix;
     55  1.1  christos   char base[4];
     56  1.1  christos   int n_base;
     57  1.1  christos   char ops[8];
     58  1.1  christos   int n_ops;
     59  1.1  christos   struct
     60  1.1  christos   {
     61  1.1  christos     expressionS  exp;
     62  1.1  christos     char         offset;
     63  1.1  christos     char         nbits;
     64  1.1  christos     char         type; /* RL78REL_*.  */
     65  1.1  christos     int          reloc;
     66  1.1  christos     fixS *       fixP;
     67  1.1  christos   } fixups[2];
     68  1.1  christos   int n_fixups;
     69  1.1  christos   struct
     70  1.1  christos   {
     71  1.1  christos     char type;
     72  1.1  christos     char field_pos;
     73  1.1  christos     char val_ofs;
     74  1.1  christos   } relax[2];
     75  1.1  christos   int n_relax;
     76  1.1  christos   int link_relax;
     77  1.1  christos   fixS *link_relax_fixP;
     78  1.1  christos   char times_grown;
     79  1.1  christos   char times_shrank;
     80  1.1  christos } rl78_bytesT;
     81  1.1  christos 
     82  1.1  christos static rl78_bytesT rl78_bytes;
     83  1.1  christos 
     84  1.1  christos void
     85  1.1  christos rl78_linkrelax_addr16 (void)
     86  1.1  christos {
     87  1.1  christos   rl78_bytes.link_relax |= RL78_RELAXA_ADDR16;
     88  1.1  christos }
     89  1.1  christos 
     90  1.1  christos void
     91  1.1  christos rl78_linkrelax_branch (void)
     92  1.1  christos {
     93  1.1  christos   rl78_bytes.link_relax |= RL78_RELAXA_BRA;
     94  1.1  christos }
     95  1.1  christos 
     96  1.1  christos static void
     97  1.1  christos rl78_fixup (expressionS exp, int offsetbits, int nbits, int type)
     98  1.1  christos {
     99  1.1  christos   rl78_bytes.fixups[rl78_bytes.n_fixups].exp = exp;
    100  1.1  christos   rl78_bytes.fixups[rl78_bytes.n_fixups].offset = offsetbits;
    101  1.1  christos   rl78_bytes.fixups[rl78_bytes.n_fixups].nbits = nbits;
    102  1.1  christos   rl78_bytes.fixups[rl78_bytes.n_fixups].type = type;
    103  1.1  christos   rl78_bytes.fixups[rl78_bytes.n_fixups].reloc = exp.X_md;
    104  1.1  christos   rl78_bytes.n_fixups ++;
    105  1.1  christos }
    106  1.1  christos 
    107  1.1  christos #define rl78_field_fixup(exp, offset, nbits, type)	\
    108  1.1  christos   rl78_fixup (exp, offset + 8 * rl78_bytes.n_prefix), nbits, type)
    109  1.1  christos 
    110  1.1  christos #define rl78_op_fixup(exp, offset, nbits, type)		\
    111  1.1  christos   rl78_fixup (exp, offset + 8 * (rl78_bytes.n_prefix + rl78_bytes.n_base), nbits, type)
    112  1.1  christos 
    113  1.1  christos void
    114  1.1  christos rl78_prefix (int p)
    115  1.1  christos {
    116  1.1  christos   rl78_bytes.prefix[0] = p;
    117  1.1  christos   rl78_bytes.n_prefix = 1;
    118  1.1  christos }
    119  1.1  christos 
    120  1.1  christos int
    121  1.1  christos rl78_has_prefix ()
    122  1.1  christos {
    123  1.1  christos   return rl78_bytes.n_prefix;
    124  1.1  christos }
    125  1.1  christos 
    126  1.1  christos void
    127  1.1  christos rl78_base1 (int b1)
    128  1.1  christos {
    129  1.1  christos   rl78_bytes.base[0] = b1;
    130  1.1  christos   rl78_bytes.n_base = 1;
    131  1.1  christos }
    132  1.1  christos 
    133  1.1  christos void
    134  1.1  christos rl78_base2 (int b1, int b2)
    135  1.1  christos {
    136  1.1  christos   rl78_bytes.base[0] = b1;
    137  1.1  christos   rl78_bytes.base[1] = b2;
    138  1.1  christos   rl78_bytes.n_base = 2;
    139  1.1  christos }
    140  1.1  christos 
    141  1.1  christos void
    142  1.1  christos rl78_base3 (int b1, int b2, int b3)
    143  1.1  christos {
    144  1.1  christos   rl78_bytes.base[0] = b1;
    145  1.1  christos   rl78_bytes.base[1] = b2;
    146  1.1  christos   rl78_bytes.base[2] = b3;
    147  1.1  christos   rl78_bytes.n_base = 3;
    148  1.1  christos }
    149  1.1  christos 
    150  1.1  christos void
    151  1.1  christos rl78_base4 (int b1, int b2, int b3, int b4)
    152  1.1  christos {
    153  1.1  christos   rl78_bytes.base[0] = b1;
    154  1.1  christos   rl78_bytes.base[1] = b2;
    155  1.1  christos   rl78_bytes.base[2] = b3;
    156  1.1  christos   rl78_bytes.base[3] = b4;
    157  1.1  christos   rl78_bytes.n_base = 4;
    158  1.1  christos }
    159  1.1  christos 
    160  1.1  christos #define F_PRECISION 2
    161  1.1  christos 
    162  1.1  christos void
    163  1.1  christos rl78_op (expressionS exp, int nbytes, int type)
    164  1.1  christos {
    165  1.1  christos   int v = 0;
    166  1.1  christos 
    167  1.1  christos   if ((exp.X_op == O_constant || exp.X_op == O_big)
    168  1.1  christos       && type != RL78REL_PCREL)
    169  1.1  christos     {
    170  1.1  christos       if (exp.X_op == O_big && exp.X_add_number <= 0)
    171  1.1  christos 	{
    172  1.1  christos 	  LITTLENUM_TYPE w[2];
    173  1.1  christos 	  char * ip = rl78_bytes.ops + rl78_bytes.n_ops;
    174  1.1  christos 
    175  1.1  christos 	  gen_to_words (w, F_PRECISION, 8);
    176  1.1  christos 	  ip[3] = w[0] >> 8;
    177  1.1  christos 	  ip[2] = w[0];
    178  1.1  christos 	  ip[1] = w[1] >> 8;
    179  1.1  christos 	  ip[0] = w[1];
    180  1.1  christos 	  rl78_bytes.n_ops += 4;
    181  1.1  christos 	}
    182  1.1  christos       else
    183  1.1  christos 	{
    184  1.1  christos 	  v = exp.X_add_number;
    185  1.1  christos 	  while (nbytes)
    186  1.1  christos 	    {
    187  1.1  christos 	      rl78_bytes.ops[rl78_bytes.n_ops++] =v & 0xff;
    188  1.1  christos 	      v >>= 8;
    189  1.1  christos 	      nbytes --;
    190  1.1  christos 	    }
    191  1.1  christos 	}
    192  1.1  christos     }
    193  1.1  christos   else
    194  1.1  christos     {
    195  1.1  christos       rl78_op_fixup (exp, rl78_bytes.n_ops * 8, nbytes * 8, type);
    196  1.1  christos       memset (rl78_bytes.ops + rl78_bytes.n_ops, 0, nbytes);
    197  1.1  christos       rl78_bytes.n_ops += nbytes;
    198  1.1  christos     }
    199  1.1  christos }
    200  1.1  christos 
    201  1.1  christos /* This gets complicated when the field spans bytes, because fields
    202  1.1  christos    are numbered from the MSB of the first byte as zero, and bits are
    203  1.1  christos    stored LSB towards the LSB of the byte.  Thus, a simple four-bit
    204  1.1  christos    insertion of 12 at position 4 of 0x00 yields: 0x0b.  A three-bit
    205  1.1  christos    insertion of b'MXL at position 7 is like this:
    206  1.1  christos 
    207  1.1  christos      - - - -  - - - -   - - - -  - - - -
    208  1.1  christos                     M   X L               */
    209  1.1  christos 
    210  1.1  christos void
    211  1.1  christos rl78_field (int val, int pos, int sz)
    212  1.1  christos {
    213  1.1  christos   int valm;
    214  1.1  christos   int bytep, bitp;
    215  1.1  christos 
    216  1.1  christos   if (sz > 0)
    217  1.1  christos     {
    218  1.1  christos       if (val < 0 || val >= (1 << sz))
    219  1.1  christos 	as_bad (_("Value %d doesn't fit in unsigned %d-bit field"), val, sz);
    220  1.1  christos     }
    221  1.1  christos   else
    222  1.1  christos     {
    223  1.1  christos       sz = - sz;
    224  1.1  christos       if (val < -(1 << (sz - 1)) || val >= (1 << (sz - 1)))
    225  1.1  christos 	as_bad (_("Value %d doesn't fit in signed %d-bit field"), val, sz);
    226  1.1  christos     }
    227  1.1  christos 
    228  1.1  christos   /* This code points at 'M' in the above example.  */
    229  1.1  christos   bytep = pos / 8;
    230  1.1  christos   bitp = pos % 8;
    231  1.1  christos 
    232  1.1  christos   while (bitp + sz > 8)
    233  1.1  christos     {
    234  1.1  christos       int ssz = 8 - bitp;
    235  1.1  christos       int svalm;
    236  1.1  christos 
    237  1.1  christos       svalm = val >> (sz - ssz);
    238  1.1  christos       svalm = svalm & ((1 << ssz) - 1);
    239  1.1  christos       svalm = svalm << (8 - bitp - ssz);
    240  1.1  christos       gas_assert (bytep < rl78_bytes.n_base);
    241  1.1  christos       rl78_bytes.base[bytep] |= svalm;
    242  1.1  christos 
    243  1.1  christos       bitp = 0;
    244  1.1  christos       sz -= ssz;
    245  1.1  christos       bytep ++;
    246  1.1  christos     }
    247  1.1  christos   valm = val & ((1 << sz) - 1);
    248  1.1  christos   valm = valm << (8 - bitp - sz);
    249  1.1  christos   gas_assert (bytep < rl78_bytes.n_base);
    250  1.1  christos   rl78_bytes.base[bytep] |= valm;
    251  1.1  christos }
    252  1.1  christos 
    253  1.1  christos /*------------------------------------------------------------------*/
    254  1.1  christos 
    255  1.1  christos enum options
    256  1.1  christos {
    257  1.1  christos   OPTION_RELAX = OPTION_MD_BASE,
    258  1.1  christos };
    259  1.1  christos 
    260  1.1  christos #define RL78_SHORTOPTS ""
    261  1.1  christos const char * md_shortopts = RL78_SHORTOPTS;
    262  1.1  christos 
    263  1.1  christos /* Assembler options.  */
    264  1.1  christos struct option md_longopts[] =
    265  1.1  christos {
    266  1.1  christos   {"relax", no_argument, NULL, OPTION_RELAX},
    267  1.1  christos   {NULL, no_argument, NULL, 0}
    268  1.1  christos };
    269  1.1  christos size_t md_longopts_size = sizeof (md_longopts);
    270  1.1  christos 
    271  1.1  christos int
    272  1.1  christos md_parse_option (int c, char * arg ATTRIBUTE_UNUSED)
    273  1.1  christos {
    274  1.1  christos   switch (c)
    275  1.1  christos     {
    276  1.1  christos     case OPTION_RELAX:
    277  1.1  christos       linkrelax = 1;
    278  1.1  christos       return 1;
    279  1.1  christos 
    280  1.1  christos     }
    281  1.1  christos   return 0;
    282  1.1  christos }
    283  1.1  christos 
    284  1.1  christos void
    285  1.1  christos md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
    286  1.1  christos {
    287  1.1  christos }
    288  1.1  christos 
    289  1.1  christos 
    290  1.1  christos static void
    291  1.1  christos s_bss (int ignore ATTRIBUTE_UNUSED)
    292  1.1  christos {
    293  1.1  christos   int temp;
    294  1.1  christos 
    295  1.1  christos   temp = get_absolute_expression ();
    296  1.1  christos   subseg_set (bss_section, (subsegT) temp);
    297  1.1  christos   demand_empty_rest_of_line ();
    298  1.1  christos }
    299  1.1  christos 
    300  1.1  christos /* The target specific pseudo-ops which we support.  */
    301  1.1  christos const pseudo_typeS md_pseudo_table[] =
    302  1.1  christos {
    303  1.1  christos   /* Our "standard" pseudos. */
    304  1.1  christos   { "double",   float_cons,    'd' },
    305  1.1  christos   { "bss",	s_bss, 		0 },
    306  1.1  christos   { "3byte",	cons,		3 },
    307  1.1  christos   { "int",	cons,		4 },
    308  1.1  christos   { "word",	cons,		4 },
    309  1.1  christos 
    310  1.1  christos   /* End of list marker.  */
    311  1.1  christos   { NULL, 	NULL, 		0 }
    312  1.1  christos };
    313  1.1  christos 
    314  1.1  christos void
    315  1.1  christos md_begin (void)
    316  1.1  christos {
    317  1.1  christos }
    318  1.1  christos 
    319  1.1  christos void
    320  1.1  christos rl78_md_end (void)
    321  1.1  christos {
    322  1.1  christos }
    323  1.1  christos 
    324  1.1  christos /* Write a value out to the object file, using the appropriate endianness.  */
    325  1.1  christos void
    326  1.1  christos md_number_to_chars (char * buf, valueT val, int n)
    327  1.1  christos {
    328  1.1  christos   number_to_chars_littleendian (buf, val, n);
    329  1.1  christos }
    330  1.1  christos 
    331  1.1  christos static struct
    332  1.1  christos {
    333  1.1  christos   char * fname;
    334  1.1  christos   int    reloc;
    335  1.1  christos }
    336  1.1  christos reloc_functions[] =
    337  1.1  christos {
    338  1.1  christos   { "lo16", BFD_RELOC_RL78_LO16 },
    339  1.1  christos   { "hi16", BFD_RELOC_RL78_HI16 },
    340  1.1  christos   { "hi8",  BFD_RELOC_RL78_HI8 },
    341  1.1  christos   { 0, 0 }
    342  1.1  christos };
    343  1.1  christos 
    344  1.1  christos void
    345  1.1  christos md_operand (expressionS * exp ATTRIBUTE_UNUSED)
    346  1.1  christos {
    347  1.1  christos   int reloc = 0;
    348  1.1  christos   int i;
    349  1.1  christos 
    350  1.1  christos   for (i = 0; reloc_functions[i].fname; i++)
    351  1.1  christos     {
    352  1.1  christos       int flen = strlen (reloc_functions[i].fname);
    353  1.1  christos 
    354  1.1  christos       if (input_line_pointer[0] == '%'
    355  1.1  christos 	  && strncasecmp (input_line_pointer + 1, reloc_functions[i].fname, flen) == 0
    356  1.1  christos 	  && input_line_pointer[flen + 1] == '(')
    357  1.1  christos 	{
    358  1.1  christos 	  reloc = reloc_functions[i].reloc;
    359  1.1  christos 	  input_line_pointer += flen + 2;
    360  1.1  christos 	  break;
    361  1.1  christos 	}
    362  1.1  christos     }
    363  1.1  christos   if (reloc == 0)
    364  1.1  christos     return;
    365  1.1  christos 
    366  1.1  christos   expression (exp);
    367  1.1  christos   if (* input_line_pointer == ')')
    368  1.1  christos     input_line_pointer ++;
    369  1.1  christos 
    370  1.1  christos   exp->X_md = reloc;
    371  1.1  christos }
    372  1.1  christos 
    373  1.1  christos void
    374  1.1  christos rl78_frag_init (fragS * fragP)
    375  1.1  christos {
    376  1.1  christos   if (rl78_bytes.n_relax || rl78_bytes.link_relax)
    377  1.1  christos     {
    378  1.1  christos       fragP->tc_frag_data = malloc (sizeof (rl78_bytesT));
    379  1.1  christos       memcpy (fragP->tc_frag_data, & rl78_bytes, sizeof (rl78_bytesT));
    380  1.1  christos     }
    381  1.1  christos   else
    382  1.1  christos     fragP->tc_frag_data = 0;
    383  1.1  christos }
    384  1.1  christos 
    385  1.1  christos /* When relaxing, we need to output a reloc for any .align directive
    386  1.1  christos    so that we can retain this alignment as we adjust opcode sizes.  */
    387  1.1  christos void
    388  1.1  christos rl78_handle_align (fragS * frag)
    389  1.1  christos {
    390  1.1  christos   if (linkrelax
    391  1.1  christos       && (frag->fr_type == rs_align
    392  1.1  christos 	  || frag->fr_type == rs_align_code)
    393  1.1  christos       && frag->fr_address + frag->fr_fix > 0
    394  1.1  christos       && frag->fr_offset > 0
    395  1.1  christos       && now_seg != bss_section)
    396  1.1  christos     {
    397  1.1  christos       fix_new (frag, frag->fr_fix, 0,
    398  1.1  christos 	       &abs_symbol, RL78_RELAXA_ALIGN + frag->fr_offset,
    399  1.1  christos 	       0, BFD_RELOC_RL78_RELAX);
    400  1.1  christos       /* For the purposes of relaxation, this relocation is attached
    401  1.1  christos 	 to the byte *after* the alignment - i.e. the byte that must
    402  1.1  christos 	 remain aligned.  */
    403  1.1  christos       fix_new (frag->fr_next, 0, 0,
    404  1.1  christos 	       &abs_symbol, RL78_RELAXA_ELIGN + frag->fr_offset,
    405  1.1  christos 	       0, BFD_RELOC_RL78_RELAX);
    406  1.1  christos     }
    407  1.1  christos }
    408  1.1  christos 
    409  1.1  christos char *
    410  1.1  christos md_atof (int type, char * litP, int * sizeP)
    411  1.1  christos {
    412  1.1  christos   return ieee_md_atof (type, litP, sizeP, target_big_endian);
    413  1.1  christos }
    414  1.1  christos 
    415  1.1  christos symbolS *
    416  1.1  christos md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
    417  1.1  christos {
    418  1.1  christos   return NULL;
    419  1.1  christos }
    420  1.1  christos 
    421  1.1  christos #define APPEND(B, N_B)				       \
    422  1.1  christos   if (rl78_bytes.N_B)				       \
    423  1.1  christos     {						       \
    424  1.1  christos       memcpy (bytes + idx, rl78_bytes.B, rl78_bytes.N_B);  \
    425  1.1  christos       idx += rl78_bytes.N_B;			       \
    426  1.1  christos     }
    427  1.1  christos 
    428  1.1  christos 
    429  1.1  christos void
    430  1.1  christos md_assemble (char * str)
    431  1.1  christos {
    432  1.1  christos   char * bytes;
    433  1.1  christos   fragS * frag_then = frag_now;
    434  1.1  christos   int idx = 0;
    435  1.1  christos   int i;
    436  1.1  christos   int rel;
    437  1.1  christos   expressionS  *exp;
    438  1.1  christos 
    439  1.1  christos   /*printf("\033[32mASM: %s\033[0m\n", str);*/
    440  1.1  christos 
    441  1.1  christos   dwarf2_emit_insn (0);
    442  1.1  christos 
    443  1.1  christos   memset (& rl78_bytes, 0, sizeof (rl78_bytes));
    444  1.1  christos 
    445  1.1  christos   rl78_lex_init (str, str + strlen (str));
    446  1.1  christos 
    447  1.1  christos   rl78_parse ();
    448  1.1  christos 
    449  1.1  christos   /* This simplifies the relaxation code.  */
    450  1.1  christos   if (rl78_bytes.link_relax)
    451  1.1  christos     {
    452  1.1  christos       int olen = rl78_bytes.n_prefix + rl78_bytes.n_base + rl78_bytes.n_ops;
    453  1.1  christos       /* We do it this way because we want the frag to have the
    454  1.1  christos 	 rl78_bytes in it, which we initialize above.  */
    455  1.1  christos       bytes = frag_more (olen);
    456  1.1  christos       frag_then = frag_now;
    457  1.1  christos       frag_variant (rs_machine_dependent,
    458  1.1  christos 		    olen /* max_chars */,
    459  1.1  christos 		    0 /* var */,
    460  1.1  christos 		    olen /* subtype */,
    461  1.1  christos 		    0 /* symbol */,
    462  1.1  christos 		    0 /* offset */,
    463  1.1  christos 		    0 /* opcode */);
    464  1.1  christos       frag_then->fr_opcode = bytes;
    465  1.1  christos       frag_then->fr_fix = olen + (bytes - frag_then->fr_literal);
    466  1.1  christos       frag_then->fr_subtype = olen;
    467  1.1  christos       frag_then->fr_var = 0;
    468  1.1  christos     }
    469  1.1  christos   else
    470  1.1  christos     {
    471  1.1  christos       bytes = frag_more (rl78_bytes.n_prefix + rl78_bytes.n_base + rl78_bytes.n_ops);
    472  1.1  christos       frag_then = frag_now;
    473  1.1  christos     }
    474  1.1  christos 
    475  1.1  christos   APPEND (prefix, n_prefix);
    476  1.1  christos   APPEND (base, n_base);
    477  1.1  christos   APPEND (ops, n_ops);
    478  1.1  christos 
    479  1.1  christos   if (rl78_bytes.link_relax)
    480  1.1  christos     {
    481  1.1  christos       fixS * f;
    482  1.1  christos 
    483  1.1  christos       f = fix_new (frag_then,
    484  1.1  christos 		   (char *) bytes - frag_then->fr_literal,
    485  1.1  christos 		   0,
    486  1.1  christos 		   abs_section_sym,
    487  1.1  christos 		   rl78_bytes.link_relax | rl78_bytes.n_fixups,
    488  1.1  christos 		   0,
    489  1.1  christos 		   BFD_RELOC_RL78_RELAX);
    490  1.1  christos       frag_then->tc_frag_data->link_relax_fixP = f;
    491  1.1  christos     }
    492  1.1  christos 
    493  1.1  christos   for (i = 0; i < rl78_bytes.n_fixups; i ++)
    494  1.1  christos     {
    495  1.1  christos       /* index: [nbytes][type] */
    496  1.1  christos       static int reloc_map[5][4] =
    497  1.1  christos 	{
    498  1.1  christos 	  { 0,            0 },
    499  1.1  christos 	  { BFD_RELOC_8,  BFD_RELOC_8_PCREL },
    500  1.1  christos 	  { BFD_RELOC_16, BFD_RELOC_16_PCREL },
    501  1.1  christos 	  { BFD_RELOC_24, BFD_RELOC_24_PCREL },
    502  1.1  christos 	  { BFD_RELOC_32, BFD_RELOC_32_PCREL },
    503  1.1  christos 	};
    504  1.1  christos       fixS * f;
    505  1.1  christos 
    506  1.1  christos       idx = rl78_bytes.fixups[i].offset / 8;
    507  1.1  christos       rel = reloc_map [rl78_bytes.fixups[i].nbits / 8][(int) rl78_bytes.fixups[i].type];
    508  1.1  christos 
    509  1.1  christos       if (rl78_bytes.fixups[i].reloc)
    510  1.1  christos 	rel = rl78_bytes.fixups[i].reloc;
    511  1.1  christos 
    512  1.1  christos       if (frag_then->tc_frag_data)
    513  1.1  christos 	exp = & frag_then->tc_frag_data->fixups[i].exp;
    514  1.1  christos       else
    515  1.1  christos 	exp = & rl78_bytes.fixups[i].exp;
    516  1.1  christos 
    517  1.1  christos       f = fix_new_exp (frag_then,
    518  1.1  christos 		       (char *) bytes + idx - frag_then->fr_literal,
    519  1.1  christos 		       rl78_bytes.fixups[i].nbits / 8,
    520  1.1  christos 		       exp,
    521  1.1  christos 		       rl78_bytes.fixups[i].type == RL78REL_PCREL ? 1 : 0,
    522  1.1  christos 		       rel);
    523  1.1  christos       if (frag_then->tc_frag_data)
    524  1.1  christos 	frag_then->tc_frag_data->fixups[i].fixP = f;
    525  1.1  christos     }
    526  1.1  christos }
    527  1.1  christos 
    528  1.1  christos void
    529  1.1  christos rl78_cons_fix_new (fragS *	frag,
    530  1.1  christos 		 int		where,
    531  1.1  christos 		 int		size,
    532  1.1  christos 		 expressionS *  exp)
    533  1.1  christos {
    534  1.1  christos   bfd_reloc_code_real_type type;
    535  1.1  christos 
    536  1.1  christos   switch (size)
    537  1.1  christos     {
    538  1.1  christos     case 1:
    539  1.1  christos       type = BFD_RELOC_8;
    540  1.1  christos       break;
    541  1.1  christos     case 2:
    542  1.1  christos       type = BFD_RELOC_16;
    543  1.1  christos       break;
    544  1.1  christos     case 3:
    545  1.1  christos       type = BFD_RELOC_24;
    546  1.1  christos       break;
    547  1.1  christos     case 4:
    548  1.1  christos       type = BFD_RELOC_32;
    549  1.1  christos       break;
    550  1.1  christos     default:
    551  1.1  christos       as_bad (_("unsupported constant size %d\n"), size);
    552  1.1  christos       return;
    553  1.1  christos     }
    554  1.1  christos 
    555  1.1  christos   if (exp->X_op == O_subtract && exp->X_op_symbol)
    556  1.1  christos     {
    557  1.1  christos       if (size != 4 && size != 2 && size != 1)
    558  1.1  christos 	as_bad (_("difference of two symbols only supported with .long, .short, or .byte"));
    559  1.1  christos       else
    560  1.1  christos 	type = BFD_RELOC_RL78_DIFF;
    561  1.1  christos     }
    562  1.1  christos 
    563  1.1  christos   fix_new_exp (frag, where, (int) size, exp, 0, type);
    564  1.1  christos }
    565  1.1  christos 
    566  1.1  christos /* No relaxation just yet */
    567  1.1  christos int
    568  1.1  christos md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED, segT segment ATTRIBUTE_UNUSED)
    569  1.1  christos {
    570  1.1  christos   return 0;
    571  1.1  christos }
    572  1.1  christos 
    573  1.1  christos arelent **
    574  1.1  christos tc_gen_reloc (asection * seg ATTRIBUTE_UNUSED, fixS * fixp)
    575  1.1  christos {
    576  1.1  christos   static arelent * reloc[8];
    577  1.1  christos   int rp;
    578  1.1  christos 
    579  1.1  christos   if (fixp->fx_r_type == BFD_RELOC_NONE)
    580  1.1  christos     {
    581  1.1  christos       reloc[0] = NULL;
    582  1.1  christos       return reloc;
    583  1.1  christos     }
    584  1.1  christos 
    585  1.1  christos   if (fixp->fx_subsy
    586  1.1  christos       && S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
    587  1.1  christos     {
    588  1.1  christos       fixp->fx_offset -= S_GET_VALUE (fixp->fx_subsy);
    589  1.1  christos       fixp->fx_subsy = NULL;
    590  1.1  christos     }
    591  1.1  christos 
    592  1.1  christos   reloc[0]		  = (arelent *) xmalloc (sizeof (arelent));
    593  1.1  christos   reloc[0]->sym_ptr_ptr   = (asymbol **) xmalloc (sizeof (asymbol *));
    594  1.1  christos   * reloc[0]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
    595  1.1  christos   reloc[0]->address       = fixp->fx_frag->fr_address + fixp->fx_where;
    596  1.1  christos   reloc[0]->addend        = fixp->fx_offset;
    597  1.1  christos 
    598  1.1  christos   if (fixp->fx_r_type == BFD_RELOC_RL78_32_OP
    599  1.1  christos       && fixp->fx_subsy)
    600  1.1  christos     {
    601  1.1  christos       fixp->fx_r_type = BFD_RELOC_RL78_DIFF;
    602  1.1  christos     }
    603  1.1  christos 
    604  1.1  christos #define OPX(REL,SYM,ADD)							\
    605  1.1  christos   reloc[rp]		   = (arelent *) xmalloc (sizeof (arelent));		\
    606  1.1  christos   reloc[rp]->sym_ptr_ptr   = (asymbol **) xmalloc (sizeof (asymbol *));		\
    607  1.1  christos   reloc[rp]->howto         = bfd_reloc_type_lookup (stdoutput, REL);		\
    608  1.1  christos   reloc[rp]->addend        = ADD;						\
    609  1.1  christos   * reloc[rp]->sym_ptr_ptr = SYM;						\
    610  1.1  christos   reloc[rp]->address       = fixp->fx_frag->fr_address + fixp->fx_where;	\
    611  1.1  christos   reloc[++rp] = NULL
    612  1.1  christos #define OPSYM(SYM) OPX(BFD_RELOC_RL78_SYM, SYM, 0)
    613  1.1  christos #define OPIMM(IMM) OPX(BFD_RELOC_RL78_SYM, abs_symbol.bsym, IMM)
    614  1.1  christos #define OP(OP) OPX(BFD_RELOC_RL78_##OP, *reloc[0]->sym_ptr_ptr, 0)
    615  1.1  christos #define SYM0() reloc[0]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_RL78_SYM)
    616  1.1  christos 
    617  1.1  christos   rp = 1;
    618  1.1  christos 
    619  1.1  christos   /* Certain BFD relocations cannot be translated directly into
    620  1.1  christos      a single (non-Red Hat) RL78 relocation, but instead need
    621  1.1  christos      multiple RL78 relocations - handle them here.  */
    622  1.1  christos   switch (fixp->fx_r_type)
    623  1.1  christos     {
    624  1.1  christos     case BFD_RELOC_RL78_DIFF:
    625  1.1  christos       SYM0 ();
    626  1.1  christos       OPSYM (symbol_get_bfdsym (fixp->fx_subsy));
    627  1.1  christos       OP(OP_SUBTRACT);
    628  1.1  christos 
    629  1.1  christos       switch (fixp->fx_size)
    630  1.1  christos 	{
    631  1.1  christos 	case 1:
    632  1.1  christos 	  OP(ABS8);
    633  1.1  christos 	  break;
    634  1.1  christos 	case 2:
    635  1.1  christos 	  OP (ABS16);
    636  1.1  christos 	  break;
    637  1.1  christos 	case 4:
    638  1.1  christos 	  OP (ABS32);
    639  1.1  christos 	  break;
    640  1.1  christos 	}
    641  1.1  christos       break;
    642  1.1  christos 
    643  1.1  christos     case BFD_RELOC_RL78_NEG32:
    644  1.1  christos       SYM0 ();
    645  1.1  christos       OP (OP_NEG);
    646  1.1  christos       OP (ABS32);
    647  1.1  christos       break;
    648  1.1  christos 
    649  1.1  christos     case BFD_RELOC_RL78_LO16:
    650  1.1  christos       SYM0 ();
    651  1.1  christos       OPIMM (0xffff);
    652  1.1  christos       OP (OP_AND);
    653  1.1  christos       OP (ABS16);
    654  1.1  christos       break;
    655  1.1  christos 
    656  1.1  christos     case BFD_RELOC_RL78_HI16:
    657  1.1  christos       SYM0 ();
    658  1.1  christos       OPIMM (16);
    659  1.1  christos       OP (OP_SHRA);
    660  1.1  christos       OP (ABS16);
    661  1.1  christos       break;
    662  1.1  christos 
    663  1.1  christos     case BFD_RELOC_RL78_HI8:
    664  1.1  christos       SYM0 ();
    665  1.1  christos       OPIMM (16);
    666  1.1  christos       OP (OP_SHRA);
    667  1.1  christos       OPIMM (0xff);
    668  1.1  christos       OP (OP_AND);
    669  1.1  christos       OP (ABS8);
    670  1.1  christos       break;
    671  1.1  christos 
    672  1.1  christos     default:
    673  1.1  christos       reloc[0]->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
    674  1.1  christos       reloc[1] = NULL;
    675  1.1  christos       break;
    676  1.1  christos     }
    677  1.1  christos 
    678  1.1  christos   return reloc;
    679  1.1  christos }
    680  1.1  christos 
    681  1.1  christos int
    682  1.1  christos rl78_validate_fix_sub (struct fix * f)
    683  1.1  christos {
    684  1.1  christos   /* We permit the subtraction of two symbols in a few cases.  */
    685  1.1  christos   /* mov #sym1-sym2, R3 */
    686  1.1  christos   if (f->fx_r_type == BFD_RELOC_RL78_32_OP)
    687  1.1  christos     return 1;
    688  1.1  christos   /* .long sym1-sym2 */
    689  1.1  christos   if (f->fx_r_type == BFD_RELOC_RL78_DIFF
    690  1.1  christos       && ! f->fx_pcrel
    691  1.1  christos       && (f->fx_size == 4 || f->fx_size == 2 || f->fx_size == 1))
    692  1.1  christos     return 1;
    693  1.1  christos   return 0;
    694  1.1  christos }
    695  1.1  christos 
    696  1.1  christos long
    697  1.1  christos md_pcrel_from_section (fixS * fixP, segT sec)
    698  1.1  christos {
    699  1.1  christos   long rv;
    700  1.1  christos 
    701  1.1  christos   if (fixP->fx_addsy != NULL
    702  1.1  christos       && (! S_IS_DEFINED (fixP->fx_addsy)
    703  1.1  christos 	  || S_GET_SEGMENT (fixP->fx_addsy) != sec))
    704  1.1  christos     /* The symbol is undefined (or is defined but not in this section).
    705  1.1  christos        Let the linker figure it out.  */
    706  1.1  christos     return 0;
    707  1.1  christos 
    708  1.1  christos   rv = fixP->fx_frag->fr_address + fixP->fx_where;
    709  1.1  christos   switch (fixP->fx_r_type)
    710  1.1  christos     {
    711  1.1  christos     case BFD_RELOC_8_PCREL:
    712  1.1  christos       rv += 1;
    713  1.1  christos       break;
    714  1.1  christos     case BFD_RELOC_16_PCREL:
    715  1.1  christos       rv += 2;
    716  1.1  christos       break;
    717  1.1  christos     default:
    718  1.1  christos       break;
    719  1.1  christos     }
    720  1.1  christos   return rv;
    721  1.1  christos }
    722  1.1  christos 
    723  1.1  christos void
    724  1.1  christos md_apply_fix (struct fix * f ATTRIBUTE_UNUSED,
    725  1.1  christos 	      valueT *     t ATTRIBUTE_UNUSED,
    726  1.1  christos 	      segT         s ATTRIBUTE_UNUSED)
    727  1.1  christos {
    728  1.1  christos   char * op;
    729  1.1  christos   unsigned long val;
    730  1.1  christos 
    731  1.1  christos   if (f->fx_addsy && S_FORCE_RELOC (f->fx_addsy, 1))
    732  1.1  christos     return;
    733  1.1  christos   if (f->fx_subsy && S_FORCE_RELOC (f->fx_subsy, 1))
    734  1.1  christos     return;
    735  1.1  christos 
    736  1.1  christos   op = f->fx_frag->fr_literal + f->fx_where;
    737  1.1  christos   val = (unsigned long) * t;
    738  1.1  christos 
    739  1.1  christos   switch (f->fx_r_type)
    740  1.1  christos     {
    741  1.1  christos     case BFD_RELOC_NONE:
    742  1.1  christos       break;
    743  1.1  christos 
    744  1.1  christos     case BFD_RELOC_RL78_RELAX:
    745  1.1  christos       f->fx_done = 1;
    746  1.1  christos       break;
    747  1.1  christos 
    748  1.1  christos     case BFD_RELOC_8:
    749  1.1  christos     case BFD_RELOC_8_PCREL:
    750  1.1  christos       op[0] = val;
    751  1.1  christos       break;
    752  1.1  christos 
    753  1.1  christos     case BFD_RELOC_16:
    754  1.1  christos     case BFD_RELOC_16_PCREL:
    755  1.1  christos       op[0] = val;
    756  1.1  christos       op[1] = val >> 8;
    757  1.1  christos       break;
    758  1.1  christos 
    759  1.1  christos     case BFD_RELOC_24:
    760  1.1  christos       op[0] = val;
    761  1.1  christos       op[1] = val >> 8;
    762  1.1  christos       op[2] = val >> 16;
    763  1.1  christos       break;
    764  1.1  christos 
    765  1.1  christos     case BFD_RELOC_32:
    766  1.1  christos     case BFD_RELOC_RL78_DIFF:
    767  1.1  christos       op[0] = val;
    768  1.1  christos       op[1] = val >> 8;
    769  1.1  christos       op[2] = val >> 16;
    770  1.1  christos       op[3] = val >> 24;
    771  1.1  christos       break;
    772  1.1  christos 
    773  1.1  christos     default:
    774  1.1  christos       as_bad (_("Unknown reloc in md_apply_fix: %s"),
    775  1.1  christos 	      bfd_get_reloc_code_name (f->fx_r_type));
    776  1.1  christos       break;
    777  1.1  christos     }
    778  1.1  christos 
    779  1.1  christos   if (f->fx_addsy == NULL)
    780  1.1  christos     f->fx_done = 1;
    781  1.1  christos }
    782  1.1  christos 
    783  1.1  christos valueT
    784  1.1  christos md_section_align (segT segment, valueT size)
    785  1.1  christos {
    786  1.1  christos   int align = bfd_get_section_alignment (stdoutput, segment);
    787  1.1  christos   return ((size + (1 << align) - 1) & (-1 << align));
    788  1.1  christos }
    789  1.1  christos 
    790  1.1  christos void
    791  1.1  christos md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
    792  1.1  christos 		 segT    segment ATTRIBUTE_UNUSED,
    793  1.1  christos 		 fragS * fragP ATTRIBUTE_UNUSED)
    794  1.1  christos {
    795  1.1  christos   /* No relaxation yet */
    796  1.1  christos   fragP->fr_var = 0;
    797  1.1  christos }
    798