[bfd]
[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 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 static void
85 rl78_fixup (expressionS exp, int offsetbits, int nbits, int type)
86 {
87   rl78_bytes.fixups[rl78_bytes.n_fixups].exp = exp;
88   rl78_bytes.fixups[rl78_bytes.n_fixups].offset = offsetbits;
89   rl78_bytes.fixups[rl78_bytes.n_fixups].nbits = nbits;
90   rl78_bytes.fixups[rl78_bytes.n_fixups].type = type;
91   rl78_bytes.fixups[rl78_bytes.n_fixups].reloc = exp.X_md;
92   rl78_bytes.n_fixups ++;
93 }
94
95 #define rl78_field_fixup(exp, offset, nbits, type)      \
96   rl78_fixup (exp, offset + 8 * rl78_bytes.n_prefix), nbits, type)
97
98 #define rl78_op_fixup(exp, offset, nbits, type)         \
99   rl78_fixup (exp, offset + 8 * (rl78_bytes.n_prefix + rl78_bytes.n_base), nbits, type)
100
101 void
102 rl78_prefix (int p)
103 {
104   rl78_bytes.prefix[0] = p;
105   rl78_bytes.n_prefix = 1;
106 }
107
108 int
109 rl78_has_prefix ()
110 {
111   return rl78_bytes.n_prefix;
112 }
113
114 void
115 rl78_base1 (int b1)
116 {
117   rl78_bytes.base[0] = b1;
118   rl78_bytes.n_base = 1;
119 }
120
121 void
122 rl78_base2 (int b1, int b2)
123 {
124   rl78_bytes.base[0] = b1;
125   rl78_bytes.base[1] = b2;
126   rl78_bytes.n_base = 2;
127 }
128
129 void
130 rl78_base3 (int b1, int b2, int b3)
131 {
132   rl78_bytes.base[0] = b1;
133   rl78_bytes.base[1] = b2;
134   rl78_bytes.base[2] = b3;
135   rl78_bytes.n_base = 3;
136 }
137
138 void
139 rl78_base4 (int b1, int b2, int b3, int b4)
140 {
141   rl78_bytes.base[0] = b1;
142   rl78_bytes.base[1] = b2;
143   rl78_bytes.base[2] = b3;
144   rl78_bytes.base[3] = b4;
145   rl78_bytes.n_base = 4;
146 }
147
148 #define F_PRECISION 2
149
150 void
151 rl78_op (expressionS exp, int nbytes, int type)
152 {
153   int v = 0;
154
155   if ((exp.X_op == O_constant || exp.X_op == O_big)
156       && type != RL78REL_PCREL)
157     {
158       if (exp.X_op == O_big && exp.X_add_number <= 0)
159         {
160           LITTLENUM_TYPE w[2];
161           char * ip = rl78_bytes.ops + rl78_bytes.n_ops;
162
163           gen_to_words (w, F_PRECISION, 8);
164           ip[3] = w[0] >> 8;
165           ip[2] = w[0];
166           ip[1] = w[1] >> 8;
167           ip[0] = w[1];
168           rl78_bytes.n_ops += 4;
169         }
170       else
171         {
172           v = exp.X_add_number;
173           while (nbytes)
174             {
175               rl78_bytes.ops[rl78_bytes.n_ops++] =v & 0xff;
176               v >>= 8;
177               nbytes --;
178             }
179         }
180     }
181   else
182     {
183       rl78_op_fixup (exp, rl78_bytes.n_ops * 8, nbytes * 8, type);
184       memset (rl78_bytes.ops + rl78_bytes.n_ops, 0, nbytes);
185       rl78_bytes.n_ops += nbytes;
186     }
187 }
188
189 /* This gets complicated when the field spans bytes, because fields
190    are numbered from the MSB of the first byte as zero, and bits are
191    stored LSB towards the LSB of the byte.  Thus, a simple four-bit
192    insertion of 12 at position 4 of 0x00 yields: 0x0b.  A three-bit
193    insertion of b'MXL at position 7 is like this:
194
195      - - - -  - - - -   - - - -  - - - -
196                     M   X L               */
197
198 void
199 rl78_field (int val, int pos, int sz)
200 {
201   int valm;
202   int bytep, bitp;
203
204   if (sz > 0)
205     {
206       if (val < 0 || val >= (1 << sz))
207         as_bad (_("Value %d doesn't fit in unsigned %d-bit field"), val, sz);
208     }
209   else
210     {
211       sz = - sz;
212       if (val < -(1 << (sz - 1)) || val >= (1 << (sz - 1)))
213         as_bad (_("Value %d doesn't fit in signed %d-bit field"), val, sz);
214     }
215
216   /* This code points at 'M' in the above example.  */
217   bytep = pos / 8;
218   bitp = pos % 8;
219
220   while (bitp + sz > 8)
221     {
222       int ssz = 8 - bitp;
223       int svalm;
224
225       svalm = val >> (sz - ssz);
226       svalm = svalm & ((1 << ssz) - 1);
227       svalm = svalm << (8 - bitp - ssz);
228       gas_assert (bytep < rl78_bytes.n_base);
229       rl78_bytes.base[bytep] |= svalm;
230
231       bitp = 0;
232       sz -= ssz;
233       bytep ++;
234     }
235   valm = val & ((1 << sz) - 1);
236   valm = valm << (8 - bitp - sz);
237   gas_assert (bytep < rl78_bytes.n_base);
238   rl78_bytes.base[bytep] |= valm;
239 }
240
241 /*------------------------------------------------------------------*/
242
243 #define RL78_SHORTOPTS ""
244 const char * md_shortopts = RL78_SHORTOPTS;
245
246 /* Assembler options.  */
247 struct option md_longopts[] =
248 {
249   {NULL, no_argument, NULL, 0}
250 };
251 size_t md_longopts_size = sizeof (md_longopts);
252
253 int
254 md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED)
255 {
256   return 0;
257 }
258
259 void
260 md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
261 {
262 }
263
264
265 static void
266 s_bss (int ignore ATTRIBUTE_UNUSED)
267 {
268   int temp;
269
270   temp = get_absolute_expression ();
271   subseg_set (bss_section, (subsegT) temp);
272   demand_empty_rest_of_line ();
273 }
274
275 /* The target specific pseudo-ops which we support.  */
276 const pseudo_typeS md_pseudo_table[] =
277 {
278   /* Our "standard" pseudos. */
279   { "double",   float_cons,    'd' },
280   { "bss",      s_bss,          0 },
281   { "3byte",    cons,           3 },
282   { "int",      cons,           4 },
283   { "word",     cons,           4 },
284
285   /* End of list marker.  */
286   { NULL,       NULL,           0 }
287 };
288
289 void
290 md_begin (void)
291 {
292 }
293
294 void
295 rl78_md_end (void)
296 {
297 }
298
299 /* Write a value out to the object file, using the appropriate endianness.  */
300 void
301 md_number_to_chars (char * buf, valueT val, int n)
302 {
303   number_to_chars_littleendian (buf, val, n);
304 }
305
306 static struct
307 {
308   char * fname;
309   int    reloc;
310 }
311 reloc_functions[] =
312 {
313   { "lo16", BFD_RELOC_RL78_LO16 },
314   { "hi16", BFD_RELOC_RL78_HI16 },
315   { "hi8",  BFD_RELOC_RL78_HI8 },
316   { 0, 0 }
317 };
318
319 void
320 md_operand (expressionS * exp ATTRIBUTE_UNUSED)
321 {
322   int reloc = 0;
323   int i;
324
325   for (i = 0; reloc_functions[i].fname; i++)
326     {
327       int flen = strlen (reloc_functions[i].fname);
328
329       if (input_line_pointer[0] == '%'
330           && strncasecmp (input_line_pointer + 1, reloc_functions[i].fname, flen) == 0
331           && input_line_pointer[flen + 1] == '(')
332         {
333           reloc = reloc_functions[i].reloc;
334           input_line_pointer += flen + 2;
335           break;
336         }
337     }
338   if (reloc == 0)
339     return;
340
341   expression (exp);
342   if (* input_line_pointer == ')')
343     input_line_pointer ++;
344
345   exp->X_md = reloc;
346 }
347
348 void
349 rl78_frag_init (fragS * fragP)
350 {
351   fragP->tc_frag_data = 0;
352 }
353
354 char *
355 md_atof (int type, char * litP, int * sizeP)
356 {
357   return ieee_md_atof (type, litP, sizeP, target_big_endian);
358 }
359
360 symbolS *
361 md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
362 {
363   return NULL;
364 }
365
366 #define APPEND(B, N_B)                                 \
367   if (rl78_bytes.N_B)                                  \
368     {                                                  \
369       memcpy (bytes + idx, rl78_bytes.B, rl78_bytes.N_B);  \
370       idx += rl78_bytes.N_B;                           \
371     }
372
373
374 void
375 md_assemble (char * str)
376 {
377   char * bytes;
378   fragS * frag_then = frag_now;
379   int idx = 0;
380   int i;
381   int rel;
382   expressionS  *exp;
383
384   /*printf("\033[32mASM: %s\033[0m\n", str);*/
385
386   dwarf2_emit_insn (0);
387
388   memset (& rl78_bytes, 0, sizeof (rl78_bytes));
389
390   rl78_lex_init (str, str + strlen (str));
391
392   rl78_parse ();
393
394   bytes = frag_more (rl78_bytes.n_prefix + rl78_bytes.n_base + rl78_bytes.n_ops);
395   frag_then = frag_now;
396
397   APPEND (prefix, n_prefix);
398   APPEND (base, n_base);
399   APPEND (ops, n_ops);
400
401   for (i = 0; i < rl78_bytes.n_fixups; i ++)
402     {
403       /* index: [nbytes][type] */
404       static int reloc_map[5][4] =
405         {
406           { 0,            0 },
407           { BFD_RELOC_8,  BFD_RELOC_8_PCREL },
408           { BFD_RELOC_16, BFD_RELOC_16_PCREL },
409           { BFD_RELOC_24, BFD_RELOC_24_PCREL },
410           { BFD_RELOC_32, BFD_RELOC_32_PCREL },
411         };
412       fixS * f;
413
414       idx = rl78_bytes.fixups[i].offset / 8;
415       rel = reloc_map [rl78_bytes.fixups[i].nbits / 8][(int) rl78_bytes.fixups[i].type];
416
417       if (rl78_bytes.fixups[i].reloc)
418         rel = rl78_bytes.fixups[i].reloc;
419
420       if (frag_then->tc_frag_data)
421         exp = & frag_then->tc_frag_data->fixups[i].exp;
422       else
423         exp = & rl78_bytes.fixups[i].exp;
424
425       f = fix_new_exp (frag_then,
426                        (char *) bytes + idx - frag_then->fr_literal,
427                        rl78_bytes.fixups[i].nbits / 8,
428                        exp,
429                        rl78_bytes.fixups[i].type == RL78REL_PCREL ? 1 : 0,
430                        rel);
431       if (frag_then->tc_frag_data)
432         frag_then->tc_frag_data->fixups[i].fixP = f;
433     }
434 }
435
436 void
437 rl78_cons_fix_new (fragS *      frag,
438                  int            where,
439                  int            size,
440                  expressionS *  exp)
441 {
442   bfd_reloc_code_real_type type;
443
444   switch (size)
445     {
446     case 1:
447       type = BFD_RELOC_8;
448       break;
449     case 2:
450       type = BFD_RELOC_16;
451       break;
452     case 3:
453       type = BFD_RELOC_24;
454       break;
455     case 4:
456       type = BFD_RELOC_32;
457       break;
458     default:
459       as_bad (_("unsupported constant size %d\n"), size);
460       return;
461     }
462
463   if (exp->X_op == O_subtract && exp->X_op_symbol)
464     {
465       if (size != 4 && size != 2 && size != 1)
466         as_bad (_("difference of two symbols only supported with .long, .short, or .byte"));
467       else
468         type = BFD_RELOC_RL78_DIFF;
469     }
470
471   fix_new_exp (frag, where, (int) size, exp, 0, type);
472 }
473
474 /* No relaxation just yet */
475 int
476 md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED, segT segment ATTRIBUTE_UNUSED)
477 {
478   return 0;
479 }
480 arelent **
481 tc_gen_reloc (asection * seg ATTRIBUTE_UNUSED, fixS * fixp)
482 {
483   static arelent * reloc[8];
484   int rp;
485
486   if (fixp->fx_r_type == BFD_RELOC_NONE)
487     {
488       reloc[0] = NULL;
489       return reloc;
490     }
491
492   if (fixp->fx_subsy
493       && S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
494     {
495       fixp->fx_offset -= S_GET_VALUE (fixp->fx_subsy);
496       fixp->fx_subsy = NULL;
497     }
498
499   reloc[0]                = (arelent *) xmalloc (sizeof (arelent));
500   reloc[0]->sym_ptr_ptr   = (asymbol **) xmalloc (sizeof (asymbol *));
501   * reloc[0]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
502   reloc[0]->address       = fixp->fx_frag->fr_address + fixp->fx_where;
503   reloc[0]->addend        = fixp->fx_offset;
504
505   if (fixp->fx_r_type == BFD_RELOC_RL78_32_OP
506       && fixp->fx_subsy)
507     {
508       fixp->fx_r_type = BFD_RELOC_RL78_DIFF;
509     }
510
511 #define OPX(REL,SYM,ADD)                                                        \
512   reloc[rp]                = (arelent *) xmalloc (sizeof (arelent));            \
513   reloc[rp]->sym_ptr_ptr   = (asymbol **) xmalloc (sizeof (asymbol *));         \
514   reloc[rp]->howto         = bfd_reloc_type_lookup (stdoutput, REL);            \
515   reloc[rp]->addend        = ADD;                                               \
516   * reloc[rp]->sym_ptr_ptr = SYM;                                               \
517   reloc[rp]->address       = fixp->fx_frag->fr_address + fixp->fx_where;        \
518   reloc[++rp] = NULL
519 #define OPSYM(SYM) OPX(BFD_RELOC_RL78_SYM, SYM, 0)
520 #define OPIMM(IMM) OPX(BFD_RELOC_RL78_SYM, abs_symbol.bsym, IMM)
521 #define OP(OP) OPX(BFD_RELOC_RL78_##OP, *reloc[0]->sym_ptr_ptr, 0)
522 #define SYM0() reloc[0]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_RL78_SYM)
523
524   rp = 1;
525
526   /* Certain BFD relocations cannot be translated directly into
527      a single (non-Red Hat) RL78 relocation, but instead need
528      multiple RL78 relocations - handle them here.  */
529   switch (fixp->fx_r_type)
530     {
531     case BFD_RELOC_RL78_DIFF:
532       SYM0 ();
533       OPSYM (symbol_get_bfdsym (fixp->fx_subsy));
534       OP(OP_SUBTRACT);
535
536       switch (fixp->fx_size)
537         {
538         case 1:
539           OP(ABS8);
540           break;
541         case 2:
542           OP (ABS16);
543           break;
544         case 4:
545           OP (ABS32);
546           break;
547         }
548       break;
549
550     case BFD_RELOC_RL78_NEG32:
551       SYM0 ();
552       OP (OP_NEG);
553       OP (ABS32);
554       break;
555
556     case BFD_RELOC_RL78_LO16:
557       SYM0 ();
558       OPIMM (0xffff);
559       OP (OP_AND);
560       OP (ABS16);
561       break;
562
563     case BFD_RELOC_RL78_HI16:
564       SYM0 ();
565       OPIMM (16);
566       OP (OP_SHRA);
567       OP (ABS16);
568       break;
569
570     case BFD_RELOC_RL78_HI8:
571       SYM0 ();
572       OPIMM (16);
573       OP (OP_SHRA);
574       OPIMM (0xff);
575       OP (OP_AND);
576       OP (ABS8);
577       break;
578
579     default:
580       reloc[0]->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
581       reloc[1] = NULL;
582       break;
583     }
584
585   return reloc;
586 }
587
588 int
589 rl78_validate_fix_sub (struct fix * f)
590 {
591   /* We permit the subtraction of two symbols in a few cases.  */
592   /* mov #sym1-sym2, R3 */
593   if (f->fx_r_type == BFD_RELOC_RL78_32_OP)
594     return 1;
595   /* .long sym1-sym2 */
596   if (f->fx_r_type == BFD_RELOC_RL78_DIFF
597       && ! f->fx_pcrel
598       && (f->fx_size == 4 || f->fx_size == 2 || f->fx_size == 1))
599     return 1;
600   return 0;
601 }
602
603 long
604 md_pcrel_from_section (fixS * fixP, segT sec)
605 {
606   long rv;
607
608   if (fixP->fx_addsy != NULL
609       && (! S_IS_DEFINED (fixP->fx_addsy)
610           || S_GET_SEGMENT (fixP->fx_addsy) != sec))
611     /* The symbol is undefined (or is defined but not in this section).
612        Let the linker figure it out.  */
613     return 0;
614
615   rv = fixP->fx_frag->fr_address + fixP->fx_where;
616   switch (fixP->fx_r_type)
617     {
618     case BFD_RELOC_8_PCREL:
619       rv += 1;
620       break;
621     case BFD_RELOC_16_PCREL:
622       rv += 2;
623       break;
624     default:
625       break;
626     }
627   return rv;
628 }
629
630 void
631 md_apply_fix (struct fix * f ATTRIBUTE_UNUSED,
632               valueT *     t ATTRIBUTE_UNUSED,
633               segT         s ATTRIBUTE_UNUSED)
634 {
635   char * op;
636   unsigned long val;
637
638   if (f->fx_addsy && S_FORCE_RELOC (f->fx_addsy, 1))
639     return;
640   if (f->fx_subsy && S_FORCE_RELOC (f->fx_subsy, 1))
641     return;
642
643   op = f->fx_frag->fr_literal + f->fx_where;
644   val = (unsigned long) * t;
645
646   switch (f->fx_r_type)
647     {
648     case BFD_RELOC_NONE:
649       break;
650
651     case BFD_RELOC_8:
652     case BFD_RELOC_8_PCREL:
653       op[0] = val;
654       break;
655
656     case BFD_RELOC_16:
657     case BFD_RELOC_16_PCREL:
658       op[0] = val;
659       op[1] = val >> 8;
660       break;
661
662     case BFD_RELOC_24:
663       op[0] = val;
664       op[1] = val >> 8;
665       op[2] = val >> 16;
666       break;
667
668     case BFD_RELOC_32:
669     case BFD_RELOC_RL78_DIFF:
670       op[0] = val;
671       op[1] = val >> 8;
672       op[2] = val >> 16;
673       op[3] = val >> 24;
674       break;
675
676     default:
677       as_bad (_("Unknown reloc in md_apply_fix: %s"),
678               bfd_get_reloc_code_name (f->fx_r_type));
679       break;
680     }
681
682   if (f->fx_addsy == NULL)
683     f->fx_done = 1;
684 }
685
686 valueT
687 md_section_align (segT segment, valueT size)
688 {
689   int align = bfd_get_section_alignment (stdoutput, segment);
690   return ((size + (1 << align) - 1) & (-1 << align));
691 }
692
693 void
694 md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
695                  segT    segment ATTRIBUTE_UNUSED,
696                  fragS * fragP ATTRIBUTE_UNUSED)
697 {
698   /* No relaxation yet */
699 }