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 /* Use something that isn't going to be needed by any expressions or
43 const char line_separator_chars
[] = "@";
45 const char EXP_CHARS
[] = "eE";
46 const char FLT_CHARS
[] = "dD";
48 /*------------------------------------------------------------------*/
50 char * rl78_lex_start
;
53 typedef struct rl78_bytesT
66 char type
; /* RL78REL_*. */
79 fixS
*link_relax_fixP
;
84 static rl78_bytesT rl78_bytes
;
87 rl78_linkrelax_addr16 (void)
89 rl78_bytes
.link_relax
|= RL78_RELAXA_ADDR16
;
93 rl78_linkrelax_branch (void)
95 rl78_bytes
.link_relax
|= RL78_RELAXA_BRA
;
99 rl78_fixup (expressionS exp
, int offsetbits
, int nbits
, int type
)
101 rl78_bytes
.fixups
[rl78_bytes
.n_fixups
].exp
= exp
;
102 rl78_bytes
.fixups
[rl78_bytes
.n_fixups
].offset
= offsetbits
;
103 rl78_bytes
.fixups
[rl78_bytes
.n_fixups
].nbits
= nbits
;
104 rl78_bytes
.fixups
[rl78_bytes
.n_fixups
].type
= type
;
105 rl78_bytes
.fixups
[rl78_bytes
.n_fixups
].reloc
= exp
.X_md
;
106 rl78_bytes
.n_fixups
++;
109 #define rl78_field_fixup(exp, offset, nbits, type) \
110 rl78_fixup (exp, offset + 8 * rl78_bytes.n_prefix), nbits, type)
112 #define rl78_op_fixup(exp, offset, nbits, type) \
113 rl78_fixup (exp, offset + 8 * (rl78_bytes.n_prefix + rl78_bytes.n_base), nbits, type)
118 rl78_bytes
.prefix
[0] = p
;
119 rl78_bytes
.n_prefix
= 1;
125 return rl78_bytes
.n_prefix
;
131 rl78_bytes
.base
[0] = b1
;
132 rl78_bytes
.n_base
= 1;
136 rl78_base2 (int b1
, int b2
)
138 rl78_bytes
.base
[0] = b1
;
139 rl78_bytes
.base
[1] = b2
;
140 rl78_bytes
.n_base
= 2;
144 rl78_base3 (int b1
, int b2
, int b3
)
146 rl78_bytes
.base
[0] = b1
;
147 rl78_bytes
.base
[1] = b2
;
148 rl78_bytes
.base
[2] = b3
;
149 rl78_bytes
.n_base
= 3;
153 rl78_base4 (int b1
, int b2
, int b3
, int b4
)
155 rl78_bytes
.base
[0] = b1
;
156 rl78_bytes
.base
[1] = b2
;
157 rl78_bytes
.base
[2] = b3
;
158 rl78_bytes
.base
[3] = b4
;
159 rl78_bytes
.n_base
= 4;
162 #define F_PRECISION 2
165 rl78_op (expressionS exp
, int nbytes
, int type
)
169 if ((exp
.X_op
== O_constant
|| exp
.X_op
== O_big
)
170 && type
!= RL78REL_PCREL
)
172 if (exp
.X_op
== O_big
&& exp
.X_add_number
<= 0)
175 char * ip
= rl78_bytes
.ops
+ rl78_bytes
.n_ops
;
177 gen_to_words (w
, F_PRECISION
, 8);
182 rl78_bytes
.n_ops
+= 4;
186 v
= exp
.X_add_number
;
189 rl78_bytes
.ops
[rl78_bytes
.n_ops
++] =v
& 0xff;
197 rl78_op_fixup (exp
, rl78_bytes
.n_ops
* 8, nbytes
* 8, type
);
198 memset (rl78_bytes
.ops
+ rl78_bytes
.n_ops
, 0, nbytes
);
199 rl78_bytes
.n_ops
+= nbytes
;
203 /* This gets complicated when the field spans bytes, because fields
204 are numbered from the MSB of the first byte as zero, and bits are
205 stored LSB towards the LSB of the byte. Thus, a simple four-bit
206 insertion of 12 at position 4 of 0x00 yields: 0x0b. A three-bit
207 insertion of b'MXL at position 7 is like this:
209 - - - - - - - - - - - - - - - -
213 rl78_field (int val
, int pos
, int sz
)
220 if (val
< 0 || val
>= (1 << sz
))
221 as_bad (_("Value %d doesn't fit in unsigned %d-bit field"), val
, sz
);
226 if (val
< -(1 << (sz
- 1)) || val
>= (1 << (sz
- 1)))
227 as_bad (_("Value %d doesn't fit in signed %d-bit field"), val
, sz
);
230 /* This code points at 'M' in the above example. */
234 while (bitp
+ sz
> 8)
239 svalm
= val
>> (sz
- ssz
);
240 svalm
= svalm
& ((1 << ssz
) - 1);
241 svalm
= svalm
<< (8 - bitp
- ssz
);
242 gas_assert (bytep
< rl78_bytes
.n_base
);
243 rl78_bytes
.base
[bytep
] |= svalm
;
249 valm
= val
& ((1 << sz
) - 1);
250 valm
= valm
<< (8 - bitp
- sz
);
251 gas_assert (bytep
< rl78_bytes
.n_base
);
252 rl78_bytes
.base
[bytep
] |= valm
;
255 /*------------------------------------------------------------------*/
259 OPTION_RELAX
= OPTION_MD_BASE
,
262 #define RL78_SHORTOPTS ""
263 const char * md_shortopts
= RL78_SHORTOPTS
;
265 /* Assembler options. */
266 struct option md_longopts
[] =
268 {"relax", no_argument
, NULL
, OPTION_RELAX
},
269 {NULL
, no_argument
, NULL
, 0}
271 size_t md_longopts_size
= sizeof (md_longopts
);
274 md_parse_option (int c
, char * arg ATTRIBUTE_UNUSED
)
287 md_show_usage (FILE * stream ATTRIBUTE_UNUSED
)
293 s_bss (int ignore ATTRIBUTE_UNUSED
)
297 temp
= get_absolute_expression ();
298 subseg_set (bss_section
, (subsegT
) temp
);
299 demand_empty_rest_of_line ();
302 /* The target specific pseudo-ops which we support. */
303 const pseudo_typeS md_pseudo_table
[] =
305 /* Our "standard" pseudos. */
306 { "double", float_cons
, 'd' },
308 { "3byte", cons
, 3 },
312 /* End of list marker. */
326 /* Write a value out to the object file, using the appropriate endianness. */
328 md_number_to_chars (char * buf
, valueT val
, int n
)
330 number_to_chars_littleendian (buf
, val
, n
);
340 { "lo16", BFD_RELOC_RL78_LO16
},
341 { "hi16", BFD_RELOC_RL78_HI16
},
342 { "hi8", BFD_RELOC_RL78_HI8
},
347 md_operand (expressionS
* exp ATTRIBUTE_UNUSED
)
352 for (i
= 0; reloc_functions
[i
].fname
; i
++)
354 int flen
= strlen (reloc_functions
[i
].fname
);
356 if (input_line_pointer
[0] == '%'
357 && strncasecmp (input_line_pointer
+ 1, reloc_functions
[i
].fname
, flen
) == 0
358 && input_line_pointer
[flen
+ 1] == '(')
360 reloc
= reloc_functions
[i
].reloc
;
361 input_line_pointer
+= flen
+ 2;
369 if (* input_line_pointer
== ')')
370 input_line_pointer
++;
376 rl78_frag_init (fragS
* fragP
)
378 if (rl78_bytes
.n_relax
|| rl78_bytes
.link_relax
)
380 fragP
->tc_frag_data
= malloc (sizeof (rl78_bytesT
));
381 memcpy (fragP
->tc_frag_data
, & rl78_bytes
, sizeof (rl78_bytesT
));
384 fragP
->tc_frag_data
= 0;
387 /* When relaxing, we need to output a reloc for any .align directive
388 so that we can retain this alignment as we adjust opcode sizes. */
390 rl78_handle_align (fragS
* frag
)
393 && (frag
->fr_type
== rs_align
394 || frag
->fr_type
== rs_align_code
)
395 && frag
->fr_address
+ frag
->fr_fix
> 0
396 && frag
->fr_offset
> 0
397 && now_seg
!= bss_section
)
399 fix_new (frag
, frag
->fr_fix
, 0,
400 &abs_symbol
, RL78_RELAXA_ALIGN
+ frag
->fr_offset
,
401 0, BFD_RELOC_RL78_RELAX
);
402 /* For the purposes of relaxation, this relocation is attached
403 to the byte *after* the alignment - i.e. the byte that must
405 fix_new (frag
->fr_next
, 0, 0,
406 &abs_symbol
, RL78_RELAXA_ELIGN
+ frag
->fr_offset
,
407 0, BFD_RELOC_RL78_RELAX
);
412 md_atof (int type
, char * litP
, int * sizeP
)
414 return ieee_md_atof (type
, litP
, sizeP
, target_big_endian
);
418 md_undefined_symbol (char * name ATTRIBUTE_UNUSED
)
423 #define APPEND(B, N_B) \
424 if (rl78_bytes.N_B) \
426 memcpy (bytes + idx, rl78_bytes.B, rl78_bytes.N_B); \
427 idx += rl78_bytes.N_B; \
432 md_assemble (char * str
)
435 fragS
* frag_then
= frag_now
;
441 /*printf("\033[32mASM: %s\033[0m\n", str);*/
443 dwarf2_emit_insn (0);
445 memset (& rl78_bytes
, 0, sizeof (rl78_bytes
));
447 rl78_lex_init (str
, str
+ strlen (str
));
451 /* This simplifies the relaxation code. */
452 if (rl78_bytes
.link_relax
)
454 int olen
= rl78_bytes
.n_prefix
+ rl78_bytes
.n_base
+ rl78_bytes
.n_ops
;
455 /* We do it this way because we want the frag to have the
456 rl78_bytes in it, which we initialize above. */
457 bytes
= frag_more (olen
);
458 frag_then
= frag_now
;
459 frag_variant (rs_machine_dependent
,
460 olen
/* max_chars */,
466 frag_then
->fr_opcode
= bytes
;
467 frag_then
->fr_fix
= olen
+ (bytes
- frag_then
->fr_literal
);
468 frag_then
->fr_subtype
= olen
;
469 frag_then
->fr_var
= 0;
473 bytes
= frag_more (rl78_bytes
.n_prefix
+ rl78_bytes
.n_base
+ rl78_bytes
.n_ops
);
474 frag_then
= frag_now
;
477 APPEND (prefix
, n_prefix
);
478 APPEND (base
, n_base
);
481 if (rl78_bytes
.link_relax
)
485 f
= fix_new (frag_then
,
486 (char *) bytes
- frag_then
->fr_literal
,
489 rl78_bytes
.link_relax
| rl78_bytes
.n_fixups
,
491 BFD_RELOC_RL78_RELAX
);
492 frag_then
->tc_frag_data
->link_relax_fixP
= f
;
495 for (i
= 0; i
< rl78_bytes
.n_fixups
; i
++)
497 /* index: [nbytes][type] */
498 static int reloc_map
[5][4] =
501 { BFD_RELOC_8
, BFD_RELOC_8_PCREL
},
502 { BFD_RELOC_16
, BFD_RELOC_16_PCREL
},
503 { BFD_RELOC_24
, BFD_RELOC_24_PCREL
},
504 { BFD_RELOC_32
, BFD_RELOC_32_PCREL
},
508 idx
= rl78_bytes
.fixups
[i
].offset
/ 8;
509 rel
= reloc_map
[rl78_bytes
.fixups
[i
].nbits
/ 8][(int) rl78_bytes
.fixups
[i
].type
];
511 if (rl78_bytes
.fixups
[i
].reloc
)
512 rel
= rl78_bytes
.fixups
[i
].reloc
;
514 if (frag_then
->tc_frag_data
)
515 exp
= & frag_then
->tc_frag_data
->fixups
[i
].exp
;
517 exp
= & rl78_bytes
.fixups
[i
].exp
;
519 f
= fix_new_exp (frag_then
,
520 (char *) bytes
+ idx
- frag_then
->fr_literal
,
521 rl78_bytes
.fixups
[i
].nbits
/ 8,
523 rl78_bytes
.fixups
[i
].type
== RL78REL_PCREL
? 1 : 0,
525 if (frag_then
->tc_frag_data
)
526 frag_then
->tc_frag_data
->fixups
[i
].fixP
= f
;
531 rl78_cons_fix_new (fragS
* frag
,
536 bfd_reloc_code_real_type type
;
553 as_bad (_("unsupported constant size %d\n"), size
);
557 if (exp
->X_op
== O_subtract
&& exp
->X_op_symbol
)
559 if (size
!= 4 && size
!= 2 && size
!= 1)
560 as_bad (_("difference of two symbols only supported with .long, .short, or .byte"));
562 type
= BFD_RELOC_RL78_DIFF
;
565 fix_new_exp (frag
, where
, (int) size
, exp
, 0, type
);
568 /* No relaxation just yet */
570 md_estimate_size_before_relax (fragS
* fragP ATTRIBUTE_UNUSED
, segT segment ATTRIBUTE_UNUSED
)
576 tc_gen_reloc (asection
* seg ATTRIBUTE_UNUSED
, fixS
* fixp
)
578 static arelent
* reloc
[8];
581 if (fixp
->fx_r_type
== BFD_RELOC_NONE
)
588 && S_GET_SEGMENT (fixp
->fx_subsy
) == absolute_section
)
590 fixp
->fx_offset
-= S_GET_VALUE (fixp
->fx_subsy
);
591 fixp
->fx_subsy
= NULL
;
594 reloc
[0] = (arelent
*) xmalloc (sizeof (arelent
));
595 reloc
[0]->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
596 * reloc
[0]->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
597 reloc
[0]->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
598 reloc
[0]->addend
= fixp
->fx_offset
;
600 if (fixp
->fx_r_type
== BFD_RELOC_RL78_32_OP
603 fixp
->fx_r_type
= BFD_RELOC_RL78_DIFF
;
606 #define OPX(REL,SYM,ADD) \
607 reloc[rp] = (arelent *) xmalloc (sizeof (arelent)); \
608 reloc[rp]->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); \
609 reloc[rp]->howto = bfd_reloc_type_lookup (stdoutput, REL); \
610 reloc[rp]->addend = ADD; \
611 * reloc[rp]->sym_ptr_ptr = SYM; \
612 reloc[rp]->address = fixp->fx_frag->fr_address + fixp->fx_where; \
614 #define OPSYM(SYM) OPX(BFD_RELOC_RL78_SYM, SYM, 0)
615 #define OPIMM(IMM) OPX(BFD_RELOC_RL78_SYM, abs_symbol.bsym, IMM)
616 #define OP(OP) OPX(BFD_RELOC_RL78_##OP, *reloc[0]->sym_ptr_ptr, 0)
617 #define SYM0() reloc[0]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_RL78_SYM)
621 /* Certain BFD relocations cannot be translated directly into
622 a single (non-Red Hat) RL78 relocation, but instead need
623 multiple RL78 relocations - handle them here. */
624 switch (fixp
->fx_r_type
)
626 case BFD_RELOC_RL78_DIFF
:
628 OPSYM (symbol_get_bfdsym (fixp
->fx_subsy
));
631 switch (fixp
->fx_size
)
645 case BFD_RELOC_RL78_NEG32
:
651 case BFD_RELOC_RL78_LO16
:
658 case BFD_RELOC_RL78_HI16
:
665 case BFD_RELOC_RL78_HI8
:
675 reloc
[0]->howto
= bfd_reloc_type_lookup (stdoutput
, fixp
->fx_r_type
);
684 rl78_validate_fix_sub (struct fix
* f
)
686 /* We permit the subtraction of two symbols in a few cases. */
687 /* mov #sym1-sym2, R3 */
688 if (f
->fx_r_type
== BFD_RELOC_RL78_32_OP
)
690 /* .long sym1-sym2 */
691 if (f
->fx_r_type
== BFD_RELOC_RL78_DIFF
693 && (f
->fx_size
== 4 || f
->fx_size
== 2 || f
->fx_size
== 1))
699 md_pcrel_from_section (fixS
* fixP
, segT sec
)
703 if (fixP
->fx_addsy
!= NULL
704 && (! S_IS_DEFINED (fixP
->fx_addsy
)
705 || S_GET_SEGMENT (fixP
->fx_addsy
) != sec
))
706 /* The symbol is undefined (or is defined but not in this section).
707 Let the linker figure it out. */
710 rv
= fixP
->fx_frag
->fr_address
+ fixP
->fx_where
;
711 switch (fixP
->fx_r_type
)
713 case BFD_RELOC_8_PCREL
:
716 case BFD_RELOC_16_PCREL
:
726 md_apply_fix (struct fix
* f ATTRIBUTE_UNUSED
,
727 valueT
* t ATTRIBUTE_UNUSED
,
728 segT s ATTRIBUTE_UNUSED
)
733 if (f
->fx_addsy
&& S_FORCE_RELOC (f
->fx_addsy
, 1))
735 if (f
->fx_subsy
&& S_FORCE_RELOC (f
->fx_subsy
, 1))
738 op
= f
->fx_frag
->fr_literal
+ f
->fx_where
;
739 val
= (unsigned long) * t
;
741 switch (f
->fx_r_type
)
746 case BFD_RELOC_RL78_RELAX
:
751 case BFD_RELOC_8_PCREL
:
756 case BFD_RELOC_16_PCREL
:
768 case BFD_RELOC_RL78_DIFF
:
776 as_bad (_("Unknown reloc in md_apply_fix: %s"),
777 bfd_get_reloc_code_name (f
->fx_r_type
));
781 if (f
->fx_addsy
== NULL
)
786 md_section_align (segT segment
, valueT size
)
788 int align
= bfd_get_section_alignment (stdoutput
, segment
);
789 return ((size
+ (1 << align
) - 1) & (-1 << align
));
793 md_convert_frag (bfd
* abfd ATTRIBUTE_UNUSED
,
794 segT segment ATTRIBUTE_UNUSED
,
795 fragS
* fragP ATTRIBUTE_UNUSED
)
797 /* No relaxation yet */