tc-rl78.c revision 1.1 1 1.1 christos /* tc-rl78.c -- Assembler for the Renesas RL78
2 1.1 christos Copyright 2011
3 1.1 christos Free Software Foundation, Inc.
4 1.1 christos
5 1.1 christos This file is part of GAS, the GNU Assembler.
6 1.1 christos
7 1.1 christos GAS is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3, or (at your option)
10 1.1 christos any later version.
11 1.1 christos
12 1.1 christos GAS is distributed in the hope that it will be useful,
13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 christos GNU General Public License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with GAS; see the file COPYING. If not, write to the Free
19 1.1 christos Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20 1.1 christos 02110-1301, USA. */
21 1.1 christos
22 1.1 christos #include "as.h"
23 1.1 christos #include "struc-symbol.h"
24 1.1 christos #include "obstack.h"
25 1.1 christos #include "safe-ctype.h"
26 1.1 christos #include "dwarf2dbg.h"
27 1.1 christos #include "libbfd.h"
28 1.1 christos #include "elf/common.h"
29 1.1 christos #include "elf/rl78.h"
30 1.1 christos #include "rl78-defs.h"
31 1.1 christos #include "filenames.h"
32 1.1 christos #include "listing.h"
33 1.1 christos #include "sb.h"
34 1.1 christos #include "macro.h"
35 1.1 christos
36 1.1 christos const char comment_chars[] = ";";
37 1.1 christos /* Note that input_file.c hand checks for '#' at the beginning of the
38 1.1 christos first line of the input file. This is because the compiler outputs
39 1.1 christos #NO_APP at the beginning of its output. */
40 1.1 christos const char line_comment_chars[] = "#";
41 1.1 christos const char line_separator_chars[] = "|";
42 1.1 christos
43 1.1 christos const char EXP_CHARS[] = "eE";
44 1.1 christos const char FLT_CHARS[] = "dD";
45 1.1 christos
46 1.1 christos /*------------------------------------------------------------------*/
47 1.1 christos
48 1.1 christos char * rl78_lex_start;
49 1.1 christos char * rl78_lex_end;
50 1.1 christos
51 1.1 christos typedef struct rl78_bytesT
52 1.1 christos {
53 1.1 christos char prefix[1];
54 1.1 christos int n_prefix;
55 1.1 christos char base[4];
56 1.1 christos int n_base;
57 1.1 christos char ops[8];
58 1.1 christos int n_ops;
59 1.1 christos struct
60 1.1 christos {
61 1.1 christos expressionS exp;
62 1.1 christos char offset;
63 1.1 christos char nbits;
64 1.1 christos char type; /* RL78REL_*. */
65 1.1 christos int reloc;
66 1.1 christos fixS * fixP;
67 1.1 christos } fixups[2];
68 1.1 christos int n_fixups;
69 1.1 christos struct
70 1.1 christos {
71 1.1 christos char type;
72 1.1 christos char field_pos;
73 1.1 christos char val_ofs;
74 1.1 christos } relax[2];
75 1.1 christos int n_relax;
76 1.1 christos int link_relax;
77 1.1 christos fixS *link_relax_fixP;
78 1.1 christos char times_grown;
79 1.1 christos char times_shrank;
80 1.1 christos } rl78_bytesT;
81 1.1 christos
82 1.1 christos static rl78_bytesT rl78_bytes;
83 1.1 christos
84 1.1 christos void
85 1.1 christos rl78_linkrelax_addr16 (void)
86 1.1 christos {
87 1.1 christos rl78_bytes.link_relax |= RL78_RELAXA_ADDR16;
88 1.1 christos }
89 1.1 christos
90 1.1 christos void
91 1.1 christos rl78_linkrelax_branch (void)
92 1.1 christos {
93 1.1 christos rl78_bytes.link_relax |= RL78_RELAXA_BRA;
94 1.1 christos }
95 1.1 christos
96 1.1 christos static void
97 1.1 christos rl78_fixup (expressionS exp, int offsetbits, int nbits, int type)
98 1.1 christos {
99 1.1 christos rl78_bytes.fixups[rl78_bytes.n_fixups].exp = exp;
100 1.1 christos rl78_bytes.fixups[rl78_bytes.n_fixups].offset = offsetbits;
101 1.1 christos rl78_bytes.fixups[rl78_bytes.n_fixups].nbits = nbits;
102 1.1 christos rl78_bytes.fixups[rl78_bytes.n_fixups].type = type;
103 1.1 christos rl78_bytes.fixups[rl78_bytes.n_fixups].reloc = exp.X_md;
104 1.1 christos rl78_bytes.n_fixups ++;
105 1.1 christos }
106 1.1 christos
107 1.1 christos #define rl78_field_fixup(exp, offset, nbits, type) \
108 1.1 christos rl78_fixup (exp, offset + 8 * rl78_bytes.n_prefix), nbits, type)
109 1.1 christos
110 1.1 christos #define rl78_op_fixup(exp, offset, nbits, type) \
111 1.1 christos rl78_fixup (exp, offset + 8 * (rl78_bytes.n_prefix + rl78_bytes.n_base), nbits, type)
112 1.1 christos
113 1.1 christos void
114 1.1 christos rl78_prefix (int p)
115 1.1 christos {
116 1.1 christos rl78_bytes.prefix[0] = p;
117 1.1 christos rl78_bytes.n_prefix = 1;
118 1.1 christos }
119 1.1 christos
120 1.1 christos int
121 1.1 christos rl78_has_prefix ()
122 1.1 christos {
123 1.1 christos return rl78_bytes.n_prefix;
124 1.1 christos }
125 1.1 christos
126 1.1 christos void
127 1.1 christos rl78_base1 (int b1)
128 1.1 christos {
129 1.1 christos rl78_bytes.base[0] = b1;
130 1.1 christos rl78_bytes.n_base = 1;
131 1.1 christos }
132 1.1 christos
133 1.1 christos void
134 1.1 christos rl78_base2 (int b1, int b2)
135 1.1 christos {
136 1.1 christos rl78_bytes.base[0] = b1;
137 1.1 christos rl78_bytes.base[1] = b2;
138 1.1 christos rl78_bytes.n_base = 2;
139 1.1 christos }
140 1.1 christos
141 1.1 christos void
142 1.1 christos rl78_base3 (int b1, int b2, int b3)
143 1.1 christos {
144 1.1 christos rl78_bytes.base[0] = b1;
145 1.1 christos rl78_bytes.base[1] = b2;
146 1.1 christos rl78_bytes.base[2] = b3;
147 1.1 christos rl78_bytes.n_base = 3;
148 1.1 christos }
149 1.1 christos
150 1.1 christos void
151 1.1 christos rl78_base4 (int b1, int b2, int b3, int b4)
152 1.1 christos {
153 1.1 christos rl78_bytes.base[0] = b1;
154 1.1 christos rl78_bytes.base[1] = b2;
155 1.1 christos rl78_bytes.base[2] = b3;
156 1.1 christos rl78_bytes.base[3] = b4;
157 1.1 christos rl78_bytes.n_base = 4;
158 1.1 christos }
159 1.1 christos
160 1.1 christos #define F_PRECISION 2
161 1.1 christos
162 1.1 christos void
163 1.1 christos rl78_op (expressionS exp, int nbytes, int type)
164 1.1 christos {
165 1.1 christos int v = 0;
166 1.1 christos
167 1.1 christos if ((exp.X_op == O_constant || exp.X_op == O_big)
168 1.1 christos && type != RL78REL_PCREL)
169 1.1 christos {
170 1.1 christos if (exp.X_op == O_big && exp.X_add_number <= 0)
171 1.1 christos {
172 1.1 christos LITTLENUM_TYPE w[2];
173 1.1 christos char * ip = rl78_bytes.ops + rl78_bytes.n_ops;
174 1.1 christos
175 1.1 christos gen_to_words (w, F_PRECISION, 8);
176 1.1 christos ip[3] = w[0] >> 8;
177 1.1 christos ip[2] = w[0];
178 1.1 christos ip[1] = w[1] >> 8;
179 1.1 christos ip[0] = w[1];
180 1.1 christos rl78_bytes.n_ops += 4;
181 1.1 christos }
182 1.1 christos else
183 1.1 christos {
184 1.1 christos v = exp.X_add_number;
185 1.1 christos while (nbytes)
186 1.1 christos {
187 1.1 christos rl78_bytes.ops[rl78_bytes.n_ops++] =v & 0xff;
188 1.1 christos v >>= 8;
189 1.1 christos nbytes --;
190 1.1 christos }
191 1.1 christos }
192 1.1 christos }
193 1.1 christos else
194 1.1 christos {
195 1.1 christos rl78_op_fixup (exp, rl78_bytes.n_ops * 8, nbytes * 8, type);
196 1.1 christos memset (rl78_bytes.ops + rl78_bytes.n_ops, 0, nbytes);
197 1.1 christos rl78_bytes.n_ops += nbytes;
198 1.1 christos }
199 1.1 christos }
200 1.1 christos
201 1.1 christos /* This gets complicated when the field spans bytes, because fields
202 1.1 christos are numbered from the MSB of the first byte as zero, and bits are
203 1.1 christos stored LSB towards the LSB of the byte. Thus, a simple four-bit
204 1.1 christos insertion of 12 at position 4 of 0x00 yields: 0x0b. A three-bit
205 1.1 christos insertion of b'MXL at position 7 is like this:
206 1.1 christos
207 1.1 christos - - - - - - - - - - - - - - - -
208 1.1 christos M X L */
209 1.1 christos
210 1.1 christos void
211 1.1 christos rl78_field (int val, int pos, int sz)
212 1.1 christos {
213 1.1 christos int valm;
214 1.1 christos int bytep, bitp;
215 1.1 christos
216 1.1 christos if (sz > 0)
217 1.1 christos {
218 1.1 christos if (val < 0 || val >= (1 << sz))
219 1.1 christos as_bad (_("Value %d doesn't fit in unsigned %d-bit field"), val, sz);
220 1.1 christos }
221 1.1 christos else
222 1.1 christos {
223 1.1 christos sz = - sz;
224 1.1 christos if (val < -(1 << (sz - 1)) || val >= (1 << (sz - 1)))
225 1.1 christos as_bad (_("Value %d doesn't fit in signed %d-bit field"), val, sz);
226 1.1 christos }
227 1.1 christos
228 1.1 christos /* This code points at 'M' in the above example. */
229 1.1 christos bytep = pos / 8;
230 1.1 christos bitp = pos % 8;
231 1.1 christos
232 1.1 christos while (bitp + sz > 8)
233 1.1 christos {
234 1.1 christos int ssz = 8 - bitp;
235 1.1 christos int svalm;
236 1.1 christos
237 1.1 christos svalm = val >> (sz - ssz);
238 1.1 christos svalm = svalm & ((1 << ssz) - 1);
239 1.1 christos svalm = svalm << (8 - bitp - ssz);
240 1.1 christos gas_assert (bytep < rl78_bytes.n_base);
241 1.1 christos rl78_bytes.base[bytep] |= svalm;
242 1.1 christos
243 1.1 christos bitp = 0;
244 1.1 christos sz -= ssz;
245 1.1 christos bytep ++;
246 1.1 christos }
247 1.1 christos valm = val & ((1 << sz) - 1);
248 1.1 christos valm = valm << (8 - bitp - sz);
249 1.1 christos gas_assert (bytep < rl78_bytes.n_base);
250 1.1 christos rl78_bytes.base[bytep] |= valm;
251 1.1 christos }
252 1.1 christos
253 1.1 christos /*------------------------------------------------------------------*/
254 1.1 christos
255 1.1 christos enum options
256 1.1 christos {
257 1.1 christos OPTION_RELAX = OPTION_MD_BASE,
258 1.1 christos };
259 1.1 christos
260 1.1 christos #define RL78_SHORTOPTS ""
261 1.1 christos const char * md_shortopts = RL78_SHORTOPTS;
262 1.1 christos
263 1.1 christos /* Assembler options. */
264 1.1 christos struct option md_longopts[] =
265 1.1 christos {
266 1.1 christos {"relax", no_argument, NULL, OPTION_RELAX},
267 1.1 christos {NULL, no_argument, NULL, 0}
268 1.1 christos };
269 1.1 christos size_t md_longopts_size = sizeof (md_longopts);
270 1.1 christos
271 1.1 christos int
272 1.1 christos md_parse_option (int c, char * arg ATTRIBUTE_UNUSED)
273 1.1 christos {
274 1.1 christos switch (c)
275 1.1 christos {
276 1.1 christos case OPTION_RELAX:
277 1.1 christos linkrelax = 1;
278 1.1 christos return 1;
279 1.1 christos
280 1.1 christos }
281 1.1 christos return 0;
282 1.1 christos }
283 1.1 christos
284 1.1 christos void
285 1.1 christos md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
286 1.1 christos {
287 1.1 christos }
288 1.1 christos
289 1.1 christos
290 1.1 christos static void
291 1.1 christos s_bss (int ignore ATTRIBUTE_UNUSED)
292 1.1 christos {
293 1.1 christos int temp;
294 1.1 christos
295 1.1 christos temp = get_absolute_expression ();
296 1.1 christos subseg_set (bss_section, (subsegT) temp);
297 1.1 christos demand_empty_rest_of_line ();
298 1.1 christos }
299 1.1 christos
300 1.1 christos /* The target specific pseudo-ops which we support. */
301 1.1 christos const pseudo_typeS md_pseudo_table[] =
302 1.1 christos {
303 1.1 christos /* Our "standard" pseudos. */
304 1.1 christos { "double", float_cons, 'd' },
305 1.1 christos { "bss", s_bss, 0 },
306 1.1 christos { "3byte", cons, 3 },
307 1.1 christos { "int", cons, 4 },
308 1.1 christos { "word", cons, 4 },
309 1.1 christos
310 1.1 christos /* End of list marker. */
311 1.1 christos { NULL, NULL, 0 }
312 1.1 christos };
313 1.1 christos
314 1.1 christos void
315 1.1 christos md_begin (void)
316 1.1 christos {
317 1.1 christos }
318 1.1 christos
319 1.1 christos void
320 1.1 christos rl78_md_end (void)
321 1.1 christos {
322 1.1 christos }
323 1.1 christos
324 1.1 christos /* Write a value out to the object file, using the appropriate endianness. */
325 1.1 christos void
326 1.1 christos md_number_to_chars (char * buf, valueT val, int n)
327 1.1 christos {
328 1.1 christos number_to_chars_littleendian (buf, val, n);
329 1.1 christos }
330 1.1 christos
331 1.1 christos static struct
332 1.1 christos {
333 1.1 christos char * fname;
334 1.1 christos int reloc;
335 1.1 christos }
336 1.1 christos reloc_functions[] =
337 1.1 christos {
338 1.1 christos { "lo16", BFD_RELOC_RL78_LO16 },
339 1.1 christos { "hi16", BFD_RELOC_RL78_HI16 },
340 1.1 christos { "hi8", BFD_RELOC_RL78_HI8 },
341 1.1 christos { 0, 0 }
342 1.1 christos };
343 1.1 christos
344 1.1 christos void
345 1.1 christos md_operand (expressionS * exp ATTRIBUTE_UNUSED)
346 1.1 christos {
347 1.1 christos int reloc = 0;
348 1.1 christos int i;
349 1.1 christos
350 1.1 christos for (i = 0; reloc_functions[i].fname; i++)
351 1.1 christos {
352 1.1 christos int flen = strlen (reloc_functions[i].fname);
353 1.1 christos
354 1.1 christos if (input_line_pointer[0] == '%'
355 1.1 christos && strncasecmp (input_line_pointer + 1, reloc_functions[i].fname, flen) == 0
356 1.1 christos && input_line_pointer[flen + 1] == '(')
357 1.1 christos {
358 1.1 christos reloc = reloc_functions[i].reloc;
359 1.1 christos input_line_pointer += flen + 2;
360 1.1 christos break;
361 1.1 christos }
362 1.1 christos }
363 1.1 christos if (reloc == 0)
364 1.1 christos return;
365 1.1 christos
366 1.1 christos expression (exp);
367 1.1 christos if (* input_line_pointer == ')')
368 1.1 christos input_line_pointer ++;
369 1.1 christos
370 1.1 christos exp->X_md = reloc;
371 1.1 christos }
372 1.1 christos
373 1.1 christos void
374 1.1 christos rl78_frag_init (fragS * fragP)
375 1.1 christos {
376 1.1 christos if (rl78_bytes.n_relax || rl78_bytes.link_relax)
377 1.1 christos {
378 1.1 christos fragP->tc_frag_data = malloc (sizeof (rl78_bytesT));
379 1.1 christos memcpy (fragP->tc_frag_data, & rl78_bytes, sizeof (rl78_bytesT));
380 1.1 christos }
381 1.1 christos else
382 1.1 christos fragP->tc_frag_data = 0;
383 1.1 christos }
384 1.1 christos
385 1.1 christos /* When relaxing, we need to output a reloc for any .align directive
386 1.1 christos so that we can retain this alignment as we adjust opcode sizes. */
387 1.1 christos void
388 1.1 christos rl78_handle_align (fragS * frag)
389 1.1 christos {
390 1.1 christos if (linkrelax
391 1.1 christos && (frag->fr_type == rs_align
392 1.1 christos || frag->fr_type == rs_align_code)
393 1.1 christos && frag->fr_address + frag->fr_fix > 0
394 1.1 christos && frag->fr_offset > 0
395 1.1 christos && now_seg != bss_section)
396 1.1 christos {
397 1.1 christos fix_new (frag, frag->fr_fix, 0,
398 1.1 christos &abs_symbol, RL78_RELAXA_ALIGN + frag->fr_offset,
399 1.1 christos 0, BFD_RELOC_RL78_RELAX);
400 1.1 christos /* For the purposes of relaxation, this relocation is attached
401 1.1 christos to the byte *after* the alignment - i.e. the byte that must
402 1.1 christos remain aligned. */
403 1.1 christos fix_new (frag->fr_next, 0, 0,
404 1.1 christos &abs_symbol, RL78_RELAXA_ELIGN + frag->fr_offset,
405 1.1 christos 0, BFD_RELOC_RL78_RELAX);
406 1.1 christos }
407 1.1 christos }
408 1.1 christos
409 1.1 christos char *
410 1.1 christos md_atof (int type, char * litP, int * sizeP)
411 1.1 christos {
412 1.1 christos return ieee_md_atof (type, litP, sizeP, target_big_endian);
413 1.1 christos }
414 1.1 christos
415 1.1 christos symbolS *
416 1.1 christos md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
417 1.1 christos {
418 1.1 christos return NULL;
419 1.1 christos }
420 1.1 christos
421 1.1 christos #define APPEND(B, N_B) \
422 1.1 christos if (rl78_bytes.N_B) \
423 1.1 christos { \
424 1.1 christos memcpy (bytes + idx, rl78_bytes.B, rl78_bytes.N_B); \
425 1.1 christos idx += rl78_bytes.N_B; \
426 1.1 christos }
427 1.1 christos
428 1.1 christos
429 1.1 christos void
430 1.1 christos md_assemble (char * str)
431 1.1 christos {
432 1.1 christos char * bytes;
433 1.1 christos fragS * frag_then = frag_now;
434 1.1 christos int idx = 0;
435 1.1 christos int i;
436 1.1 christos int rel;
437 1.1 christos expressionS *exp;
438 1.1 christos
439 1.1 christos /*printf("\033[32mASM: %s\033[0m\n", str);*/
440 1.1 christos
441 1.1 christos dwarf2_emit_insn (0);
442 1.1 christos
443 1.1 christos memset (& rl78_bytes, 0, sizeof (rl78_bytes));
444 1.1 christos
445 1.1 christos rl78_lex_init (str, str + strlen (str));
446 1.1 christos
447 1.1 christos rl78_parse ();
448 1.1 christos
449 1.1 christos /* This simplifies the relaxation code. */
450 1.1 christos if (rl78_bytes.link_relax)
451 1.1 christos {
452 1.1 christos int olen = rl78_bytes.n_prefix + rl78_bytes.n_base + rl78_bytes.n_ops;
453 1.1 christos /* We do it this way because we want the frag to have the
454 1.1 christos rl78_bytes in it, which we initialize above. */
455 1.1 christos bytes = frag_more (olen);
456 1.1 christos frag_then = frag_now;
457 1.1 christos frag_variant (rs_machine_dependent,
458 1.1 christos olen /* max_chars */,
459 1.1 christos 0 /* var */,
460 1.1 christos olen /* subtype */,
461 1.1 christos 0 /* symbol */,
462 1.1 christos 0 /* offset */,
463 1.1 christos 0 /* opcode */);
464 1.1 christos frag_then->fr_opcode = bytes;
465 1.1 christos frag_then->fr_fix = olen + (bytes - frag_then->fr_literal);
466 1.1 christos frag_then->fr_subtype = olen;
467 1.1 christos frag_then->fr_var = 0;
468 1.1 christos }
469 1.1 christos else
470 1.1 christos {
471 1.1 christos bytes = frag_more (rl78_bytes.n_prefix + rl78_bytes.n_base + rl78_bytes.n_ops);
472 1.1 christos frag_then = frag_now;
473 1.1 christos }
474 1.1 christos
475 1.1 christos APPEND (prefix, n_prefix);
476 1.1 christos APPEND (base, n_base);
477 1.1 christos APPEND (ops, n_ops);
478 1.1 christos
479 1.1 christos if (rl78_bytes.link_relax)
480 1.1 christos {
481 1.1 christos fixS * f;
482 1.1 christos
483 1.1 christos f = fix_new (frag_then,
484 1.1 christos (char *) bytes - frag_then->fr_literal,
485 1.1 christos 0,
486 1.1 christos abs_section_sym,
487 1.1 christos rl78_bytes.link_relax | rl78_bytes.n_fixups,
488 1.1 christos 0,
489 1.1 christos BFD_RELOC_RL78_RELAX);
490 1.1 christos frag_then->tc_frag_data->link_relax_fixP = f;
491 1.1 christos }
492 1.1 christos
493 1.1 christos for (i = 0; i < rl78_bytes.n_fixups; i ++)
494 1.1 christos {
495 1.1 christos /* index: [nbytes][type] */
496 1.1 christos static int reloc_map[5][4] =
497 1.1 christos {
498 1.1 christos { 0, 0 },
499 1.1 christos { BFD_RELOC_8, BFD_RELOC_8_PCREL },
500 1.1 christos { BFD_RELOC_16, BFD_RELOC_16_PCREL },
501 1.1 christos { BFD_RELOC_24, BFD_RELOC_24_PCREL },
502 1.1 christos { BFD_RELOC_32, BFD_RELOC_32_PCREL },
503 1.1 christos };
504 1.1 christos fixS * f;
505 1.1 christos
506 1.1 christos idx = rl78_bytes.fixups[i].offset / 8;
507 1.1 christos rel = reloc_map [rl78_bytes.fixups[i].nbits / 8][(int) rl78_bytes.fixups[i].type];
508 1.1 christos
509 1.1 christos if (rl78_bytes.fixups[i].reloc)
510 1.1 christos rel = rl78_bytes.fixups[i].reloc;
511 1.1 christos
512 1.1 christos if (frag_then->tc_frag_data)
513 1.1 christos exp = & frag_then->tc_frag_data->fixups[i].exp;
514 1.1 christos else
515 1.1 christos exp = & rl78_bytes.fixups[i].exp;
516 1.1 christos
517 1.1 christos f = fix_new_exp (frag_then,
518 1.1 christos (char *) bytes + idx - frag_then->fr_literal,
519 1.1 christos rl78_bytes.fixups[i].nbits / 8,
520 1.1 christos exp,
521 1.1 christos rl78_bytes.fixups[i].type == RL78REL_PCREL ? 1 : 0,
522 1.1 christos rel);
523 1.1 christos if (frag_then->tc_frag_data)
524 1.1 christos frag_then->tc_frag_data->fixups[i].fixP = f;
525 1.1 christos }
526 1.1 christos }
527 1.1 christos
528 1.1 christos void
529 1.1 christos rl78_cons_fix_new (fragS * frag,
530 1.1 christos int where,
531 1.1 christos int size,
532 1.1 christos expressionS * exp)
533 1.1 christos {
534 1.1 christos bfd_reloc_code_real_type type;
535 1.1 christos
536 1.1 christos switch (size)
537 1.1 christos {
538 1.1 christos case 1:
539 1.1 christos type = BFD_RELOC_8;
540 1.1 christos break;
541 1.1 christos case 2:
542 1.1 christos type = BFD_RELOC_16;
543 1.1 christos break;
544 1.1 christos case 3:
545 1.1 christos type = BFD_RELOC_24;
546 1.1 christos break;
547 1.1 christos case 4:
548 1.1 christos type = BFD_RELOC_32;
549 1.1 christos break;
550 1.1 christos default:
551 1.1 christos as_bad (_("unsupported constant size %d\n"), size);
552 1.1 christos return;
553 1.1 christos }
554 1.1 christos
555 1.1 christos if (exp->X_op == O_subtract && exp->X_op_symbol)
556 1.1 christos {
557 1.1 christos if (size != 4 && size != 2 && size != 1)
558 1.1 christos as_bad (_("difference of two symbols only supported with .long, .short, or .byte"));
559 1.1 christos else
560 1.1 christos type = BFD_RELOC_RL78_DIFF;
561 1.1 christos }
562 1.1 christos
563 1.1 christos fix_new_exp (frag, where, (int) size, exp, 0, type);
564 1.1 christos }
565 1.1 christos
566 1.1 christos /* No relaxation just yet */
567 1.1 christos int
568 1.1 christos md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED, segT segment ATTRIBUTE_UNUSED)
569 1.1 christos {
570 1.1 christos return 0;
571 1.1 christos }
572 1.1 christos
573 1.1 christos arelent **
574 1.1 christos tc_gen_reloc (asection * seg ATTRIBUTE_UNUSED, fixS * fixp)
575 1.1 christos {
576 1.1 christos static arelent * reloc[8];
577 1.1 christos int rp;
578 1.1 christos
579 1.1 christos if (fixp->fx_r_type == BFD_RELOC_NONE)
580 1.1 christos {
581 1.1 christos reloc[0] = NULL;
582 1.1 christos return reloc;
583 1.1 christos }
584 1.1 christos
585 1.1 christos if (fixp->fx_subsy
586 1.1 christos && S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
587 1.1 christos {
588 1.1 christos fixp->fx_offset -= S_GET_VALUE (fixp->fx_subsy);
589 1.1 christos fixp->fx_subsy = NULL;
590 1.1 christos }
591 1.1 christos
592 1.1 christos reloc[0] = (arelent *) xmalloc (sizeof (arelent));
593 1.1 christos reloc[0]->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
594 1.1 christos * reloc[0]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
595 1.1 christos reloc[0]->address = fixp->fx_frag->fr_address + fixp->fx_where;
596 1.1 christos reloc[0]->addend = fixp->fx_offset;
597 1.1 christos
598 1.1 christos if (fixp->fx_r_type == BFD_RELOC_RL78_32_OP
599 1.1 christos && fixp->fx_subsy)
600 1.1 christos {
601 1.1 christos fixp->fx_r_type = BFD_RELOC_RL78_DIFF;
602 1.1 christos }
603 1.1 christos
604 1.1 christos #define OPX(REL,SYM,ADD) \
605 1.1 christos reloc[rp] = (arelent *) xmalloc (sizeof (arelent)); \
606 1.1 christos reloc[rp]->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); \
607 1.1 christos reloc[rp]->howto = bfd_reloc_type_lookup (stdoutput, REL); \
608 1.1 christos reloc[rp]->addend = ADD; \
609 1.1 christos * reloc[rp]->sym_ptr_ptr = SYM; \
610 1.1 christos reloc[rp]->address = fixp->fx_frag->fr_address + fixp->fx_where; \
611 1.1 christos reloc[++rp] = NULL
612 1.1 christos #define OPSYM(SYM) OPX(BFD_RELOC_RL78_SYM, SYM, 0)
613 1.1 christos #define OPIMM(IMM) OPX(BFD_RELOC_RL78_SYM, abs_symbol.bsym, IMM)
614 1.1 christos #define OP(OP) OPX(BFD_RELOC_RL78_##OP, *reloc[0]->sym_ptr_ptr, 0)
615 1.1 christos #define SYM0() reloc[0]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_RL78_SYM)
616 1.1 christos
617 1.1 christos rp = 1;
618 1.1 christos
619 1.1 christos /* Certain BFD relocations cannot be translated directly into
620 1.1 christos a single (non-Red Hat) RL78 relocation, but instead need
621 1.1 christos multiple RL78 relocations - handle them here. */
622 1.1 christos switch (fixp->fx_r_type)
623 1.1 christos {
624 1.1 christos case BFD_RELOC_RL78_DIFF:
625 1.1 christos SYM0 ();
626 1.1 christos OPSYM (symbol_get_bfdsym (fixp->fx_subsy));
627 1.1 christos OP(OP_SUBTRACT);
628 1.1 christos
629 1.1 christos switch (fixp->fx_size)
630 1.1 christos {
631 1.1 christos case 1:
632 1.1 christos OP(ABS8);
633 1.1 christos break;
634 1.1 christos case 2:
635 1.1 christos OP (ABS16);
636 1.1 christos break;
637 1.1 christos case 4:
638 1.1 christos OP (ABS32);
639 1.1 christos break;
640 1.1 christos }
641 1.1 christos break;
642 1.1 christos
643 1.1 christos case BFD_RELOC_RL78_NEG32:
644 1.1 christos SYM0 ();
645 1.1 christos OP (OP_NEG);
646 1.1 christos OP (ABS32);
647 1.1 christos break;
648 1.1 christos
649 1.1 christos case BFD_RELOC_RL78_LO16:
650 1.1 christos SYM0 ();
651 1.1 christos OPIMM (0xffff);
652 1.1 christos OP (OP_AND);
653 1.1 christos OP (ABS16);
654 1.1 christos break;
655 1.1 christos
656 1.1 christos case BFD_RELOC_RL78_HI16:
657 1.1 christos SYM0 ();
658 1.1 christos OPIMM (16);
659 1.1 christos OP (OP_SHRA);
660 1.1 christos OP (ABS16);
661 1.1 christos break;
662 1.1 christos
663 1.1 christos case BFD_RELOC_RL78_HI8:
664 1.1 christos SYM0 ();
665 1.1 christos OPIMM (16);
666 1.1 christos OP (OP_SHRA);
667 1.1 christos OPIMM (0xff);
668 1.1 christos OP (OP_AND);
669 1.1 christos OP (ABS8);
670 1.1 christos break;
671 1.1 christos
672 1.1 christos default:
673 1.1 christos reloc[0]->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
674 1.1 christos reloc[1] = NULL;
675 1.1 christos break;
676 1.1 christos }
677 1.1 christos
678 1.1 christos return reloc;
679 1.1 christos }
680 1.1 christos
681 1.1 christos int
682 1.1 christos rl78_validate_fix_sub (struct fix * f)
683 1.1 christos {
684 1.1 christos /* We permit the subtraction of two symbols in a few cases. */
685 1.1 christos /* mov #sym1-sym2, R3 */
686 1.1 christos if (f->fx_r_type == BFD_RELOC_RL78_32_OP)
687 1.1 christos return 1;
688 1.1 christos /* .long sym1-sym2 */
689 1.1 christos if (f->fx_r_type == BFD_RELOC_RL78_DIFF
690 1.1 christos && ! f->fx_pcrel
691 1.1 christos && (f->fx_size == 4 || f->fx_size == 2 || f->fx_size == 1))
692 1.1 christos return 1;
693 1.1 christos return 0;
694 1.1 christos }
695 1.1 christos
696 1.1 christos long
697 1.1 christos md_pcrel_from_section (fixS * fixP, segT sec)
698 1.1 christos {
699 1.1 christos long rv;
700 1.1 christos
701 1.1 christos if (fixP->fx_addsy != NULL
702 1.1 christos && (! S_IS_DEFINED (fixP->fx_addsy)
703 1.1 christos || S_GET_SEGMENT (fixP->fx_addsy) != sec))
704 1.1 christos /* The symbol is undefined (or is defined but not in this section).
705 1.1 christos Let the linker figure it out. */
706 1.1 christos return 0;
707 1.1 christos
708 1.1 christos rv = fixP->fx_frag->fr_address + fixP->fx_where;
709 1.1 christos switch (fixP->fx_r_type)
710 1.1 christos {
711 1.1 christos case BFD_RELOC_8_PCREL:
712 1.1 christos rv += 1;
713 1.1 christos break;
714 1.1 christos case BFD_RELOC_16_PCREL:
715 1.1 christos rv += 2;
716 1.1 christos break;
717 1.1 christos default:
718 1.1 christos break;
719 1.1 christos }
720 1.1 christos return rv;
721 1.1 christos }
722 1.1 christos
723 1.1 christos void
724 1.1 christos md_apply_fix (struct fix * f ATTRIBUTE_UNUSED,
725 1.1 christos valueT * t ATTRIBUTE_UNUSED,
726 1.1 christos segT s ATTRIBUTE_UNUSED)
727 1.1 christos {
728 1.1 christos char * op;
729 1.1 christos unsigned long val;
730 1.1 christos
731 1.1 christos if (f->fx_addsy && S_FORCE_RELOC (f->fx_addsy, 1))
732 1.1 christos return;
733 1.1 christos if (f->fx_subsy && S_FORCE_RELOC (f->fx_subsy, 1))
734 1.1 christos return;
735 1.1 christos
736 1.1 christos op = f->fx_frag->fr_literal + f->fx_where;
737 1.1 christos val = (unsigned long) * t;
738 1.1 christos
739 1.1 christos switch (f->fx_r_type)
740 1.1 christos {
741 1.1 christos case BFD_RELOC_NONE:
742 1.1 christos break;
743 1.1 christos
744 1.1 christos case BFD_RELOC_RL78_RELAX:
745 1.1 christos f->fx_done = 1;
746 1.1 christos break;
747 1.1 christos
748 1.1 christos case BFD_RELOC_8:
749 1.1 christos case BFD_RELOC_8_PCREL:
750 1.1 christos op[0] = val;
751 1.1 christos break;
752 1.1 christos
753 1.1 christos case BFD_RELOC_16:
754 1.1 christos case BFD_RELOC_16_PCREL:
755 1.1 christos op[0] = val;
756 1.1 christos op[1] = val >> 8;
757 1.1 christos break;
758 1.1 christos
759 1.1 christos case BFD_RELOC_24:
760 1.1 christos op[0] = val;
761 1.1 christos op[1] = val >> 8;
762 1.1 christos op[2] = val >> 16;
763 1.1 christos break;
764 1.1 christos
765 1.1 christos case BFD_RELOC_32:
766 1.1 christos case BFD_RELOC_RL78_DIFF:
767 1.1 christos op[0] = val;
768 1.1 christos op[1] = val >> 8;
769 1.1 christos op[2] = val >> 16;
770 1.1 christos op[3] = val >> 24;
771 1.1 christos break;
772 1.1 christos
773 1.1 christos default:
774 1.1 christos as_bad (_("Unknown reloc in md_apply_fix: %s"),
775 1.1 christos bfd_get_reloc_code_name (f->fx_r_type));
776 1.1 christos break;
777 1.1 christos }
778 1.1 christos
779 1.1 christos if (f->fx_addsy == NULL)
780 1.1 christos f->fx_done = 1;
781 1.1 christos }
782 1.1 christos
783 1.1 christos valueT
784 1.1 christos md_section_align (segT segment, valueT size)
785 1.1 christos {
786 1.1 christos int align = bfd_get_section_alignment (stdoutput, segment);
787 1.1 christos return ((size + (1 << align) - 1) & (-1 << align));
788 1.1 christos }
789 1.1 christos
790 1.1 christos void
791 1.1 christos md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
792 1.1 christos segT segment ATTRIBUTE_UNUSED,
793 1.1 christos fragS * fragP ATTRIBUTE_UNUSED)
794 1.1 christos {
795 1.1 christos /* No relaxation yet */
796 1.1 christos fragP->fr_var = 0;
797 1.1 christos }
798