2012-01-06 Tristan Gingold <gingold@adacore.com>
[binutils.git] / gas / config / tc-rl78.c
blob1d9fb2e6a4786c2459a16cc3eb7f4afe8ce12e91
1 /* tc-rl78.c -- Assembler for the Renesas RL78
2 Copyright 2011
3 Free Software Foundation, Inc.
5 This file is part of GAS, the GNU Assembler.
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.
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.
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. */
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"
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[] = "|";
43 const char EXP_CHARS[] = "eE";
44 const char FLT_CHARS[] = "dD";
46 /*------------------------------------------------------------------*/
48 char * rl78_lex_start;
49 char * rl78_lex_end;
51 typedef struct rl78_bytesT
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
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
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;
82 static rl78_bytesT rl78_bytes;
84 void
85 rl78_linkrelax_addr16 (void)
87 rl78_bytes.link_relax |= RL78_RELAXA_ADDR16;
90 void
91 rl78_linkrelax_branch (void)
93 rl78_bytes.link_relax |= RL78_RELAXA_BRA;
96 static void
97 rl78_fixup (expressionS exp, int offsetbits, int nbits, int type)
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 ++;
107 #define rl78_field_fixup(exp, offset, nbits, type) \
108 rl78_fixup (exp, offset + 8 * rl78_bytes.n_prefix), nbits, type)
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)
113 void
114 rl78_prefix (int p)
116 rl78_bytes.prefix[0] = p;
117 rl78_bytes.n_prefix = 1;
121 rl78_has_prefix ()
123 return rl78_bytes.n_prefix;
126 void
127 rl78_base1 (int b1)
129 rl78_bytes.base[0] = b1;
130 rl78_bytes.n_base = 1;
133 void
134 rl78_base2 (int b1, int b2)
136 rl78_bytes.base[0] = b1;
137 rl78_bytes.base[1] = b2;
138 rl78_bytes.n_base = 2;
141 void
142 rl78_base3 (int b1, int b2, int b3)
144 rl78_bytes.base[0] = b1;
145 rl78_bytes.base[1] = b2;
146 rl78_bytes.base[2] = b3;
147 rl78_bytes.n_base = 3;
150 void
151 rl78_base4 (int b1, int b2, int b3, int b4)
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;
160 #define F_PRECISION 2
162 void
163 rl78_op (expressionS exp, int nbytes, int type)
165 int v = 0;
167 if ((exp.X_op == O_constant || exp.X_op == O_big)
168 && type != RL78REL_PCREL)
170 if (exp.X_op == O_big && exp.X_add_number <= 0)
172 LITTLENUM_TYPE w[2];
173 char * ip = rl78_bytes.ops + rl78_bytes.n_ops;
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;
182 else
184 v = exp.X_add_number;
185 while (nbytes)
187 rl78_bytes.ops[rl78_bytes.n_ops++] =v & 0xff;
188 v >>= 8;
189 nbytes --;
193 else
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;
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:
207 - - - - - - - - - - - - - - - -
208 M X L */
210 void
211 rl78_field (int val, int pos, int sz)
213 int valm;
214 int bytep, bitp;
216 if (sz > 0)
218 if (val < 0 || val >= (1 << sz))
219 as_bad (_("Value %d doesn't fit in unsigned %d-bit field"), val, sz);
221 else
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);
228 /* This code points at 'M' in the above example. */
229 bytep = pos / 8;
230 bitp = pos % 8;
232 while (bitp + sz > 8)
234 int ssz = 8 - bitp;
235 int svalm;
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;
243 bitp = 0;
244 sz -= ssz;
245 bytep ++;
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;
253 /*------------------------------------------------------------------*/
255 enum options
257 OPTION_RELAX = OPTION_MD_BASE,
260 #define RL78_SHORTOPTS ""
261 const char * md_shortopts = RL78_SHORTOPTS;
263 /* Assembler options. */
264 struct option md_longopts[] =
266 {"relax", no_argument, NULL, OPTION_RELAX},
267 {NULL, no_argument, NULL, 0}
269 size_t md_longopts_size = sizeof (md_longopts);
272 md_parse_option (int c, char * arg ATTRIBUTE_UNUSED)
274 switch (c)
276 case OPTION_RELAX:
277 linkrelax = 1;
278 return 1;
281 return 0;
284 void
285 md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
290 static void
291 s_bss (int ignore ATTRIBUTE_UNUSED)
293 int temp;
295 temp = get_absolute_expression ();
296 subseg_set (bss_section, (subsegT) temp);
297 demand_empty_rest_of_line ();
300 /* The target specific pseudo-ops which we support. */
301 const pseudo_typeS md_pseudo_table[] =
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 },
310 /* End of list marker. */
311 { NULL, NULL, 0 }
314 void
315 md_begin (void)
319 void
320 rl78_md_end (void)
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)
328 number_to_chars_littleendian (buf, val, n);
331 static struct
333 char * fname;
334 int reloc;
336 reloc_functions[] =
338 { "lo16", BFD_RELOC_RL78_LO16 },
339 { "hi16", BFD_RELOC_RL78_HI16 },
340 { "hi8", BFD_RELOC_RL78_HI8 },
341 { 0, 0 }
344 void
345 md_operand (expressionS * exp ATTRIBUTE_UNUSED)
347 int reloc = 0;
348 int i;
350 for (i = 0; reloc_functions[i].fname; i++)
352 int flen = strlen (reloc_functions[i].fname);
354 if (input_line_pointer[0] == '%'
355 && strncasecmp (input_line_pointer + 1, reloc_functions[i].fname, flen) == 0
356 && input_line_pointer[flen + 1] == '(')
358 reloc = reloc_functions[i].reloc;
359 input_line_pointer += flen + 2;
360 break;
363 if (reloc == 0)
364 return;
366 expression (exp);
367 if (* input_line_pointer == ')')
368 input_line_pointer ++;
370 exp->X_md = reloc;
373 void
374 rl78_frag_init (fragS * fragP)
376 if (rl78_bytes.n_relax || rl78_bytes.link_relax)
378 fragP->tc_frag_data = malloc (sizeof (rl78_bytesT));
379 memcpy (fragP->tc_frag_data, & rl78_bytes, sizeof (rl78_bytesT));
381 else
382 fragP->tc_frag_data = 0;
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)
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)
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);
409 char *
410 md_atof (int type, char * litP, int * sizeP)
412 return ieee_md_atof (type, litP, sizeP, target_big_endian);
415 symbolS *
416 md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
418 return NULL;
421 #define APPEND(B, N_B) \
422 if (rl78_bytes.N_B) \
424 memcpy (bytes + idx, rl78_bytes.B, rl78_bytes.N_B); \
425 idx += rl78_bytes.N_B; \
429 void
430 md_assemble (char * str)
432 char * bytes;
433 fragS * frag_then = frag_now;
434 int idx = 0;
435 int i;
436 int rel;
437 expressionS *exp;
439 /*printf("\033[32mASM: %s\033[0m\n", str);*/
441 dwarf2_emit_insn (0);
443 memset (& rl78_bytes, 0, sizeof (rl78_bytes));
445 rl78_lex_init (str, str + strlen (str));
447 rl78_parse ();
449 /* This simplifies the relaxation code. */
450 if (rl78_bytes.link_relax)
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;
469 else
471 bytes = frag_more (rl78_bytes.n_prefix + rl78_bytes.n_base + rl78_bytes.n_ops);
472 frag_then = frag_now;
475 APPEND (prefix, n_prefix);
476 APPEND (base, n_base);
477 APPEND (ops, n_ops);
479 if (rl78_bytes.link_relax)
481 fixS * f;
483 f = fix_new (frag_then,
484 (char *) bytes - frag_then->fr_literal,
486 abs_section_sym,
487 rl78_bytes.link_relax | rl78_bytes.n_fixups,
489 BFD_RELOC_RL78_RELAX);
490 frag_then->tc_frag_data->link_relax_fixP = f;
493 for (i = 0; i < rl78_bytes.n_fixups; i ++)
495 /* index: [nbytes][type] */
496 static int reloc_map[5][4] =
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 },
504 fixS * f;
506 idx = rl78_bytes.fixups[i].offset / 8;
507 rel = reloc_map [rl78_bytes.fixups[i].nbits / 8][(int) rl78_bytes.fixups[i].type];
509 if (rl78_bytes.fixups[i].reloc)
510 rel = rl78_bytes.fixups[i].reloc;
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;
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;
528 void
529 rl78_cons_fix_new (fragS * frag,
530 int where,
531 int size,
532 expressionS * exp)
534 bfd_reloc_code_real_type type;
536 switch (size)
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;
555 if (exp->X_op == O_subtract && exp->X_op_symbol)
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;
563 fix_new_exp (frag, where, (int) size, exp, 0, type);
566 /* No relaxation just yet */
568 md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED, segT segment ATTRIBUTE_UNUSED)
570 return 0;
573 arelent **
574 tc_gen_reloc (asection * seg ATTRIBUTE_UNUSED, fixS * fixp)
576 static arelent * reloc[8];
577 int rp;
579 if (fixp->fx_r_type == BFD_RELOC_NONE)
581 reloc[0] = NULL;
582 return reloc;
585 if (fixp->fx_subsy
586 && S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
588 fixp->fx_offset -= S_GET_VALUE (fixp->fx_subsy);
589 fixp->fx_subsy = NULL;
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;
598 if (fixp->fx_r_type == BFD_RELOC_RL78_32_OP
599 && fixp->fx_subsy)
601 fixp->fx_r_type = BFD_RELOC_RL78_DIFF;
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)
617 rp = 1;
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)
624 case BFD_RELOC_RL78_DIFF:
625 SYM0 ();
626 OPSYM (symbol_get_bfdsym (fixp->fx_subsy));
627 OP(OP_SUBTRACT);
629 switch (fixp->fx_size)
631 case 1:
632 OP(ABS8);
633 break;
634 case 2:
635 OP (ABS16);
636 break;
637 case 4:
638 OP (ABS32);
639 break;
641 break;
643 case BFD_RELOC_RL78_NEG32:
644 SYM0 ();
645 OP (OP_NEG);
646 OP (ABS32);
647 break;
649 case BFD_RELOC_RL78_LO16:
650 SYM0 ();
651 OPIMM (0xffff);
652 OP (OP_AND);
653 OP (ABS16);
654 break;
656 case BFD_RELOC_RL78_HI16:
657 SYM0 ();
658 OPIMM (16);
659 OP (OP_SHRA);
660 OP (ABS16);
661 break;
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;
672 default:
673 reloc[0]->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
674 reloc[1] = NULL;
675 break;
678 return reloc;
682 rl78_validate_fix_sub (struct fix * f)
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;
696 long
697 md_pcrel_from_section (fixS * fixP, segT sec)
699 long rv;
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;
708 rv = fixP->fx_frag->fr_address + fixP->fx_where;
709 switch (fixP->fx_r_type)
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;
720 return rv;
723 void
724 md_apply_fix (struct fix * f ATTRIBUTE_UNUSED,
725 valueT * t ATTRIBUTE_UNUSED,
726 segT s ATTRIBUTE_UNUSED)
728 char * op;
729 unsigned long val;
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;
736 op = f->fx_frag->fr_literal + f->fx_where;
737 val = (unsigned long) * t;
739 switch (f->fx_r_type)
741 case BFD_RELOC_NONE:
742 break;
744 case BFD_RELOC_RL78_RELAX:
745 f->fx_done = 1;
746 break;
748 case BFD_RELOC_8:
749 case BFD_RELOC_8_PCREL:
750 op[0] = val;
751 break;
753 case BFD_RELOC_16:
754 case BFD_RELOC_16_PCREL:
755 op[0] = val;
756 op[1] = val >> 8;
757 break;
759 case BFD_RELOC_24:
760 op[0] = val;
761 op[1] = val >> 8;
762 op[2] = val >> 16;
763 break;
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;
773 default:
774 as_bad (_("Unknown reloc in md_apply_fix: %s"),
775 bfd_get_reloc_code_name (f->fx_r_type));
776 break;
779 if (f->fx_addsy == NULL)
780 f->fx_done = 1;
783 valueT
784 md_section_align (segT segment, valueT size)
786 int align = bfd_get_section_alignment (stdoutput, segment);
787 return ((size + (1 << align) - 1) & (-1 << align));
790 void
791 md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
792 segT segment ATTRIBUTE_UNUSED,
793 fragS * fragP ATTRIBUTE_UNUSED)
795 /* No relaxation yet */
796 fragP->fr_var = 0;