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_fixup (expressionS exp, int offsetbits, int nbits, int type)
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 ++;
95 #define rl78_field_fixup(exp, offset, nbits, type) \
96 rl78_fixup (exp, offset + 8 * rl78_bytes.n_prefix), nbits, type)
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)
104 rl78_bytes.prefix[0] = p;
105 rl78_bytes.n_prefix = 1;
111 return rl78_bytes.n_prefix;
117 rl78_bytes.base[0] = b1;
118 rl78_bytes.n_base = 1;
122 rl78_base2 (int b1, int b2)
124 rl78_bytes.base[0] = b1;
125 rl78_bytes.base[1] = b2;
126 rl78_bytes.n_base = 2;
130 rl78_base3 (int b1, int b2, int b3)
132 rl78_bytes.base[0] = b1;
133 rl78_bytes.base[1] = b2;
134 rl78_bytes.base[2] = b3;
135 rl78_bytes.n_base = 3;
139 rl78_base4 (int b1, int b2, int b3, int b4)
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;
148 #define F_PRECISION 2
151 rl78_op (expressionS exp, int nbytes, int type)
155 if ((exp.X_op == O_constant || exp.X_op == O_big)
156 && type != RL78REL_PCREL)
158 if (exp.X_op == O_big && exp.X_add_number <= 0)
161 char * ip = rl78_bytes.ops + rl78_bytes.n_ops;
163 gen_to_words (w, F_PRECISION, 8);
168 rl78_bytes.n_ops += 4;
172 v = exp.X_add_number;
175 rl78_bytes.ops[rl78_bytes.n_ops++] =v & 0xff;
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;
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:
195 - - - - - - - - - - - - - - - -
199 rl78_field (int val, int pos, int sz)
206 if (val < 0 || val >= (1 << sz))
207 as_bad (_("Value %d doesn't fit in unsigned %d-bit field"), val, 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);
216 /* This code points at 'M' in the above example. */
220 while (bitp + sz > 8)
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;
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;
241 /*------------------------------------------------------------------*/
243 #define RL78_SHORTOPTS ""
244 const char * md_shortopts = RL78_SHORTOPTS;
246 /* Assembler options. */
247 struct option md_longopts[] =
249 {NULL, no_argument, NULL, 0}
251 size_t md_longopts_size = sizeof (md_longopts);
254 md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED)
260 md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
266 s_bss (int ignore ATTRIBUTE_UNUSED)
270 temp = get_absolute_expression ();
271 subseg_set (bss_section, (subsegT) temp);
272 demand_empty_rest_of_line ();
275 /* The target specific pseudo-ops which we support. */
276 const pseudo_typeS md_pseudo_table[] =
278 /* Our "standard" pseudos. */
279 { "double", float_cons, 'd' },
281 { "3byte", cons, 3 },
285 /* End of list marker. */
299 /* Write a value out to the object file, using the appropriate endianness. */
301 md_number_to_chars (char * buf, valueT val, int n)
303 number_to_chars_littleendian (buf, val, n);
313 { "lo16", BFD_RELOC_RL78_LO16 },
314 { "hi16", BFD_RELOC_RL78_HI16 },
315 { "hi8", BFD_RELOC_RL78_HI8 },
320 md_operand (expressionS * exp ATTRIBUTE_UNUSED)
325 for (i = 0; reloc_functions[i].fname; i++)
327 int flen = strlen (reloc_functions[i].fname);
329 if (input_line_pointer[0] == '%'
330 && strncasecmp (input_line_pointer + 1, reloc_functions[i].fname, flen) == 0
331 && input_line_pointer[flen + 1] == '(')
333 reloc = reloc_functions[i].reloc;
334 input_line_pointer += flen + 2;
342 if (* input_line_pointer == ')')
343 input_line_pointer ++;
349 rl78_frag_init (fragS * fragP)
351 fragP->tc_frag_data = 0;
355 md_atof (int type, char * litP, int * sizeP)
357 return ieee_md_atof (type, litP, sizeP, target_big_endian);
361 md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
366 #define APPEND(B, N_B) \
367 if (rl78_bytes.N_B) \
369 memcpy (bytes + idx, rl78_bytes.B, rl78_bytes.N_B); \
370 idx += rl78_bytes.N_B; \
375 md_assemble (char * str)
378 fragS * frag_then = frag_now;
384 /*printf("\033[32mASM: %s\033[0m\n", str);*/
386 dwarf2_emit_insn (0);
388 memset (& rl78_bytes, 0, sizeof (rl78_bytes));
390 rl78_lex_init (str, str + strlen (str));
394 bytes = frag_more (rl78_bytes.n_prefix + rl78_bytes.n_base + rl78_bytes.n_ops);
395 frag_then = frag_now;
397 APPEND (prefix, n_prefix);
398 APPEND (base, n_base);
401 for (i = 0; i < rl78_bytes.n_fixups; i ++)
403 /* index: [nbytes][type] */
404 static int reloc_map[5][4] =
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 },
414 idx = rl78_bytes.fixups[i].offset / 8;
415 rel = reloc_map [rl78_bytes.fixups[i].nbits / 8][(int) rl78_bytes.fixups[i].type];
417 if (rl78_bytes.fixups[i].reloc)
418 rel = rl78_bytes.fixups[i].reloc;
420 if (frag_then->tc_frag_data)
421 exp = & frag_then->tc_frag_data->fixups[i].exp;
423 exp = & rl78_bytes.fixups[i].exp;
425 f = fix_new_exp (frag_then,
426 (char *) bytes + idx - frag_then->fr_literal,
427 rl78_bytes.fixups[i].nbits / 8,
429 rl78_bytes.fixups[i].type == RL78REL_PCREL ? 1 : 0,
431 if (frag_then->tc_frag_data)
432 frag_then->tc_frag_data->fixups[i].fixP = f;
437 rl78_cons_fix_new (fragS * frag,
442 bfd_reloc_code_real_type type;
459 as_bad (_("unsupported constant size %d\n"), size);
463 if (exp->X_op == O_subtract && exp->X_op_symbol)
465 if (size != 4 && size != 2 && size != 1)
466 as_bad (_("difference of two symbols only supported with .long, .short, or .byte"));
468 type = BFD_RELOC_RL78_DIFF;
471 fix_new_exp (frag, where, (int) size, exp, 0, type);
474 /* No relaxation just yet */
476 md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED, segT segment ATTRIBUTE_UNUSED)
481 tc_gen_reloc (asection * seg ATTRIBUTE_UNUSED, fixS * fixp)
483 static arelent * reloc[8];
486 if (fixp->fx_r_type == BFD_RELOC_NONE)
493 && S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
495 fixp->fx_offset -= S_GET_VALUE (fixp->fx_subsy);
496 fixp->fx_subsy = NULL;
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;
505 if (fixp->fx_r_type == BFD_RELOC_RL78_32_OP
508 fixp->fx_r_type = BFD_RELOC_RL78_DIFF;
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; \
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)
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)
531 case BFD_RELOC_RL78_DIFF:
533 OPSYM (symbol_get_bfdsym (fixp->fx_subsy));
536 switch (fixp->fx_size)
550 case BFD_RELOC_RL78_NEG32:
556 case BFD_RELOC_RL78_LO16:
563 case BFD_RELOC_RL78_HI16:
570 case BFD_RELOC_RL78_HI8:
580 reloc[0]->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
589 rl78_validate_fix_sub (struct fix * f)
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)
595 /* .long sym1-sym2 */
596 if (f->fx_r_type == BFD_RELOC_RL78_DIFF
598 && (f->fx_size == 4 || f->fx_size == 2 || f->fx_size == 1))
604 md_pcrel_from_section (fixS * fixP, segT sec)
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. */
615 rv = fixP->fx_frag->fr_address + fixP->fx_where;
616 switch (fixP->fx_r_type)
618 case BFD_RELOC_8_PCREL:
621 case BFD_RELOC_16_PCREL:
631 md_apply_fix (struct fix * f ATTRIBUTE_UNUSED,
632 valueT * t ATTRIBUTE_UNUSED,
633 segT s ATTRIBUTE_UNUSED)
638 if (f->fx_addsy && S_FORCE_RELOC (f->fx_addsy, 1))
640 if (f->fx_subsy && S_FORCE_RELOC (f->fx_subsy, 1))
643 op = f->fx_frag->fr_literal + f->fx_where;
644 val = (unsigned long) * t;
646 switch (f->fx_r_type)
652 case BFD_RELOC_8_PCREL:
657 case BFD_RELOC_16_PCREL:
669 case BFD_RELOC_RL78_DIFF:
677 as_bad (_("Unknown reloc in md_apply_fix: %s"),
678 bfd_get_reloc_code_name (f->fx_r_type));
682 if (f->fx_addsy == NULL)
687 md_section_align (segT segment, valueT size)
689 int align = bfd_get_section_alignment (stdoutput, segment);
690 return ((size + (1 << align) - 1) & (-1 << align));
694 md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
695 segT segment ATTRIBUTE_UNUSED,
696 fragS * fragP ATTRIBUTE_UNUSED)
698 /* No relaxation yet */