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