[.]
[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   int is_opcode = 0;
486
487   if (fixp->fx_r_type == BFD_RELOC_NONE)
488     {
489       reloc[0] = NULL;
490       return reloc;
491     }
492
493   if (fixp->fx_subsy
494       && S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
495     {
496       fixp->fx_offset -= S_GET_VALUE (fixp->fx_subsy);
497       fixp->fx_subsy = NULL;
498     }
499
500   reloc[0]                = (arelent *) xmalloc (sizeof (arelent));
501   reloc[0]->sym_ptr_ptr   = (asymbol **) xmalloc (sizeof (asymbol *));
502   * reloc[0]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
503   reloc[0]->address       = fixp->fx_frag->fr_address + fixp->fx_where;
504   reloc[0]->addend        = fixp->fx_offset;
505
506   if (fixp->fx_r_type == BFD_RELOC_RL78_32_OP
507       && fixp->fx_subsy)
508     {
509       fixp->fx_r_type = BFD_RELOC_RL78_DIFF;
510       is_opcode = 1;
511     }
512
513 #define OPX(REL,SYM,ADD)                                                        \
514   reloc[rp]                = (arelent *) xmalloc (sizeof (arelent));            \
515   reloc[rp]->sym_ptr_ptr   = (asymbol **) xmalloc (sizeof (asymbol *));         \
516   reloc[rp]->howto         = bfd_reloc_type_lookup (stdoutput, REL);            \
517   reloc[rp]->addend        = ADD;                                               \
518   * reloc[rp]->sym_ptr_ptr = SYM;                                               \
519   reloc[rp]->address       = fixp->fx_frag->fr_address + fixp->fx_where;        \
520   reloc[++rp] = NULL
521 #define OPSYM(SYM) OPX(BFD_RELOC_RL78_SYM, SYM, 0)
522 #define OPIMM(IMM) OPX(BFD_RELOC_RL78_SYM, abs_symbol.bsym, IMM)
523 #define OP(OP) OPX(BFD_RELOC_RL78_##OP, *reloc[0]->sym_ptr_ptr, 0)
524 #define SYM0() reloc[0]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_RL78_SYM)
525
526   rp = 1;
527
528   /* Certain BFD relocations cannot be translated directly into
529      a single (non-Red Hat) RL78 relocation, but instead need
530      multiple RL78 relocations - handle them here.  */
531   switch (fixp->fx_r_type)
532     {
533     case BFD_RELOC_RL78_DIFF:
534       SYM0 ();
535       OPSYM (symbol_get_bfdsym (fixp->fx_subsy));
536       OP(OP_SUBTRACT);
537
538       switch (fixp->fx_size)
539         {
540         case 1:
541           OP(ABS8);
542           break;
543         case 2:
544           OP (ABS16);
545           break;
546         case 4:
547           OP (ABS32);
548           break;
549         }
550       break;
551
552     case BFD_RELOC_RL78_NEG32:
553       SYM0 ();
554       OP (OP_NEG);
555       OP (ABS32);
556       break;
557
558     case BFD_RELOC_RL78_LO16:
559       SYM0 ();
560       OPIMM (0xffff);
561       OP (OP_AND);
562       OP (ABS16);
563       break;
564
565     case BFD_RELOC_RL78_HI16:
566       SYM0 ();
567       OPIMM (16);
568       OP (OP_SHRA);
569       OP (ABS16);
570       break;
571
572     case BFD_RELOC_RL78_HI8:
573       SYM0 ();
574       OPIMM (16);
575       OP (OP_SHRA);
576       OPIMM (0xff);
577       OP (OP_AND);
578       OP (ABS8);
579       break;
580
581     default:
582       reloc[0]->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
583       reloc[1] = NULL;
584       break;
585     }
586
587   return reloc;
588 }
589
590 int
591 rl78_validate_fix_sub (struct fix * f)
592 {
593   /* We permit the subtraction of two symbols in a few cases.  */
594   /* mov #sym1-sym2, R3 */
595   if (f->fx_r_type == BFD_RELOC_RL78_32_OP)
596     return 1;
597   /* .long sym1-sym2 */
598   if (f->fx_r_type == BFD_RELOC_RL78_DIFF
599       && ! f->fx_pcrel
600       && (f->fx_size == 4 || f->fx_size == 2 || f->fx_size == 1))
601     return 1;
602   return 0;
603 }
604
605 long
606 md_pcrel_from_section (fixS * fixP, segT sec)
607 {
608   long rv;
609
610   if (fixP->fx_addsy != NULL
611       && (! S_IS_DEFINED (fixP->fx_addsy)
612           || S_GET_SEGMENT (fixP->fx_addsy) != sec))
613     /* The symbol is undefined (or is defined but not in this section).
614        Let the linker figure it out.  */
615     return 0;
616
617   rv = fixP->fx_frag->fr_address + fixP->fx_where;
618   switch (fixP->fx_r_type)
619     {
620     case BFD_RELOC_8_PCREL:
621       rv += 1;
622       break;
623     case BFD_RELOC_16_PCREL:
624       rv += 2;
625       break;
626     default:
627       break;
628     }
629   return rv;
630 }
631
632 void
633 md_apply_fix (struct fix * f ATTRIBUTE_UNUSED,
634               valueT *     t ATTRIBUTE_UNUSED,
635               segT         s ATTRIBUTE_UNUSED)
636 {
637   char * op;
638   unsigned long val;
639
640   if (f->fx_addsy && S_FORCE_RELOC (f->fx_addsy, 1))
641     return;
642   if (f->fx_subsy && S_FORCE_RELOC (f->fx_subsy, 1))
643     return;
644
645   op = f->fx_frag->fr_literal + f->fx_where;
646   val = (unsigned long) * t;
647
648   switch (f->fx_r_type)
649     {
650     case BFD_RELOC_NONE:
651       break;
652
653     case BFD_RELOC_8:
654     case BFD_RELOC_8_PCREL:
655       op[0] = val;
656       break;
657
658     case BFD_RELOC_16:
659     case BFD_RELOC_16_PCREL:
660       op[0] = val;
661       op[1] = val >> 8;
662       break;
663
664     case BFD_RELOC_24:
665       op[0] = val;
666       op[1] = val >> 8;
667       op[2] = val >> 16;
668       break;
669
670     case BFD_RELOC_32:
671     case BFD_RELOC_RL78_DIFF:
672       op[0] = val;
673       op[1] = val >> 8;
674       op[2] = val >> 16;
675       op[3] = val >> 24;
676       break;
677
678     default:
679       as_bad (_("Unknown reloc in md_apply_fix: %s"),
680               bfd_get_reloc_code_name (f->fx_r_type));
681       break;
682     }
683
684   if (f->fx_addsy == NULL)
685     f->fx_done = 1;
686 }
687
688 valueT
689 md_section_align (segT segment, valueT size)
690 {
691   int align = bfd_get_section_alignment (stdoutput, segment);
692   return ((size + (1 << align) - 1) & (-1 << align));
693 }
694
695 void
696 md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
697                  segT    segment ATTRIBUTE_UNUSED,
698                  fragS * fragP ATTRIBUTE_UNUSED)
699 {
700   /* No relaxation yet */
701 }