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