[bfd]
[deliverable/binutils-gdb.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 }
This page took 0.04602 seconds and 5 git commands to generate.