1 /* tc-rl78.c -- Assembler for the Renesas RL78
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)
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
23 #include "struc-symbol.h"
25 #include "safe-ctype.h"
26 #include "dwarf2dbg.h"
28 #include "elf/common.h"
30 #include "rl78-defs.h"
31 #include "filenames.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
;
51 typedef struct rl78_bytesT
64 char type
; /* RL78REL_*. */
77 fixS
*link_relax_fixP
;
82 static rl78_bytesT rl78_bytes
;
85 rl78_linkrelax_addr16 (void)
87 rl78_bytes
.link_relax
|= RL78_RELAXA_ADDR16
;
91 rl78_linkrelax_branch (void)
93 rl78_bytes
.link_relax
|= RL78_RELAXA_BRA
;
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)
116 rl78_bytes
.prefix
[0] = p
;
117 rl78_bytes
.n_prefix
= 1;
123 return rl78_bytes
.n_prefix
;
129 rl78_bytes
.base
[0] = b1
;
130 rl78_bytes
.n_base
= 1;
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;
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;
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
163 rl78_op (expressionS exp
, int nbytes
, int type
)
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)
173 char * ip
= rl78_bytes
.ops
+ rl78_bytes
.n_ops
;
175 gen_to_words (w
, F_PRECISION
, 8);
180 rl78_bytes
.n_ops
+= 4;
184 v
= exp
.X_add_number
;
187 rl78_bytes
.ops
[rl78_bytes
.n_ops
++] =v
& 0xff;
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 - - - - - - - - - - - - - - - -
211 rl78_field (int val
, int pos
, int sz
)
218 if (val
< 0 || val
>= (1 << sz
))
219 as_bad (_("Value %d doesn't fit in unsigned %d-bit field"), val
, 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. */
232 while (bitp
+ sz
> 8)
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
;
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 /*------------------------------------------------------------------*/
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
)
285 md_show_usage (FILE * stream ATTRIBUTE_UNUSED
)
291 s_bss (int ignore ATTRIBUTE_UNUSED
)
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' },
306 { "3byte", cons
, 3 },
310 /* End of list marker. */
324 /* Write a value out to the object file, using the appropriate endianness. */
326 md_number_to_chars (char * buf
, valueT val
, int n
)
328 number_to_chars_littleendian (buf
, val
, n
);
338 { "lo16", BFD_RELOC_RL78_LO16
},
339 { "hi16", BFD_RELOC_RL78_HI16
},
340 { "hi8", BFD_RELOC_RL78_HI8
},
345 md_operand (expressionS
* exp ATTRIBUTE_UNUSED
)
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;
367 if (* input_line_pointer
== ')')
368 input_line_pointer
++;
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
));
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. */
388 rl78_handle_align (fragS
* frag
)
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
403 fix_new (frag
->fr_next
, 0, 0,
404 &abs_symbol
, RL78_RELAXA_ELIGN
+ frag
->fr_offset
,
405 0, BFD_RELOC_RL78_RELAX
);
410 md_atof (int type
, char * litP
, int * sizeP
)
412 return ieee_md_atof (type
, litP
, sizeP
, target_big_endian
);
416 md_undefined_symbol (char * name ATTRIBUTE_UNUSED
)
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; \
430 md_assemble (char * str
)
433 fragS
* frag_then
= frag_now
;
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
));
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 */,
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;
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
);
479 if (rl78_bytes
.link_relax
)
483 f
= fix_new (frag_then
,
484 (char *) bytes
- frag_then
->fr_literal
,
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] =
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
},
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
;
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,
521 rl78_bytes
.fixups
[i
].type
== RL78REL_PCREL
? 1 : 0,
523 if (frag_then
->tc_frag_data
)
524 frag_then
->tc_frag_data
->fixups
[i
].fixP
= f
;
529 rl78_cons_fix_new (fragS
* frag
,
534 bfd_reloc_code_real_type type
;
551 as_bad (_("unsupported constant size %d\n"), size
);
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"));
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
)
574 tc_gen_reloc (asection
* seg ATTRIBUTE_UNUSED
, fixS
* fixp
)
576 static arelent
* reloc
[8];
579 if (fixp
->fx_r_type
== BFD_RELOC_NONE
)
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
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; \
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)
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
:
626 OPSYM (symbol_get_bfdsym (fixp
->fx_subsy
));
629 switch (fixp
->fx_size
)
643 case BFD_RELOC_RL78_NEG32
:
649 case BFD_RELOC_RL78_LO16
:
656 case BFD_RELOC_RL78_HI16
:
663 case BFD_RELOC_RL78_HI8
:
673 reloc
[0]->howto
= bfd_reloc_type_lookup (stdoutput
, fixp
->fx_r_type
);
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
)
688 /* .long sym1-sym2 */
689 if (f
->fx_r_type
== BFD_RELOC_RL78_DIFF
691 && (f
->fx_size
== 4 || f
->fx_size
== 2 || f
->fx_size
== 1))
697 md_pcrel_from_section (fixS
* fixP
, segT sec
)
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. */
708 rv
= fixP
->fx_frag
->fr_address
+ fixP
->fx_where
;
709 switch (fixP
->fx_r_type
)
711 case BFD_RELOC_8_PCREL
:
714 case BFD_RELOC_16_PCREL
:
724 md_apply_fix (struct fix
* f ATTRIBUTE_UNUSED
,
725 valueT
* t ATTRIBUTE_UNUSED
,
726 segT s ATTRIBUTE_UNUSED
)
731 if (f
->fx_addsy
&& S_FORCE_RELOC (f
->fx_addsy
, 1))
733 if (f
->fx_subsy
&& S_FORCE_RELOC (f
->fx_subsy
, 1))
736 op
= f
->fx_frag
->fr_literal
+ f
->fx_where
;
737 val
= (unsigned long) * t
;
739 switch (f
->fx_r_type
)
744 case BFD_RELOC_RL78_RELAX
:
749 case BFD_RELOC_8_PCREL
:
754 case BFD_RELOC_16_PCREL
:
766 case BFD_RELOC_RL78_DIFF
:
774 as_bad (_("Unknown reloc in md_apply_fix: %s"),
775 bfd_get_reloc_code_name (f
->fx_r_type
));
779 if (f
->fx_addsy
== NULL
)
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
));
791 md_convert_frag (bfd
* abfd ATTRIBUTE_UNUSED
,
792 segT segment ATTRIBUTE_UNUSED
,
793 fragS
* fragP ATTRIBUTE_UNUSED
)
795 /* No relaxation yet */