tc-rl78.c revision 1.1.1.1.2.1 1 1.1 christos /* tc-rl78.c -- Assembler for the Renesas RL78
2 1.1.1.1.2.1 pgoyette Copyright (C) 2011-2015 Free Software Foundation, Inc.
3 1.1 christos
4 1.1 christos This file is part of GAS, the GNU Assembler.
5 1.1 christos
6 1.1 christos GAS is free software; you can redistribute it and/or modify
7 1.1 christos it under the terms of the GNU General Public License as published by
8 1.1 christos the Free Software Foundation; either version 3, or (at your option)
9 1.1 christos any later version.
10 1.1 christos
11 1.1 christos GAS is distributed in the hope that it will be useful,
12 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
13 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 1.1 christos GNU General Public License for more details.
15 1.1 christos
16 1.1 christos You should have received a copy of the GNU General Public License
17 1.1 christos along with GAS; see the file COPYING. If not, write to the Free
18 1.1 christos Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
19 1.1 christos 02110-1301, USA. */
20 1.1 christos
21 1.1 christos #include "as.h"
22 1.1 christos #include "struc-symbol.h"
23 1.1 christos #include "safe-ctype.h"
24 1.1 christos #include "dwarf2dbg.h"
25 1.1 christos #include "libbfd.h"
26 1.1 christos #include "elf/common.h"
27 1.1 christos #include "elf/rl78.h"
28 1.1 christos #include "rl78-defs.h"
29 1.1 christos #include "filenames.h"
30 1.1 christos #include "listing.h"
31 1.1 christos #include "sb.h"
32 1.1 christos #include "macro.h"
33 1.1 christos
34 1.1 christos const char comment_chars[] = ";";
35 1.1 christos /* Note that input_file.c hand checks for '#' at the beginning of the
36 1.1 christos first line of the input file. This is because the compiler outputs
37 1.1 christos #NO_APP at the beginning of its output. */
38 1.1 christos const char line_comment_chars[] = "#";
39 1.1.1.1.2.1 pgoyette /* Use something that isn't going to be needed by any expressions or
40 1.1.1.1.2.1 pgoyette other syntax. */
41 1.1.1.1.2.1 pgoyette 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.1.1.2.1 pgoyette /* ELF flags to set in the output file header. */
47 1.1.1.1.2.1 pgoyette static int elf_flags = 0;
48 1.1.1.1.2.1 pgoyette
49 1.1 christos /*------------------------------------------------------------------*/
50 1.1 christos
51 1.1 christos char * rl78_lex_start;
52 1.1 christos char * rl78_lex_end;
53 1.1 christos
54 1.1 christos typedef struct rl78_bytesT
55 1.1 christos {
56 1.1 christos char prefix[1];
57 1.1 christos int n_prefix;
58 1.1 christos char base[4];
59 1.1 christos int n_base;
60 1.1 christos char ops[8];
61 1.1 christos int n_ops;
62 1.1 christos struct
63 1.1 christos {
64 1.1 christos expressionS exp;
65 1.1 christos char offset;
66 1.1 christos char nbits;
67 1.1 christos char type; /* RL78REL_*. */
68 1.1 christos int reloc;
69 1.1 christos fixS * fixP;
70 1.1 christos } fixups[2];
71 1.1 christos int n_fixups;
72 1.1 christos struct
73 1.1 christos {
74 1.1 christos char type;
75 1.1 christos char field_pos;
76 1.1 christos char val_ofs;
77 1.1 christos } relax[2];
78 1.1 christos int n_relax;
79 1.1 christos int link_relax;
80 1.1 christos fixS *link_relax_fixP;
81 1.1 christos char times_grown;
82 1.1 christos char times_shrank;
83 1.1 christos } rl78_bytesT;
84 1.1 christos
85 1.1 christos static rl78_bytesT rl78_bytes;
86 1.1 christos
87 1.1 christos void
88 1.1.1.1.2.1 pgoyette rl78_relax (int type, int pos)
89 1.1.1.1.2.1 pgoyette {
90 1.1.1.1.2.1 pgoyette rl78_bytes.relax[rl78_bytes.n_relax].type = type;
91 1.1.1.1.2.1 pgoyette rl78_bytes.relax[rl78_bytes.n_relax].field_pos = pos;
92 1.1.1.1.2.1 pgoyette rl78_bytes.relax[rl78_bytes.n_relax].val_ofs = rl78_bytes.n_base + rl78_bytes.n_ops;
93 1.1.1.1.2.1 pgoyette rl78_bytes.n_relax ++;
94 1.1.1.1.2.1 pgoyette }
95 1.1.1.1.2.1 pgoyette
96 1.1.1.1.2.1 pgoyette void
97 1.1 christos rl78_linkrelax_addr16 (void)
98 1.1 christos {
99 1.1 christos rl78_bytes.link_relax |= RL78_RELAXA_ADDR16;
100 1.1 christos }
101 1.1 christos
102 1.1 christos void
103 1.1 christos rl78_linkrelax_branch (void)
104 1.1 christos {
105 1.1 christos rl78_bytes.link_relax |= RL78_RELAXA_BRA;
106 1.1 christos }
107 1.1 christos
108 1.1 christos static void
109 1.1 christos rl78_fixup (expressionS exp, int offsetbits, int nbits, int type)
110 1.1 christos {
111 1.1 christos rl78_bytes.fixups[rl78_bytes.n_fixups].exp = exp;
112 1.1 christos rl78_bytes.fixups[rl78_bytes.n_fixups].offset = offsetbits;
113 1.1 christos rl78_bytes.fixups[rl78_bytes.n_fixups].nbits = nbits;
114 1.1 christos rl78_bytes.fixups[rl78_bytes.n_fixups].type = type;
115 1.1 christos rl78_bytes.fixups[rl78_bytes.n_fixups].reloc = exp.X_md;
116 1.1 christos rl78_bytes.n_fixups ++;
117 1.1 christos }
118 1.1 christos
119 1.1 christos #define rl78_field_fixup(exp, offset, nbits, type) \
120 1.1 christos rl78_fixup (exp, offset + 8 * rl78_bytes.n_prefix), nbits, type)
121 1.1 christos
122 1.1 christos #define rl78_op_fixup(exp, offset, nbits, type) \
123 1.1 christos rl78_fixup (exp, offset + 8 * (rl78_bytes.n_prefix + rl78_bytes.n_base), nbits, type)
124 1.1 christos
125 1.1 christos void
126 1.1 christos rl78_prefix (int p)
127 1.1 christos {
128 1.1 christos rl78_bytes.prefix[0] = p;
129 1.1 christos rl78_bytes.n_prefix = 1;
130 1.1 christos }
131 1.1 christos
132 1.1 christos int
133 1.1 christos rl78_has_prefix ()
134 1.1 christos {
135 1.1 christos return rl78_bytes.n_prefix;
136 1.1 christos }
137 1.1 christos
138 1.1 christos void
139 1.1 christos rl78_base1 (int b1)
140 1.1 christos {
141 1.1 christos rl78_bytes.base[0] = b1;
142 1.1 christos rl78_bytes.n_base = 1;
143 1.1 christos }
144 1.1 christos
145 1.1 christos void
146 1.1 christos rl78_base2 (int b1, int b2)
147 1.1 christos {
148 1.1 christos rl78_bytes.base[0] = b1;
149 1.1 christos rl78_bytes.base[1] = b2;
150 1.1 christos rl78_bytes.n_base = 2;
151 1.1 christos }
152 1.1 christos
153 1.1 christos void
154 1.1 christos rl78_base3 (int b1, int b2, int b3)
155 1.1 christos {
156 1.1 christos rl78_bytes.base[0] = b1;
157 1.1 christos rl78_bytes.base[1] = b2;
158 1.1 christos rl78_bytes.base[2] = b3;
159 1.1 christos rl78_bytes.n_base = 3;
160 1.1 christos }
161 1.1 christos
162 1.1 christos void
163 1.1 christos rl78_base4 (int b1, int b2, int b3, int b4)
164 1.1 christos {
165 1.1 christos rl78_bytes.base[0] = b1;
166 1.1 christos rl78_bytes.base[1] = b2;
167 1.1 christos rl78_bytes.base[2] = b3;
168 1.1 christos rl78_bytes.base[3] = b4;
169 1.1 christos rl78_bytes.n_base = 4;
170 1.1 christos }
171 1.1 christos
172 1.1 christos #define F_PRECISION 2
173 1.1 christos
174 1.1 christos void
175 1.1 christos rl78_op (expressionS exp, int nbytes, int type)
176 1.1 christos {
177 1.1 christos int v = 0;
178 1.1 christos
179 1.1 christos if ((exp.X_op == O_constant || exp.X_op == O_big)
180 1.1 christos && type != RL78REL_PCREL)
181 1.1 christos {
182 1.1 christos if (exp.X_op == O_big && exp.X_add_number <= 0)
183 1.1 christos {
184 1.1 christos LITTLENUM_TYPE w[2];
185 1.1 christos char * ip = rl78_bytes.ops + rl78_bytes.n_ops;
186 1.1 christos
187 1.1 christos gen_to_words (w, F_PRECISION, 8);
188 1.1 christos ip[3] = w[0] >> 8;
189 1.1 christos ip[2] = w[0];
190 1.1 christos ip[1] = w[1] >> 8;
191 1.1 christos ip[0] = w[1];
192 1.1 christos rl78_bytes.n_ops += 4;
193 1.1 christos }
194 1.1 christos else
195 1.1 christos {
196 1.1 christos v = exp.X_add_number;
197 1.1 christos while (nbytes)
198 1.1 christos {
199 1.1 christos rl78_bytes.ops[rl78_bytes.n_ops++] =v & 0xff;
200 1.1 christos v >>= 8;
201 1.1 christos nbytes --;
202 1.1 christos }
203 1.1 christos }
204 1.1 christos }
205 1.1 christos else
206 1.1 christos {
207 1.1.1.1.2.1 pgoyette if (nbytes > 2
208 1.1.1.1.2.1 pgoyette && exp.X_md == BFD_RELOC_RL78_CODE)
209 1.1.1.1.2.1 pgoyette exp.X_md = 0;
210 1.1.1.1.2.1 pgoyette
211 1.1.1.1.2.1 pgoyette if (nbytes == 1
212 1.1.1.1.2.1 pgoyette && (exp.X_md == BFD_RELOC_RL78_LO16
213 1.1.1.1.2.1 pgoyette || exp.X_md == BFD_RELOC_RL78_HI16))
214 1.1.1.1.2.1 pgoyette as_bad (_("16-bit relocation used in 8-bit operand"));
215 1.1.1.1.2.1 pgoyette
216 1.1.1.1.2.1 pgoyette if (nbytes == 2
217 1.1.1.1.2.1 pgoyette && exp.X_md == BFD_RELOC_RL78_HI8)
218 1.1.1.1.2.1 pgoyette as_bad (_("8-bit relocation used in 16-bit operand"));
219 1.1.1.1.2.1 pgoyette
220 1.1 christos rl78_op_fixup (exp, rl78_bytes.n_ops * 8, nbytes * 8, type);
221 1.1 christos memset (rl78_bytes.ops + rl78_bytes.n_ops, 0, nbytes);
222 1.1 christos rl78_bytes.n_ops += nbytes;
223 1.1 christos }
224 1.1 christos }
225 1.1 christos
226 1.1 christos /* This gets complicated when the field spans bytes, because fields
227 1.1 christos are numbered from the MSB of the first byte as zero, and bits are
228 1.1 christos stored LSB towards the LSB of the byte. Thus, a simple four-bit
229 1.1 christos insertion of 12 at position 4 of 0x00 yields: 0x0b. A three-bit
230 1.1 christos insertion of b'MXL at position 7 is like this:
231 1.1 christos
232 1.1 christos - - - - - - - - - - - - - - - -
233 1.1 christos M X L */
234 1.1 christos
235 1.1 christos void
236 1.1 christos rl78_field (int val, int pos, int sz)
237 1.1 christos {
238 1.1 christos int valm;
239 1.1 christos int bytep, bitp;
240 1.1 christos
241 1.1 christos if (sz > 0)
242 1.1 christos {
243 1.1 christos if (val < 0 || val >= (1 << sz))
244 1.1 christos as_bad (_("Value %d doesn't fit in unsigned %d-bit field"), val, sz);
245 1.1 christos }
246 1.1 christos else
247 1.1 christos {
248 1.1 christos sz = - sz;
249 1.1 christos if (val < -(1 << (sz - 1)) || val >= (1 << (sz - 1)))
250 1.1 christos as_bad (_("Value %d doesn't fit in signed %d-bit field"), val, sz);
251 1.1 christos }
252 1.1 christos
253 1.1 christos /* This code points at 'M' in the above example. */
254 1.1 christos bytep = pos / 8;
255 1.1 christos bitp = pos % 8;
256 1.1 christos
257 1.1 christos while (bitp + sz > 8)
258 1.1 christos {
259 1.1 christos int ssz = 8 - bitp;
260 1.1 christos int svalm;
261 1.1 christos
262 1.1 christos svalm = val >> (sz - ssz);
263 1.1 christos svalm = svalm & ((1 << ssz) - 1);
264 1.1 christos svalm = svalm << (8 - bitp - ssz);
265 1.1 christos gas_assert (bytep < rl78_bytes.n_base);
266 1.1 christos rl78_bytes.base[bytep] |= svalm;
267 1.1 christos
268 1.1 christos bitp = 0;
269 1.1 christos sz -= ssz;
270 1.1 christos bytep ++;
271 1.1 christos }
272 1.1 christos valm = val & ((1 << sz) - 1);
273 1.1 christos valm = valm << (8 - bitp - sz);
274 1.1 christos gas_assert (bytep < rl78_bytes.n_base);
275 1.1 christos rl78_bytes.base[bytep] |= valm;
276 1.1 christos }
277 1.1 christos
278 1.1 christos /*------------------------------------------------------------------*/
279 1.1 christos
280 1.1 christos enum options
281 1.1 christos {
282 1.1 christos OPTION_RELAX = OPTION_MD_BASE,
283 1.1.1.1.2.1 pgoyette OPTION_G10,
284 1.1.1.1.2.1 pgoyette OPTION_G13,
285 1.1.1.1.2.1 pgoyette OPTION_G14,
286 1.1.1.1.2.1 pgoyette OPTION_32BIT_DOUBLES,
287 1.1.1.1.2.1 pgoyette OPTION_64BIT_DOUBLES,
288 1.1 christos };
289 1.1 christos
290 1.1 christos #define RL78_SHORTOPTS ""
291 1.1 christos const char * md_shortopts = RL78_SHORTOPTS;
292 1.1 christos
293 1.1 christos /* Assembler options. */
294 1.1 christos struct option md_longopts[] =
295 1.1 christos {
296 1.1 christos {"relax", no_argument, NULL, OPTION_RELAX},
297 1.1.1.1.2.1 pgoyette {"mg10", no_argument, NULL, OPTION_G10},
298 1.1.1.1.2.1 pgoyette {"mg13", no_argument, NULL, OPTION_G13},
299 1.1.1.1.2.1 pgoyette {"mg14", no_argument, NULL, OPTION_G14},
300 1.1.1.1.2.1 pgoyette {"mrl78", no_argument, NULL, OPTION_G14},
301 1.1.1.1.2.1 pgoyette {"m32bit-doubles", no_argument, NULL, OPTION_32BIT_DOUBLES},
302 1.1.1.1.2.1 pgoyette {"m64bit-doubles", no_argument, NULL, OPTION_64BIT_DOUBLES},
303 1.1 christos {NULL, no_argument, NULL, 0}
304 1.1 christos };
305 1.1 christos size_t md_longopts_size = sizeof (md_longopts);
306 1.1 christos
307 1.1 christos int
308 1.1 christos md_parse_option (int c, char * arg ATTRIBUTE_UNUSED)
309 1.1 christos {
310 1.1 christos switch (c)
311 1.1 christos {
312 1.1 christos case OPTION_RELAX:
313 1.1 christos linkrelax = 1;
314 1.1 christos return 1;
315 1.1 christos
316 1.1.1.1.2.1 pgoyette case OPTION_G10:
317 1.1.1.1.2.1 pgoyette elf_flags &= ~ E_FLAG_RL78_CPU_MASK;
318 1.1.1.1.2.1 pgoyette elf_flags |= E_FLAG_RL78_G10;
319 1.1.1.1.2.1 pgoyette return 1;
320 1.1.1.1.2.1 pgoyette
321 1.1.1.1.2.1 pgoyette case OPTION_G13:
322 1.1.1.1.2.1 pgoyette elf_flags &= ~ E_FLAG_RL78_CPU_MASK;
323 1.1.1.1.2.1 pgoyette elf_flags |= E_FLAG_RL78_G13;
324 1.1.1.1.2.1 pgoyette return 1;
325 1.1.1.1.2.1 pgoyette
326 1.1.1.1.2.1 pgoyette case OPTION_G14:
327 1.1.1.1.2.1 pgoyette elf_flags &= ~ E_FLAG_RL78_CPU_MASK;
328 1.1.1.1.2.1 pgoyette elf_flags |= E_FLAG_RL78_G14;
329 1.1.1.1.2.1 pgoyette return 1;
330 1.1.1.1.2.1 pgoyette
331 1.1.1.1.2.1 pgoyette case OPTION_32BIT_DOUBLES:
332 1.1.1.1.2.1 pgoyette elf_flags &= ~ E_FLAG_RL78_64BIT_DOUBLES;
333 1.1.1.1.2.1 pgoyette return 1;
334 1.1.1.1.2.1 pgoyette
335 1.1.1.1.2.1 pgoyette case OPTION_64BIT_DOUBLES:
336 1.1.1.1.2.1 pgoyette elf_flags |= E_FLAG_RL78_64BIT_DOUBLES;
337 1.1.1.1.2.1 pgoyette return 1;
338 1.1 christos }
339 1.1 christos return 0;
340 1.1 christos }
341 1.1 christos
342 1.1.1.1.2.1 pgoyette int
343 1.1.1.1.2.1 pgoyette rl78_isa_g10 (void)
344 1.1 christos {
345 1.1.1.1.2.1 pgoyette return (elf_flags & E_FLAG_RL78_CPU_MASK) == E_FLAG_RL78_G10;
346 1.1 christos }
347 1.1 christos
348 1.1.1.1.2.1 pgoyette int
349 1.1.1.1.2.1 pgoyette rl78_isa_g13 (void)
350 1.1.1.1.2.1 pgoyette {
351 1.1.1.1.2.1 pgoyette return (elf_flags & E_FLAG_RL78_CPU_MASK) == E_FLAG_RL78_G13;
352 1.1.1.1.2.1 pgoyette }
353 1.1.1.1.2.1 pgoyette
354 1.1.1.1.2.1 pgoyette int
355 1.1.1.1.2.1 pgoyette rl78_isa_g14 (void)
356 1.1.1.1.2.1 pgoyette {
357 1.1.1.1.2.1 pgoyette return (elf_flags & E_FLAG_RL78_CPU_MASK) == E_FLAG_RL78_G14;
358 1.1.1.1.2.1 pgoyette }
359 1.1.1.1.2.1 pgoyette
360 1.1.1.1.2.1 pgoyette void
361 1.1.1.1.2.1 pgoyette md_show_usage (FILE * stream)
362 1.1.1.1.2.1 pgoyette {
363 1.1.1.1.2.1 pgoyette fprintf (stream, _(" RL78 specific command line options:\n"));
364 1.1.1.1.2.1 pgoyette fprintf (stream, _(" --mrelax Enable link time relaxation\n"));
365 1.1.1.1.2.1 pgoyette fprintf (stream, _(" --mg10 Enable support for G10 variant\n"));
366 1.1.1.1.2.1 pgoyette fprintf (stream, _(" --mg13 Selects the G13 core.\n"));
367 1.1.1.1.2.1 pgoyette fprintf (stream, _(" --mg14 Selects the G14 core [default]\n"));
368 1.1.1.1.2.1 pgoyette fprintf (stream, _(" --mrl78 Alias for --mg14\n"));
369 1.1.1.1.2.1 pgoyette fprintf (stream, _(" --m32bit-doubles [default]\n"));
370 1.1.1.1.2.1 pgoyette fprintf (stream, _(" --m64bit-doubles Source code uses 64-bit doubles\n"));
371 1.1.1.1.2.1 pgoyette }
372 1.1 christos
373 1.1 christos static void
374 1.1 christos s_bss (int ignore ATTRIBUTE_UNUSED)
375 1.1 christos {
376 1.1 christos int temp;
377 1.1 christos
378 1.1 christos temp = get_absolute_expression ();
379 1.1 christos subseg_set (bss_section, (subsegT) temp);
380 1.1 christos demand_empty_rest_of_line ();
381 1.1 christos }
382 1.1 christos
383 1.1.1.1.2.1 pgoyette static void
384 1.1.1.1.2.1 pgoyette rl78_float_cons (int ignore ATTRIBUTE_UNUSED)
385 1.1.1.1.2.1 pgoyette {
386 1.1.1.1.2.1 pgoyette if (elf_flags & E_FLAG_RL78_64BIT_DOUBLES)
387 1.1.1.1.2.1 pgoyette return float_cons ('d');
388 1.1.1.1.2.1 pgoyette return float_cons ('f');
389 1.1.1.1.2.1 pgoyette }
390 1.1.1.1.2.1 pgoyette
391 1.1 christos /* The target specific pseudo-ops which we support. */
392 1.1 christos const pseudo_typeS md_pseudo_table[] =
393 1.1 christos {
394 1.1.1.1.2.1 pgoyette /* Our "standard" pseudos. */
395 1.1.1.1.2.1 pgoyette { "double", rl78_float_cons, 'd' },
396 1.1.1.1.2.1 pgoyette { "bss", s_bss, 0 },
397 1.1.1.1.2.1 pgoyette { "3byte", cons, 3 },
398 1.1.1.1.2.1 pgoyette { "int", cons, 4 },
399 1.1.1.1.2.1 pgoyette { "word", cons, 4 },
400 1.1 christos
401 1.1 christos /* End of list marker. */
402 1.1 christos { NULL, NULL, 0 }
403 1.1 christos };
404 1.1 christos
405 1.1.1.1.2.1 pgoyette static symbolS * rl78_abs_sym = NULL;
406 1.1.1.1.2.1 pgoyette
407 1.1 christos void
408 1.1 christos md_begin (void)
409 1.1 christos {
410 1.1.1.1.2.1 pgoyette rl78_abs_sym = symbol_make ("__rl78_abs__");
411 1.1 christos }
412 1.1 christos
413 1.1 christos void
414 1.1 christos rl78_md_end (void)
415 1.1 christos {
416 1.1 christos }
417 1.1 christos
418 1.1.1.1.2.1 pgoyette /* Set the ELF specific flags. */
419 1.1.1.1.2.1 pgoyette void
420 1.1.1.1.2.1 pgoyette rl78_elf_final_processing (void)
421 1.1.1.1.2.1 pgoyette {
422 1.1.1.1.2.1 pgoyette elf_elfheader (stdoutput)->e_flags |= elf_flags;
423 1.1.1.1.2.1 pgoyette }
424 1.1.1.1.2.1 pgoyette
425 1.1 christos /* Write a value out to the object file, using the appropriate endianness. */
426 1.1 christos void
427 1.1 christos md_number_to_chars (char * buf, valueT val, int n)
428 1.1 christos {
429 1.1 christos number_to_chars_littleendian (buf, val, n);
430 1.1 christos }
431 1.1 christos
432 1.1.1.1.2.1 pgoyette static void
433 1.1.1.1.2.1 pgoyette require_end_of_expr (char *fname)
434 1.1.1.1.2.1 pgoyette {
435 1.1.1.1.2.1 pgoyette while (* input_line_pointer == ' '
436 1.1.1.1.2.1 pgoyette || * input_line_pointer == '\t')
437 1.1.1.1.2.1 pgoyette input_line_pointer ++;
438 1.1.1.1.2.1 pgoyette
439 1.1.1.1.2.1 pgoyette if (! * input_line_pointer
440 1.1.1.1.2.1 pgoyette || strchr ("\n\r,", * input_line_pointer)
441 1.1.1.1.2.1 pgoyette || strchr (comment_chars, * input_line_pointer)
442 1.1.1.1.2.1 pgoyette || strchr (line_comment_chars, * input_line_pointer)
443 1.1.1.1.2.1 pgoyette || strchr (line_separator_chars, * input_line_pointer))
444 1.1.1.1.2.1 pgoyette return;
445 1.1.1.1.2.1 pgoyette
446 1.1.1.1.2.1 pgoyette as_bad (_("%%%s() must be outermost term in expression"), fname);
447 1.1.1.1.2.1 pgoyette }
448 1.1.1.1.2.1 pgoyette
449 1.1 christos static struct
450 1.1 christos {
451 1.1 christos char * fname;
452 1.1 christos int reloc;
453 1.1 christos }
454 1.1 christos reloc_functions[] =
455 1.1 christos {
456 1.1.1.1.2.1 pgoyette { "code", BFD_RELOC_RL78_CODE },
457 1.1 christos { "lo16", BFD_RELOC_RL78_LO16 },
458 1.1 christos { "hi16", BFD_RELOC_RL78_HI16 },
459 1.1 christos { "hi8", BFD_RELOC_RL78_HI8 },
460 1.1 christos { 0, 0 }
461 1.1 christos };
462 1.1 christos
463 1.1 christos void
464 1.1 christos md_operand (expressionS * exp ATTRIBUTE_UNUSED)
465 1.1 christos {
466 1.1 christos int reloc = 0;
467 1.1 christos int i;
468 1.1 christos
469 1.1 christos for (i = 0; reloc_functions[i].fname; i++)
470 1.1 christos {
471 1.1 christos int flen = strlen (reloc_functions[i].fname);
472 1.1 christos
473 1.1 christos if (input_line_pointer[0] == '%'
474 1.1 christos && strncasecmp (input_line_pointer + 1, reloc_functions[i].fname, flen) == 0
475 1.1 christos && input_line_pointer[flen + 1] == '(')
476 1.1 christos {
477 1.1 christos reloc = reloc_functions[i].reloc;
478 1.1 christos input_line_pointer += flen + 2;
479 1.1 christos break;
480 1.1 christos }
481 1.1 christos }
482 1.1 christos if (reloc == 0)
483 1.1 christos return;
484 1.1 christos
485 1.1 christos expression (exp);
486 1.1 christos if (* input_line_pointer == ')')
487 1.1 christos input_line_pointer ++;
488 1.1 christos
489 1.1 christos exp->X_md = reloc;
490 1.1.1.1.2.1 pgoyette
491 1.1.1.1.2.1 pgoyette require_end_of_expr (reloc_functions[i].fname);
492 1.1 christos }
493 1.1 christos
494 1.1 christos void
495 1.1 christos rl78_frag_init (fragS * fragP)
496 1.1 christos {
497 1.1 christos if (rl78_bytes.n_relax || rl78_bytes.link_relax)
498 1.1 christos {
499 1.1 christos fragP->tc_frag_data = malloc (sizeof (rl78_bytesT));
500 1.1 christos memcpy (fragP->tc_frag_data, & rl78_bytes, sizeof (rl78_bytesT));
501 1.1 christos }
502 1.1 christos else
503 1.1 christos fragP->tc_frag_data = 0;
504 1.1 christos }
505 1.1 christos
506 1.1 christos /* When relaxing, we need to output a reloc for any .align directive
507 1.1 christos so that we can retain this alignment as we adjust opcode sizes. */
508 1.1 christos void
509 1.1 christos rl78_handle_align (fragS * frag)
510 1.1 christos {
511 1.1 christos if (linkrelax
512 1.1 christos && (frag->fr_type == rs_align
513 1.1 christos || frag->fr_type == rs_align_code)
514 1.1 christos && frag->fr_address + frag->fr_fix > 0
515 1.1 christos && frag->fr_offset > 0
516 1.1 christos && now_seg != bss_section)
517 1.1 christos {
518 1.1 christos fix_new (frag, frag->fr_fix, 0,
519 1.1 christos &abs_symbol, RL78_RELAXA_ALIGN + frag->fr_offset,
520 1.1 christos 0, BFD_RELOC_RL78_RELAX);
521 1.1 christos /* For the purposes of relaxation, this relocation is attached
522 1.1 christos to the byte *after* the alignment - i.e. the byte that must
523 1.1 christos remain aligned. */
524 1.1 christos fix_new (frag->fr_next, 0, 0,
525 1.1 christos &abs_symbol, RL78_RELAXA_ELIGN + frag->fr_offset,
526 1.1 christos 0, BFD_RELOC_RL78_RELAX);
527 1.1 christos }
528 1.1 christos }
529 1.1 christos
530 1.1 christos char *
531 1.1 christos md_atof (int type, char * litP, int * sizeP)
532 1.1 christos {
533 1.1 christos return ieee_md_atof (type, litP, sizeP, target_big_endian);
534 1.1 christos }
535 1.1 christos
536 1.1 christos symbolS *
537 1.1 christos md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
538 1.1 christos {
539 1.1 christos return NULL;
540 1.1 christos }
541 1.1 christos
542 1.1 christos #define APPEND(B, N_B) \
543 1.1 christos if (rl78_bytes.N_B) \
544 1.1 christos { \
545 1.1 christos memcpy (bytes + idx, rl78_bytes.B, rl78_bytes.N_B); \
546 1.1 christos idx += rl78_bytes.N_B; \
547 1.1 christos }
548 1.1 christos
549 1.1 christos
550 1.1 christos void
551 1.1 christos md_assemble (char * str)
552 1.1 christos {
553 1.1 christos char * bytes;
554 1.1 christos fragS * frag_then = frag_now;
555 1.1 christos int idx = 0;
556 1.1 christos int i;
557 1.1 christos int rel;
558 1.1 christos expressionS *exp;
559 1.1 christos
560 1.1 christos /*printf("\033[32mASM: %s\033[0m\n", str);*/
561 1.1 christos
562 1.1 christos dwarf2_emit_insn (0);
563 1.1 christos
564 1.1 christos memset (& rl78_bytes, 0, sizeof (rl78_bytes));
565 1.1 christos
566 1.1 christos rl78_lex_init (str, str + strlen (str));
567 1.1 christos
568 1.1 christos rl78_parse ();
569 1.1 christos
570 1.1 christos /* This simplifies the relaxation code. */
571 1.1.1.1.2.1 pgoyette if (rl78_bytes.n_relax || rl78_bytes.link_relax)
572 1.1 christos {
573 1.1 christos int olen = rl78_bytes.n_prefix + rl78_bytes.n_base + rl78_bytes.n_ops;
574 1.1 christos /* We do it this way because we want the frag to have the
575 1.1.1.1.2.1 pgoyette rl78_bytes in it, which we initialize above. The extra bytes
576 1.1.1.1.2.1 pgoyette are for relaxing. */
577 1.1.1.1.2.1 pgoyette bytes = frag_more (olen + 3);
578 1.1 christos frag_then = frag_now;
579 1.1 christos frag_variant (rs_machine_dependent,
580 1.1 christos olen /* max_chars */,
581 1.1 christos 0 /* var */,
582 1.1 christos olen /* subtype */,
583 1.1 christos 0 /* symbol */,
584 1.1 christos 0 /* offset */,
585 1.1 christos 0 /* opcode */);
586 1.1 christos frag_then->fr_opcode = bytes;
587 1.1 christos frag_then->fr_fix = olen + (bytes - frag_then->fr_literal);
588 1.1 christos frag_then->fr_subtype = olen;
589 1.1 christos frag_then->fr_var = 0;
590 1.1 christos }
591 1.1 christos else
592 1.1 christos {
593 1.1 christos bytes = frag_more (rl78_bytes.n_prefix + rl78_bytes.n_base + rl78_bytes.n_ops);
594 1.1 christos frag_then = frag_now;
595 1.1 christos }
596 1.1 christos
597 1.1 christos APPEND (prefix, n_prefix);
598 1.1 christos APPEND (base, n_base);
599 1.1 christos APPEND (ops, n_ops);
600 1.1 christos
601 1.1 christos if (rl78_bytes.link_relax)
602 1.1 christos {
603 1.1 christos fixS * f;
604 1.1 christos
605 1.1 christos f = fix_new (frag_then,
606 1.1 christos (char *) bytes - frag_then->fr_literal,
607 1.1 christos 0,
608 1.1 christos abs_section_sym,
609 1.1 christos rl78_bytes.link_relax | rl78_bytes.n_fixups,
610 1.1 christos 0,
611 1.1 christos BFD_RELOC_RL78_RELAX);
612 1.1 christos frag_then->tc_frag_data->link_relax_fixP = f;
613 1.1 christos }
614 1.1 christos
615 1.1 christos for (i = 0; i < rl78_bytes.n_fixups; i ++)
616 1.1 christos {
617 1.1 christos /* index: [nbytes][type] */
618 1.1 christos static int reloc_map[5][4] =
619 1.1 christos {
620 1.1 christos { 0, 0 },
621 1.1 christos { BFD_RELOC_8, BFD_RELOC_8_PCREL },
622 1.1 christos { BFD_RELOC_16, BFD_RELOC_16_PCREL },
623 1.1 christos { BFD_RELOC_24, BFD_RELOC_24_PCREL },
624 1.1 christos { BFD_RELOC_32, BFD_RELOC_32_PCREL },
625 1.1 christos };
626 1.1 christos fixS * f;
627 1.1 christos
628 1.1 christos idx = rl78_bytes.fixups[i].offset / 8;
629 1.1 christos rel = reloc_map [rl78_bytes.fixups[i].nbits / 8][(int) rl78_bytes.fixups[i].type];
630 1.1 christos
631 1.1 christos if (rl78_bytes.fixups[i].reloc)
632 1.1 christos rel = rl78_bytes.fixups[i].reloc;
633 1.1 christos
634 1.1 christos if (frag_then->tc_frag_data)
635 1.1 christos exp = & frag_then->tc_frag_data->fixups[i].exp;
636 1.1 christos else
637 1.1 christos exp = & rl78_bytes.fixups[i].exp;
638 1.1 christos
639 1.1 christos f = fix_new_exp (frag_then,
640 1.1 christos (char *) bytes + idx - frag_then->fr_literal,
641 1.1 christos rl78_bytes.fixups[i].nbits / 8,
642 1.1 christos exp,
643 1.1 christos rl78_bytes.fixups[i].type == RL78REL_PCREL ? 1 : 0,
644 1.1 christos rel);
645 1.1 christos if (frag_then->tc_frag_data)
646 1.1 christos frag_then->tc_frag_data->fixups[i].fixP = f;
647 1.1 christos }
648 1.1 christos }
649 1.1 christos
650 1.1 christos void
651 1.1 christos rl78_cons_fix_new (fragS * frag,
652 1.1 christos int where,
653 1.1 christos int size,
654 1.1 christos expressionS * exp)
655 1.1 christos {
656 1.1 christos bfd_reloc_code_real_type type;
657 1.1.1.1.2.1 pgoyette fixS *fixP;
658 1.1 christos
659 1.1 christos switch (size)
660 1.1 christos {
661 1.1 christos case 1:
662 1.1 christos type = BFD_RELOC_8;
663 1.1 christos break;
664 1.1 christos case 2:
665 1.1 christos type = BFD_RELOC_16;
666 1.1 christos break;
667 1.1 christos case 3:
668 1.1 christos type = BFD_RELOC_24;
669 1.1 christos break;
670 1.1 christos case 4:
671 1.1 christos type = BFD_RELOC_32;
672 1.1 christos break;
673 1.1 christos default:
674 1.1 christos as_bad (_("unsupported constant size %d\n"), size);
675 1.1 christos return;
676 1.1 christos }
677 1.1 christos
678 1.1.1.1.2.1 pgoyette switch (exp->X_md)
679 1.1.1.1.2.1 pgoyette {
680 1.1.1.1.2.1 pgoyette case BFD_RELOC_RL78_CODE:
681 1.1.1.1.2.1 pgoyette if (size == 2)
682 1.1.1.1.2.1 pgoyette type = exp->X_md;
683 1.1.1.1.2.1 pgoyette break;
684 1.1.1.1.2.1 pgoyette case BFD_RELOC_RL78_LO16:
685 1.1.1.1.2.1 pgoyette case BFD_RELOC_RL78_HI16:
686 1.1.1.1.2.1 pgoyette if (size != 2)
687 1.1.1.1.2.1 pgoyette {
688 1.1.1.1.2.1 pgoyette /* Fixups to assembler generated expressions do not use %hi or %lo. */
689 1.1.1.1.2.1 pgoyette if (frag->fr_file)
690 1.1.1.1.2.1 pgoyette as_bad (_("%%hi16/%%lo16 only applies to .short or .hword"));
691 1.1.1.1.2.1 pgoyette }
692 1.1.1.1.2.1 pgoyette else
693 1.1.1.1.2.1 pgoyette type = exp->X_md;
694 1.1.1.1.2.1 pgoyette break;
695 1.1.1.1.2.1 pgoyette case BFD_RELOC_RL78_HI8:
696 1.1.1.1.2.1 pgoyette if (size != 1)
697 1.1.1.1.2.1 pgoyette {
698 1.1.1.1.2.1 pgoyette /* Fixups to assembler generated expressions do not use %hi or %lo. */
699 1.1.1.1.2.1 pgoyette if (frag->fr_file)
700 1.1.1.1.2.1 pgoyette as_bad (_("%%hi8 only applies to .byte"));
701 1.1.1.1.2.1 pgoyette }
702 1.1.1.1.2.1 pgoyette else
703 1.1.1.1.2.1 pgoyette type = exp->X_md;
704 1.1.1.1.2.1 pgoyette break;
705 1.1.1.1.2.1 pgoyette default:
706 1.1.1.1.2.1 pgoyette break;
707 1.1.1.1.2.1 pgoyette }
708 1.1.1.1.2.1 pgoyette
709 1.1 christos if (exp->X_op == O_subtract && exp->X_op_symbol)
710 1.1 christos {
711 1.1 christos if (size != 4 && size != 2 && size != 1)
712 1.1 christos as_bad (_("difference of two symbols only supported with .long, .short, or .byte"));
713 1.1 christos else
714 1.1 christos type = BFD_RELOC_RL78_DIFF;
715 1.1 christos }
716 1.1 christos
717 1.1.1.1.2.1 pgoyette fixP = fix_new_exp (frag, where, (int) size, exp, 0, type);
718 1.1.1.1.2.1 pgoyette switch (exp->X_md)
719 1.1.1.1.2.1 pgoyette {
720 1.1.1.1.2.1 pgoyette /* These are intended to have values larger than the container,
721 1.1.1.1.2.1 pgoyette since the backend puts only the portion we need in it.
722 1.1.1.1.2.1 pgoyette However, we don't have a backend-specific reloc for them as
723 1.1.1.1.2.1 pgoyette they're handled with complex relocations. */
724 1.1.1.1.2.1 pgoyette case BFD_RELOC_RL78_LO16:
725 1.1.1.1.2.1 pgoyette case BFD_RELOC_RL78_HI16:
726 1.1.1.1.2.1 pgoyette case BFD_RELOC_RL78_HI8:
727 1.1.1.1.2.1 pgoyette fixP->fx_no_overflow = 1;
728 1.1.1.1.2.1 pgoyette break;
729 1.1.1.1.2.1 pgoyette default:
730 1.1.1.1.2.1 pgoyette break;
731 1.1.1.1.2.1 pgoyette }
732 1.1.1.1.2.1 pgoyette }
733 1.1.1.1.2.1 pgoyette
734 1.1.1.1.2.1 pgoyette
735 1.1.1.1.2.1 pgoyette /*----------------------------------------------------------------------*/
737 1.1.1.1.2.1 pgoyette /* To recap: we estimate everything based on md_estimate_size, then
738 1.1.1.1.2.1 pgoyette adjust based on rl78_relax_frag. When it all settles, we call
739 1.1.1.1.2.1 pgoyette md_convert frag to update the bytes. The relaxation types and
740 1.1.1.1.2.1 pgoyette relocations are in fragP->tc_frag_data, which is a copy of that
741 1.1.1.1.2.1 pgoyette rl78_bytes.
742 1.1.1.1.2.1 pgoyette
743 1.1.1.1.2.1 pgoyette Our scheme is as follows: fr_fix has the size of the smallest
744 1.1.1.1.2.1 pgoyette opcode (like BRA.S). We store the number of total bytes we need in
745 1.1.1.1.2.1 pgoyette fr_subtype. When we're done relaxing, we use fr_subtype and the
746 1.1.1.1.2.1 pgoyette existing opcode bytes to figure out what actual opcode we need to
747 1.1.1.1.2.1 pgoyette put in there. If the fixup isn't resolvable now, we use the
748 1.1.1.1.2.1 pgoyette maximal size. */
749 1.1.1.1.2.1 pgoyette
750 1.1.1.1.2.1 pgoyette #define TRACE_RELAX 0
751 1.1.1.1.2.1 pgoyette #define tprintf if (TRACE_RELAX) printf
752 1.1.1.1.2.1 pgoyette
753 1.1.1.1.2.1 pgoyette
754 1.1.1.1.2.1 pgoyette typedef enum
755 1.1.1.1.2.1 pgoyette {
756 1.1.1.1.2.1 pgoyette OT_other,
757 1.1.1.1.2.1 pgoyette OT_bt,
758 1.1.1.1.2.1 pgoyette OT_bt_sfr,
759 1.1.1.1.2.1 pgoyette OT_bt_es,
760 1.1.1.1.2.1 pgoyette OT_bc,
761 1.1.1.1.2.1 pgoyette OT_bh
762 1.1.1.1.2.1 pgoyette } op_type_T;
763 1.1.1.1.2.1 pgoyette
764 1.1.1.1.2.1 pgoyette /* We're looking for these types of relaxations:
765 1.1.1.1.2.1 pgoyette
766 1.1.1.1.2.1 pgoyette BT 00110001 sbit0cc1 addr---- (cc is 10 (BF) or 01 (BT))
767 1.1.1.1.2.1 pgoyette B~T 00110001 sbit0cc1 00000011 11101110 pcrel16- -------- (BR $!pcrel20)
768 1.1.1.1.2.1 pgoyette
769 1.1.1.1.2.1 pgoyette BT sfr 00110001 sbit0cc0 sfr----- addr----
770 1.1.1.1.2.1 pgoyette BT ES: 00010001 00101110 sbit0cc1 addr----
771 1.1.1.1.2.1 pgoyette
772 1.1.1.1.2.1 pgoyette BC 110111cc addr----
773 1.1.1.1.2.1 pgoyette B~C 110111cc 00000011 11101110 pcrel16- -------- (BR $!pcrel20)
774 1.1.1.1.2.1 pgoyette
775 1.1.1.1.2.1 pgoyette BH 01100001 110c0011 00000011 11101110 pcrel16- -------- (BR $!pcrel20)
776 1.1.1.1.2.1 pgoyette B~H 01100001 110c0011 00000011 11101110 pcrel16- -------- (BR $!pcrel20)
777 1.1.1.1.2.1 pgoyette */
778 1.1.1.1.2.1 pgoyette
779 1.1.1.1.2.1 pgoyette /* Given the opcode bytes at OP, figure out which opcode it is and
780 1.1.1.1.2.1 pgoyette return the type of opcode. We use this to re-encode the opcode as
781 1.1.1.1.2.1 pgoyette a different size later. */
782 1.1.1.1.2.1 pgoyette
783 1.1.1.1.2.1 pgoyette static op_type_T
784 1.1.1.1.2.1 pgoyette rl78_opcode_type (char * op)
785 1.1.1.1.2.1 pgoyette {
786 1.1.1.1.2.1 pgoyette if (op[0] == 0x31
787 1.1.1.1.2.1 pgoyette && ((op[1] & 0x0f) == 0x05
788 1.1.1.1.2.1 pgoyette || (op[1] & 0x0f) == 0x03))
789 1.1.1.1.2.1 pgoyette return OT_bt;
790 1.1.1.1.2.1 pgoyette
791 1.1.1.1.2.1 pgoyette if (op[0] == 0x31
792 1.1.1.1.2.1 pgoyette && ((op[1] & 0x0f) == 0x04
793 1.1.1.1.2.1 pgoyette || (op[1] & 0x0f) == 0x02))
794 1.1.1.1.2.1 pgoyette return OT_bt_sfr;
795 1.1.1.1.2.1 pgoyette
796 1.1.1.1.2.1 pgoyette if (op[0] == 0x11
797 1.1.1.1.2.1 pgoyette && op[1] == 0x31
798 1.1.1.1.2.1 pgoyette && ((op[2] & 0x0f) == 0x05
799 1.1.1.1.2.1 pgoyette || (op[2] & 0x0f) == 0x03))
800 1.1.1.1.2.1 pgoyette return OT_bt_es;
801 1.1.1.1.2.1 pgoyette
802 1.1.1.1.2.1 pgoyette if ((op[0] & 0xfc) == 0xdc)
803 1.1.1.1.2.1 pgoyette return OT_bc;
804 1.1.1.1.2.1 pgoyette
805 1.1.1.1.2.1 pgoyette if (op[0] == 0x61
806 1.1.1.1.2.1 pgoyette && (op[1] & 0xef) == 0xc3)
807 1.1.1.1.2.1 pgoyette return OT_bh;
808 1.1.1.1.2.1 pgoyette
809 1.1.1.1.2.1 pgoyette return OT_other;
810 1.1.1.1.2.1 pgoyette }
811 1.1.1.1.2.1 pgoyette
812 1.1.1.1.2.1 pgoyette /* Returns zero if *addrP has the target address. Else returns nonzero
813 1.1.1.1.2.1 pgoyette if we cannot compute the target address yet. */
814 1.1.1.1.2.1 pgoyette
815 1.1.1.1.2.1 pgoyette static int
816 1.1.1.1.2.1 pgoyette rl78_frag_fix_value (fragS * fragP,
817 1.1.1.1.2.1 pgoyette segT segment,
818 1.1.1.1.2.1 pgoyette int which,
819 1.1.1.1.2.1 pgoyette addressT * addrP,
820 1.1.1.1.2.1 pgoyette int need_diff,
821 1.1.1.1.2.1 pgoyette addressT * sym_addr)
822 1.1.1.1.2.1 pgoyette {
823 1.1.1.1.2.1 pgoyette addressT addr = 0;
824 1.1.1.1.2.1 pgoyette rl78_bytesT * b = fragP->tc_frag_data;
825 1.1.1.1.2.1 pgoyette expressionS * exp = & b->fixups[which].exp;
826 1.1.1.1.2.1 pgoyette
827 1.1.1.1.2.1 pgoyette if (need_diff && exp->X_op != O_subtract)
828 1.1.1.1.2.1 pgoyette return 1;
829 1.1.1.1.2.1 pgoyette
830 1.1.1.1.2.1 pgoyette if (exp->X_add_symbol)
831 1.1.1.1.2.1 pgoyette {
832 1.1.1.1.2.1 pgoyette if (S_FORCE_RELOC (exp->X_add_symbol, 1))
833 1.1.1.1.2.1 pgoyette return 1;
834 1.1.1.1.2.1 pgoyette if (S_GET_SEGMENT (exp->X_add_symbol) != segment)
835 1.1.1.1.2.1 pgoyette return 1;
836 1.1.1.1.2.1 pgoyette addr += S_GET_VALUE (exp->X_add_symbol);
837 1.1.1.1.2.1 pgoyette }
838 1.1.1.1.2.1 pgoyette
839 1.1.1.1.2.1 pgoyette if (exp->X_op_symbol)
840 1.1.1.1.2.1 pgoyette {
841 1.1.1.1.2.1 pgoyette if (exp->X_op != O_subtract)
842 1.1.1.1.2.1 pgoyette return 1;
843 1.1.1.1.2.1 pgoyette if (S_FORCE_RELOC (exp->X_op_symbol, 1))
844 1.1.1.1.2.1 pgoyette return 1;
845 1.1.1.1.2.1 pgoyette if (S_GET_SEGMENT (exp->X_op_symbol) != segment)
846 1.1.1.1.2.1 pgoyette return 1;
847 1.1.1.1.2.1 pgoyette addr -= S_GET_VALUE (exp->X_op_symbol);
848 1.1.1.1.2.1 pgoyette }
849 1.1.1.1.2.1 pgoyette if (sym_addr)
850 1.1.1.1.2.1 pgoyette * sym_addr = addr;
851 1.1.1.1.2.1 pgoyette addr += exp->X_add_number;
852 1.1.1.1.2.1 pgoyette * addrP = addr;
853 1.1 christos return 0;
854 1.1 christos }
855 1.1.1.1.2.1 pgoyette
856 1.1.1.1.2.1 pgoyette /* Estimate how big the opcode is after this relax pass. The return
857 1.1.1.1.2.1 pgoyette value is the difference between fr_fix and the actual size. We
858 1.1.1.1.2.1 pgoyette compute the total size in rl78_relax_frag and store it in fr_subtype,
859 1.1.1.1.2.1 pgoyette so we only need to subtract fx_fix and return it. */
860 1.1 christos
861 1.1 christos int
862 1.1 christos md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED, segT segment ATTRIBUTE_UNUSED)
863 1.1.1.1.2.1 pgoyette {
864 1.1.1.1.2.1 pgoyette int opfixsize;
865 1.1.1.1.2.1 pgoyette int delta;
866 1.1.1.1.2.1 pgoyette
867 1.1.1.1.2.1 pgoyette /* This is the size of the opcode that's accounted for in fr_fix. */
868 1.1.1.1.2.1 pgoyette opfixsize = fragP->fr_fix - (fragP->fr_opcode - fragP->fr_literal);
869 1.1.1.1.2.1 pgoyette /* This is the size of the opcode that isn't. */
870 1.1.1.1.2.1 pgoyette delta = (fragP->fr_subtype - opfixsize);
871 1.1.1.1.2.1 pgoyette
872 1.1.1.1.2.1 pgoyette tprintf (" -> opfixsize %d delta %d\n", opfixsize, delta);
873 1.1.1.1.2.1 pgoyette return delta;
874 1.1.1.1.2.1 pgoyette }
875 1.1.1.1.2.1 pgoyette
876 1.1.1.1.2.1 pgoyette /* Given the new addresses for this relax pass, figure out how big
877 1.1.1.1.2.1 pgoyette each opcode must be. We store the total number of bytes needed in
878 1.1.1.1.2.1 pgoyette fr_subtype. The return value is the difference between the size
879 1.1.1.1.2.1 pgoyette after the last pass and the size after this pass, so we use the old
880 1.1.1.1.2.1 pgoyette fr_subtype to calculate the difference. */
881 1.1.1.1.2.1 pgoyette
882 1.1.1.1.2.1 pgoyette int
883 1.1.1.1.2.1 pgoyette rl78_relax_frag (segT segment ATTRIBUTE_UNUSED, fragS * fragP, long stretch)
884 1.1.1.1.2.1 pgoyette {
885 1.1.1.1.2.1 pgoyette addressT addr0, sym_addr;
886 1.1.1.1.2.1 pgoyette addressT mypc;
887 1.1.1.1.2.1 pgoyette int disp;
888 1.1.1.1.2.1 pgoyette int oldsize = fragP->fr_subtype;
889 1.1.1.1.2.1 pgoyette int newsize = oldsize;
890 1.1.1.1.2.1 pgoyette op_type_T optype;
891 1.1.1.1.2.1 pgoyette int ri;
892 1.1.1.1.2.1 pgoyette
893 1.1.1.1.2.1 pgoyette mypc = fragP->fr_address + (fragP->fr_opcode - fragP->fr_literal);
894 1.1.1.1.2.1 pgoyette
895 1.1.1.1.2.1 pgoyette /* If we ever get more than one reloc per opcode, this is the one
896 1.1.1.1.2.1 pgoyette we're relaxing. */
897 1.1.1.1.2.1 pgoyette ri = 0;
898 1.1.1.1.2.1 pgoyette
899 1.1.1.1.2.1 pgoyette optype = rl78_opcode_type (fragP->fr_opcode);
900 1.1.1.1.2.1 pgoyette /* Try to get the target address. */
901 1.1.1.1.2.1 pgoyette if (rl78_frag_fix_value (fragP, segment, ri, & addr0,
902 1.1.1.1.2.1 pgoyette fragP->tc_frag_data->relax[ri].type != RL78_RELAX_BRANCH,
903 1.1.1.1.2.1 pgoyette & sym_addr))
904 1.1.1.1.2.1 pgoyette {
905 1.1.1.1.2.1 pgoyette /* If we don't, we must use the maximum size for the linker. */
906 1.1.1.1.2.1 pgoyette switch (fragP->tc_frag_data->relax[ri].type)
907 1.1.1.1.2.1 pgoyette {
908 1.1.1.1.2.1 pgoyette case RL78_RELAX_BRANCH:
909 1.1.1.1.2.1 pgoyette switch (optype)
910 1.1.1.1.2.1 pgoyette {
911 1.1.1.1.2.1 pgoyette case OT_bt:
912 1.1.1.1.2.1 pgoyette newsize = 6;
913 1.1.1.1.2.1 pgoyette break;
914 1.1.1.1.2.1 pgoyette case OT_bt_sfr:
915 1.1.1.1.2.1 pgoyette case OT_bt_es:
916 1.1.1.1.2.1 pgoyette newsize = 7;
917 1.1.1.1.2.1 pgoyette break;
918 1.1.1.1.2.1 pgoyette case OT_bc:
919 1.1.1.1.2.1 pgoyette newsize = 5;
920 1.1.1.1.2.1 pgoyette break;
921 1.1.1.1.2.1 pgoyette case OT_bh:
922 1.1.1.1.2.1 pgoyette newsize = 6;
923 1.1.1.1.2.1 pgoyette break;
924 1.1.1.1.2.1 pgoyette case OT_other:
925 1.1.1.1.2.1 pgoyette newsize = oldsize;
926 1.1.1.1.2.1 pgoyette break;
927 1.1.1.1.2.1 pgoyette }
928 1.1.1.1.2.1 pgoyette break;
929 1.1.1.1.2.1 pgoyette
930 1.1.1.1.2.1 pgoyette }
931 1.1.1.1.2.1 pgoyette fragP->fr_subtype = newsize;
932 1.1.1.1.2.1 pgoyette tprintf (" -> new %d old %d delta %d (external)\n", newsize, oldsize, newsize-oldsize);
933 1.1.1.1.2.1 pgoyette return newsize - oldsize;
934 1.1.1.1.2.1 pgoyette }
935 1.1.1.1.2.1 pgoyette
936 1.1.1.1.2.1 pgoyette if (sym_addr > mypc)
937 1.1.1.1.2.1 pgoyette addr0 += stretch;
938 1.1.1.1.2.1 pgoyette
939 1.1.1.1.2.1 pgoyette switch (fragP->tc_frag_data->relax[ri].type)
940 1.1.1.1.2.1 pgoyette {
941 1.1.1.1.2.1 pgoyette case RL78_RELAX_BRANCH:
942 1.1.1.1.2.1 pgoyette disp = (int) addr0 - (int) mypc;
943 1.1.1.1.2.1 pgoyette
944 1.1.1.1.2.1 pgoyette switch (optype)
945 1.1.1.1.2.1 pgoyette {
946 1.1.1.1.2.1 pgoyette case OT_bt:
947 1.1.1.1.2.1 pgoyette if (disp >= -128 && (disp - (oldsize-2)) <= 127)
948 1.1.1.1.2.1 pgoyette newsize = 3;
949 1.1.1.1.2.1 pgoyette else
950 1.1.1.1.2.1 pgoyette newsize = 6;
951 1.1.1.1.2.1 pgoyette break;
952 1.1.1.1.2.1 pgoyette case OT_bt_sfr:
953 1.1.1.1.2.1 pgoyette case OT_bt_es:
954 1.1.1.1.2.1 pgoyette if (disp >= -128 && (disp - (oldsize-3)) <= 127)
955 1.1.1.1.2.1 pgoyette newsize = 4;
956 1.1.1.1.2.1 pgoyette else
957 1.1.1.1.2.1 pgoyette newsize = 7;
958 1.1.1.1.2.1 pgoyette break;
959 1.1.1.1.2.1 pgoyette case OT_bc:
960 1.1.1.1.2.1 pgoyette if (disp >= -128 && (disp - (oldsize-1)) <= 127)
961 1.1.1.1.2.1 pgoyette newsize = 2;
962 1.1.1.1.2.1 pgoyette else
963 1.1.1.1.2.1 pgoyette newsize = 5;
964 1.1.1.1.2.1 pgoyette break;
965 1.1.1.1.2.1 pgoyette case OT_bh:
966 1.1.1.1.2.1 pgoyette if (disp >= -128 && (disp - (oldsize-2)) <= 127)
967 1.1.1.1.2.1 pgoyette newsize = 3;
968 1.1.1.1.2.1 pgoyette else
969 1.1.1.1.2.1 pgoyette newsize = 6;
970 1.1.1.1.2.1 pgoyette break;
971 1.1.1.1.2.1 pgoyette case OT_other:
972 1.1.1.1.2.1 pgoyette newsize = oldsize;
973 1.1.1.1.2.1 pgoyette break;
974 1.1.1.1.2.1 pgoyette }
975 1.1.1.1.2.1 pgoyette break;
976 1.1.1.1.2.1 pgoyette }
977 1.1.1.1.2.1 pgoyette
978 1.1.1.1.2.1 pgoyette /* This prevents infinite loops in align-heavy sources. */
979 1.1.1.1.2.1 pgoyette if (newsize < oldsize)
980 1.1.1.1.2.1 pgoyette {
981 1.1.1.1.2.1 pgoyette if (fragP->tc_frag_data->times_shrank > 10
982 1.1.1.1.2.1 pgoyette && fragP->tc_frag_data->times_grown > 10)
983 1.1.1.1.2.1 pgoyette newsize = oldsize;
984 1.1.1.1.2.1 pgoyette if (fragP->tc_frag_data->times_shrank < 20)
985 1.1.1.1.2.1 pgoyette fragP->tc_frag_data->times_shrank ++;
986 1.1.1.1.2.1 pgoyette }
987 1.1.1.1.2.1 pgoyette else if (newsize > oldsize)
988 1.1.1.1.2.1 pgoyette {
989 1.1.1.1.2.1 pgoyette if (fragP->tc_frag_data->times_grown < 20)
990 1.1.1.1.2.1 pgoyette fragP->tc_frag_data->times_grown ++;
991 1.1.1.1.2.1 pgoyette }
992 1.1.1.1.2.1 pgoyette
993 1.1.1.1.2.1 pgoyette fragP->fr_subtype = newsize;
994 1.1.1.1.2.1 pgoyette tprintf (" -> new %d old %d delta %d\n", newsize, oldsize, newsize-oldsize);
995 1.1 christos return newsize - oldsize;
996 1.1 christos }
997 1.1.1.1.2.1 pgoyette
998 1.1.1.1.2.1 pgoyette /* This lets us test for the opcode type and the desired size in a
999 1.1.1.1.2.1 pgoyette switch statement. */
1000 1.1.1.1.2.1 pgoyette #define OPCODE(type,size) ((type) * 16 + (size))
1001 1.1.1.1.2.1 pgoyette
1002 1.1.1.1.2.1 pgoyette /* Given the opcode stored in fr_opcode and the number of bytes we
1003 1.1.1.1.2.1 pgoyette think we need, encode a new opcode. We stored a pointer to the
1004 1.1.1.1.2.1 pgoyette fixup for this opcode in the tc_frag_data structure. If we can do
1005 1.1.1.1.2.1 pgoyette the fixup here, we change the relocation type to "none" (we test
1006 1.1.1.1.2.1 pgoyette for that in tc_gen_reloc) else we change it to the right type for
1007 1.1.1.1.2.1 pgoyette the new (biggest) opcode. */
1008 1.1.1.1.2.1 pgoyette
1009 1.1.1.1.2.1 pgoyette void
1010 1.1.1.1.2.1 pgoyette md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
1011 1.1.1.1.2.1 pgoyette segT segment ATTRIBUTE_UNUSED,
1012 1.1.1.1.2.1 pgoyette fragS * fragP ATTRIBUTE_UNUSED)
1013 1.1.1.1.2.1 pgoyette {
1014 1.1.1.1.2.1 pgoyette rl78_bytesT * rl78b = fragP->tc_frag_data;
1015 1.1.1.1.2.1 pgoyette addressT addr0, mypc;
1016 1.1.1.1.2.1 pgoyette int disp;
1017 1.1.1.1.2.1 pgoyette int reloc_type, reloc_adjust;
1018 1.1.1.1.2.1 pgoyette char * op = fragP->fr_opcode;
1019 1.1.1.1.2.1 pgoyette int keep_reloc = 0;
1020 1.1.1.1.2.1 pgoyette int ri;
1021 1.1.1.1.2.1 pgoyette int fi = (rl78b->n_fixups > 1) ? 1 : 0;
1022 1.1.1.1.2.1 pgoyette fixS * fix = rl78b->fixups[fi].fixP;
1023 1.1.1.1.2.1 pgoyette
1024 1.1.1.1.2.1 pgoyette /* If we ever get more than one reloc per opcode, this is the one
1025 1.1.1.1.2.1 pgoyette we're relaxing. */
1026 1.1.1.1.2.1 pgoyette ri = 0;
1027 1.1.1.1.2.1 pgoyette
1028 1.1.1.1.2.1 pgoyette /* We used a new frag for this opcode, so the opcode address should
1029 1.1.1.1.2.1 pgoyette be the frag address. */
1030 1.1.1.1.2.1 pgoyette mypc = fragP->fr_address + (fragP->fr_opcode - fragP->fr_literal);
1031 1.1.1.1.2.1 pgoyette tprintf ("\033[32mmypc: 0x%x\033[0m\n", (int)mypc);
1032 1.1.1.1.2.1 pgoyette
1033 1.1.1.1.2.1 pgoyette /* Try to get the target address. If we fail here, we just use the
1034 1.1.1.1.2.1 pgoyette largest format. */
1035 1.1.1.1.2.1 pgoyette if (rl78_frag_fix_value (fragP, segment, 0, & addr0,
1036 1.1.1.1.2.1 pgoyette fragP->tc_frag_data->relax[ri].type != RL78_RELAX_BRANCH, 0))
1037 1.1.1.1.2.1 pgoyette {
1038 1.1.1.1.2.1 pgoyette /* We don't know the target address. */
1039 1.1.1.1.2.1 pgoyette keep_reloc = 1;
1040 1.1.1.1.2.1 pgoyette addr0 = 0;
1041 1.1.1.1.2.1 pgoyette disp = 0;
1042 1.1.1.1.2.1 pgoyette tprintf ("unknown addr ? - %x = ?\n", (int)mypc);
1043 1.1.1.1.2.1 pgoyette }
1044 1.1.1.1.2.1 pgoyette else
1045 1.1.1.1.2.1 pgoyette {
1046 1.1.1.1.2.1 pgoyette /* We know the target address, and it's in addr0. */
1047 1.1.1.1.2.1 pgoyette disp = (int) addr0 - (int) mypc;
1048 1.1.1.1.2.1 pgoyette tprintf ("known addr %x - %x = %d\n", (int)addr0, (int)mypc, disp);
1049 1.1.1.1.2.1 pgoyette }
1050 1.1.1.1.2.1 pgoyette
1051 1.1.1.1.2.1 pgoyette if (linkrelax)
1052 1.1.1.1.2.1 pgoyette keep_reloc = 1;
1053 1.1.1.1.2.1 pgoyette
1054 1.1.1.1.2.1 pgoyette reloc_type = BFD_RELOC_NONE;
1055 1.1.1.1.2.1 pgoyette reloc_adjust = 0;
1056 1.1.1.1.2.1 pgoyette
1057 1.1.1.1.2.1 pgoyette switch (fragP->tc_frag_data->relax[ri].type)
1058 1.1.1.1.2.1 pgoyette {
1059 1.1.1.1.2.1 pgoyette case RL78_RELAX_BRANCH:
1060 1.1.1.1.2.1 pgoyette switch (OPCODE (rl78_opcode_type (fragP->fr_opcode), fragP->fr_subtype))
1061 1.1.1.1.2.1 pgoyette {
1062 1.1.1.1.2.1 pgoyette
1063 1.1.1.1.2.1 pgoyette case OPCODE (OT_bt, 3): /* BT A,$ - no change. */
1064 1.1.1.1.2.1 pgoyette disp -= 3;
1065 1.1.1.1.2.1 pgoyette op[2] = disp;
1066 1.1.1.1.2.1 pgoyette break;
1067 1.1.1.1.2.1 pgoyette
1068 1.1.1.1.2.1 pgoyette case OPCODE (OT_bt, 6): /* BT A,$ - long version. */
1069 1.1.1.1.2.1 pgoyette disp -= 3;
1070 1.1.1.1.2.1 pgoyette op[1] ^= 0x06; /* toggle conditional. */
1071 1.1.1.1.2.1 pgoyette op[2] = 3; /* displacement over long branch. */
1072 1.1.1.1.2.1 pgoyette disp -= 3;
1073 1.1.1.1.2.1 pgoyette op[3] = 0xEE; /* BR $!addr20 */
1074 1.1.1.1.2.1 pgoyette op[4] = disp & 0xff;
1075 1.1.1.1.2.1 pgoyette op[5] = disp >> 8;
1076 1.1.1.1.2.1 pgoyette reloc_type = keep_reloc ? BFD_RELOC_16_PCREL : BFD_RELOC_NONE;
1077 1.1.1.1.2.1 pgoyette reloc_adjust = 2;
1078 1.1.1.1.2.1 pgoyette break;
1079 1.1.1.1.2.1 pgoyette
1080 1.1.1.1.2.1 pgoyette case OPCODE (OT_bt_sfr, 4): /* BT PSW,$ - no change. */
1081 1.1.1.1.2.1 pgoyette disp -= 4;
1082 1.1.1.1.2.1 pgoyette op[3] = disp;
1083 1.1.1.1.2.1 pgoyette break;
1084 1.1.1.1.2.1 pgoyette
1085 1.1.1.1.2.1 pgoyette case OPCODE (OT_bt_sfr, 7): /* BT PSW,$ - long version. */
1086 1.1.1.1.2.1 pgoyette disp -= 4;
1087 1.1.1.1.2.1 pgoyette op[1] ^= 0x06; /* toggle conditional. */
1088 1.1.1.1.2.1 pgoyette op[3] = 3; /* displacement over long branch. */
1089 1.1.1.1.2.1 pgoyette disp -= 3;
1090 1.1.1.1.2.1 pgoyette op[4] = 0xEE; /* BR $!addr20 */
1091 1.1.1.1.2.1 pgoyette op[5] = disp & 0xff;
1092 1.1.1.1.2.1 pgoyette op[6] = disp >> 8;
1093 1.1.1.1.2.1 pgoyette reloc_type = keep_reloc ? BFD_RELOC_16_PCREL : BFD_RELOC_NONE;
1094 1.1.1.1.2.1 pgoyette reloc_adjust = 2;
1095 1.1.1.1.2.1 pgoyette break;
1096 1.1.1.1.2.1 pgoyette
1097 1.1.1.1.2.1 pgoyette case OPCODE (OT_bt_es, 4): /* BT ES:[HL],$ - no change. */
1098 1.1.1.1.2.1 pgoyette disp -= 4;
1099 1.1.1.1.2.1 pgoyette op[3] = disp;
1100 1.1.1.1.2.1 pgoyette break;
1101 1.1.1.1.2.1 pgoyette
1102 1.1.1.1.2.1 pgoyette case OPCODE (OT_bt_es, 7): /* BT PSW,$ - long version. */
1103 1.1.1.1.2.1 pgoyette disp -= 4;
1104 1.1.1.1.2.1 pgoyette op[2] ^= 0x06; /* toggle conditional. */
1105 1.1.1.1.2.1 pgoyette op[3] = 3; /* displacement over long branch. */
1106 1.1.1.1.2.1 pgoyette disp -= 3;
1107 1.1.1.1.2.1 pgoyette op[4] = 0xEE; /* BR $!addr20 */
1108 1.1.1.1.2.1 pgoyette op[5] = disp & 0xff;
1109 1.1.1.1.2.1 pgoyette op[6] = disp >> 8;
1110 1.1.1.1.2.1 pgoyette reloc_type = keep_reloc ? BFD_RELOC_16_PCREL : BFD_RELOC_NONE;
1111 1.1.1.1.2.1 pgoyette reloc_adjust = 2;
1112 1.1.1.1.2.1 pgoyette break;
1113 1.1.1.1.2.1 pgoyette
1114 1.1.1.1.2.1 pgoyette case OPCODE (OT_bc, 2): /* BC $ - no change. */
1115 1.1.1.1.2.1 pgoyette disp -= 2;
1116 1.1.1.1.2.1 pgoyette op[1] = disp;
1117 1.1.1.1.2.1 pgoyette break;
1118 1.1.1.1.2.1 pgoyette
1119 1.1.1.1.2.1 pgoyette case OPCODE (OT_bc, 5): /* BC $ - long version. */
1120 1.1.1.1.2.1 pgoyette disp -= 2;
1121 1.1.1.1.2.1 pgoyette op[0] ^= 0x02; /* toggle conditional. */
1122 1.1.1.1.2.1 pgoyette op[1] = 3;
1123 1.1.1.1.2.1 pgoyette disp -= 3;
1124 1.1.1.1.2.1 pgoyette op[2] = 0xEE; /* BR $!addr20 */
1125 1.1.1.1.2.1 pgoyette op[3] = disp & 0xff;
1126 1.1.1.1.2.1 pgoyette op[4] = disp >> 8;
1127 1.1.1.1.2.1 pgoyette reloc_type = keep_reloc ? BFD_RELOC_16_PCREL : BFD_RELOC_NONE;
1128 1.1.1.1.2.1 pgoyette reloc_adjust = 2;
1129 1.1.1.1.2.1 pgoyette break;
1130 1.1.1.1.2.1 pgoyette
1131 1.1.1.1.2.1 pgoyette case OPCODE (OT_bh, 3): /* BH $ - no change. */
1132 1.1.1.1.2.1 pgoyette disp -= 3;
1133 1.1.1.1.2.1 pgoyette op[2] = disp;
1134 1.1.1.1.2.1 pgoyette break;
1135 1.1.1.1.2.1 pgoyette
1136 1.1.1.1.2.1 pgoyette case OPCODE (OT_bh, 6): /* BC $ - long version. */
1137 1.1.1.1.2.1 pgoyette disp -= 3;
1138 1.1.1.1.2.1 pgoyette op[1] ^= 0x10; /* toggle conditional. */
1139 1.1.1.1.2.1 pgoyette op[2] = 3;
1140 1.1.1.1.2.1 pgoyette disp -= 3;
1141 1.1.1.1.2.1 pgoyette op[3] = 0xEE; /* BR $!addr20 */
1142 1.1.1.1.2.1 pgoyette op[4] = disp & 0xff;
1143 1.1.1.1.2.1 pgoyette op[5] = disp >> 8;
1144 1.1.1.1.2.1 pgoyette reloc_type = keep_reloc ? BFD_RELOC_16_PCREL : BFD_RELOC_NONE;
1145 1.1.1.1.2.1 pgoyette reloc_adjust = 2;
1146 1.1.1.1.2.1 pgoyette break;
1147 1.1.1.1.2.1 pgoyette
1148 1.1.1.1.2.1 pgoyette default:
1149 1.1.1.1.2.1 pgoyette fprintf(stderr, "Missed case %d %d at 0x%lx\n",
1150 1.1.1.1.2.1 pgoyette rl78_opcode_type (fragP->fr_opcode), fragP->fr_subtype, mypc);
1151 1.1.1.1.2.1 pgoyette abort ();
1152 1.1.1.1.2.1 pgoyette
1153 1.1.1.1.2.1 pgoyette }
1154 1.1.1.1.2.1 pgoyette break;
1155 1.1.1.1.2.1 pgoyette
1156 1.1.1.1.2.1 pgoyette default:
1157 1.1.1.1.2.1 pgoyette if (rl78b->n_fixups)
1158 1.1.1.1.2.1 pgoyette {
1159 1.1.1.1.2.1 pgoyette reloc_type = fix->fx_r_type;
1160 1.1.1.1.2.1 pgoyette reloc_adjust = 0;
1161 1.1.1.1.2.1 pgoyette }
1162 1.1.1.1.2.1 pgoyette break;
1163 1.1.1.1.2.1 pgoyette }
1164 1.1.1.1.2.1 pgoyette
1165 1.1.1.1.2.1 pgoyette if (rl78b->n_fixups)
1166 1.1.1.1.2.1 pgoyette {
1167 1.1.1.1.2.1 pgoyette
1168 1.1.1.1.2.1 pgoyette fix->fx_r_type = reloc_type;
1169 1.1.1.1.2.1 pgoyette fix->fx_where += reloc_adjust;
1170 1.1.1.1.2.1 pgoyette switch (reloc_type)
1171 1.1.1.1.2.1 pgoyette {
1172 1.1.1.1.2.1 pgoyette case BFD_RELOC_NONE:
1173 1.1.1.1.2.1 pgoyette fix->fx_size = 0;
1174 1.1.1.1.2.1 pgoyette break;
1175 1.1.1.1.2.1 pgoyette case BFD_RELOC_8:
1176 1.1.1.1.2.1 pgoyette fix->fx_size = 1;
1177 1.1.1.1.2.1 pgoyette break;
1178 1.1.1.1.2.1 pgoyette case BFD_RELOC_16_PCREL:
1179 1.1.1.1.2.1 pgoyette fix->fx_size = 2;
1180 1.1.1.1.2.1 pgoyette break;
1181 1.1.1.1.2.1 pgoyette }
1182 1.1.1.1.2.1 pgoyette }
1183 1.1.1.1.2.1 pgoyette
1184 1.1.1.1.2.1 pgoyette fragP->fr_fix = fragP->fr_subtype + (fragP->fr_opcode - fragP->fr_literal);
1185 1.1.1.1.2.1 pgoyette tprintf ("fragP->fr_fix now %ld (%d + (%p - %p)\n", (long) fragP->fr_fix,
1186 1.1.1.1.2.1 pgoyette fragP->fr_subtype, fragP->fr_opcode, fragP->fr_literal);
1187 1.1.1.1.2.1 pgoyette fragP->fr_var = 0;
1188 1.1.1.1.2.1 pgoyette
1189 1.1.1.1.2.1 pgoyette tprintf ("compare 0x%lx vs 0x%lx - 0x%lx = 0x%lx (%p)\n",
1190 1.1.1.1.2.1 pgoyette (long)fragP->fr_fix,
1191 1.1.1.1.2.1 pgoyette (long)fragP->fr_next->fr_address, (long)fragP->fr_address,
1192 1.1.1.1.2.1 pgoyette (long)(fragP->fr_next->fr_address - fragP->fr_address),
1193 1.1.1.1.2.1 pgoyette fragP->fr_next);
1194 1.1.1.1.2.1 pgoyette
1195 1.1.1.1.2.1 pgoyette if (fragP->fr_next != NULL
1196 1.1.1.1.2.1 pgoyette && ((offsetT) (fragP->fr_next->fr_address - fragP->fr_address)
1197 1.1.1.1.2.1 pgoyette != fragP->fr_fix))
1198 1.1.1.1.2.1 pgoyette as_bad (_("bad frag at %p : fix %ld addr %ld %ld \n"), fragP,
1199 1.1.1.1.2.1 pgoyette (long) fragP->fr_fix,
1200 1.1.1.1.2.1 pgoyette (long) fragP->fr_address, (long) fragP->fr_next->fr_address);
1201 1.1.1.1.2.1 pgoyette }
1202 1.1.1.1.2.1 pgoyette
1203 1.1.1.1.2.1 pgoyette /* End of relaxation code.
1204 1.1.1.1.2.1 pgoyette ----------------------------------------------------------------------*/
1205 1.1.1.1.2.1 pgoyette
1206 1.1 christos
1208 1.1 christos arelent **
1209 1.1 christos tc_gen_reloc (asection * seg ATTRIBUTE_UNUSED, fixS * fixp)
1210 1.1 christos {
1211 1.1 christos static arelent * reloc[8];
1212 1.1 christos int rp;
1213 1.1 christos
1214 1.1 christos if (fixp->fx_r_type == BFD_RELOC_NONE)
1215 1.1 christos {
1216 1.1 christos reloc[0] = NULL;
1217 1.1 christos return reloc;
1218 1.1 christos }
1219 1.1 christos
1220 1.1 christos if (fixp->fx_subsy
1221 1.1 christos && S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
1222 1.1 christos {
1223 1.1 christos fixp->fx_offset -= S_GET_VALUE (fixp->fx_subsy);
1224 1.1 christos fixp->fx_subsy = NULL;
1225 1.1 christos }
1226 1.1 christos
1227 1.1 christos reloc[0] = (arelent *) xmalloc (sizeof (arelent));
1228 1.1 christos reloc[0]->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
1229 1.1 christos * reloc[0]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
1230 1.1 christos reloc[0]->address = fixp->fx_frag->fr_address + fixp->fx_where;
1231 1.1 christos reloc[0]->addend = fixp->fx_offset;
1232 1.1 christos
1233 1.1 christos if (fixp->fx_r_type == BFD_RELOC_RL78_32_OP
1234 1.1 christos && fixp->fx_subsy)
1235 1.1 christos {
1236 1.1 christos fixp->fx_r_type = BFD_RELOC_RL78_DIFF;
1237 1.1 christos }
1238 1.1 christos
1239 1.1 christos #define OPX(REL,SYM,ADD) \
1240 1.1 christos reloc[rp] = (arelent *) xmalloc (sizeof (arelent)); \
1241 1.1 christos reloc[rp]->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); \
1242 1.1 christos reloc[rp]->howto = bfd_reloc_type_lookup (stdoutput, REL); \
1243 1.1 christos reloc[rp]->addend = ADD; \
1244 1.1 christos * reloc[rp]->sym_ptr_ptr = SYM; \
1245 1.1 christos reloc[rp]->address = fixp->fx_frag->fr_address + fixp->fx_where; \
1246 1.1.1.1.2.1 pgoyette reloc[++rp] = NULL
1247 1.1.1.1.2.1 pgoyette #define OPSYM(SYM) OPX(BFD_RELOC_RL78_SYM, SYM, 0)
1248 1.1.1.1.2.1 pgoyette
1249 1.1.1.1.2.1 pgoyette /* FIXME: We cannot do the normal thing for an immediate value reloc,
1250 1.1.1.1.2.1 pgoyette ie creating a RL78_SYM reloc in the *ABS* section with an offset
1251 1.1.1.1.2.1 pgoyette equal to the immediate value we want to store. This fails because
1252 1.1.1.1.2.1 pgoyette the reloc processing in bfd_perform_relocation and bfd_install_relocation
1253 1.1.1.1.2.1 pgoyette will short circuit such relocs and never pass them on to the special
1254 1.1.1.1.2.1 pgoyette reloc processing code. So instead we create a RL78_SYM reloc against
1255 1.1.1.1.2.1 pgoyette the __rl78_abs__ symbol and arrange for the linker scripts to place
1256 1.1.1.1.2.1 pgoyette this symbol at address 0. */
1257 1.1 christos #define OPIMM(IMM) OPX (BFD_RELOC_RL78_SYM, symbol_get_bfdsym (rl78_abs_sym), IMM)
1258 1.1 christos
1259 1.1 christos #define OP(OP) OPX(BFD_RELOC_RL78_##OP, *reloc[0]->sym_ptr_ptr, 0)
1260 1.1 christos #define SYM0() reloc[0]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_RL78_SYM)
1261 1.1 christos
1262 1.1 christos rp = 1;
1263 1.1 christos
1264 1.1 christos /* Certain BFD relocations cannot be translated directly into
1265 1.1 christos a single (non-Red Hat) RL78 relocation, but instead need
1266 1.1 christos multiple RL78 relocations - handle them here. */
1267 1.1 christos switch (fixp->fx_r_type)
1268 1.1 christos {
1269 1.1 christos case BFD_RELOC_RL78_DIFF:
1270 1.1 christos SYM0 ();
1271 1.1 christos OPSYM (symbol_get_bfdsym (fixp->fx_subsy));
1272 1.1 christos OP(OP_SUBTRACT);
1273 1.1 christos
1274 1.1 christos switch (fixp->fx_size)
1275 1.1 christos {
1276 1.1 christos case 1:
1277 1.1 christos OP(ABS8);
1278 1.1 christos break;
1279 1.1 christos case 2:
1280 1.1 christos OP (ABS16);
1281 1.1 christos break;
1282 1.1 christos case 4:
1283 1.1 christos OP (ABS32);
1284 1.1 christos break;
1285 1.1 christos }
1286 1.1 christos break;
1287 1.1 christos
1288 1.1 christos case BFD_RELOC_RL78_NEG32:
1289 1.1 christos SYM0 ();
1290 1.1 christos OP (OP_NEG);
1291 1.1 christos OP (ABS32);
1292 1.1.1.1.2.1 pgoyette break;
1293 1.1.1.1.2.1 pgoyette
1294 1.1.1.1.2.1 pgoyette case BFD_RELOC_RL78_CODE:
1295 1.1.1.1.2.1 pgoyette reloc[0]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_RL78_16U);
1296 1.1.1.1.2.1 pgoyette reloc[1] = NULL;
1297 1.1 christos break;
1298 1.1 christos
1299 1.1 christos case BFD_RELOC_RL78_LO16:
1300 1.1 christos SYM0 ();
1301 1.1 christos OPIMM (0xffff);
1302 1.1 christos OP (OP_AND);
1303 1.1 christos OP (ABS16);
1304 1.1 christos break;
1305 1.1 christos
1306 1.1 christos case BFD_RELOC_RL78_HI16:
1307 1.1 christos SYM0 ();
1308 1.1 christos OPIMM (16);
1309 1.1 christos OP (OP_SHRA);
1310 1.1 christos OP (ABS16);
1311 1.1 christos break;
1312 1.1 christos
1313 1.1 christos case BFD_RELOC_RL78_HI8:
1314 1.1 christos SYM0 ();
1315 1.1 christos OPIMM (16);
1316 1.1 christos OP (OP_SHRA);
1317 1.1 christos OPIMM (0xff);
1318 1.1 christos OP (OP_AND);
1319 1.1 christos OP (ABS8);
1320 1.1 christos break;
1321 1.1 christos
1322 1.1 christos default:
1323 1.1 christos reloc[0]->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
1324 1.1 christos reloc[1] = NULL;
1325 1.1 christos break;
1326 1.1 christos }
1327 1.1 christos
1328 1.1 christos return reloc;
1329 1.1 christos }
1330 1.1 christos
1331 1.1 christos int
1332 1.1 christos rl78_validate_fix_sub (struct fix * f)
1333 1.1 christos {
1334 1.1 christos /* We permit the subtraction of two symbols in a few cases. */
1335 1.1 christos /* mov #sym1-sym2, R3 */
1336 1.1 christos if (f->fx_r_type == BFD_RELOC_RL78_32_OP)
1337 1.1 christos return 1;
1338 1.1 christos /* .long sym1-sym2 */
1339 1.1 christos if (f->fx_r_type == BFD_RELOC_RL78_DIFF
1340 1.1 christos && ! f->fx_pcrel
1341 1.1 christos && (f->fx_size == 4 || f->fx_size == 2 || f->fx_size == 1))
1342 1.1 christos return 1;
1343 1.1 christos return 0;
1344 1.1 christos }
1345 1.1 christos
1346 1.1 christos long
1347 1.1 christos md_pcrel_from_section (fixS * fixP, segT sec)
1348 1.1 christos {
1349 1.1 christos long rv;
1350 1.1 christos
1351 1.1 christos if (fixP->fx_addsy != NULL
1352 1.1 christos && (! S_IS_DEFINED (fixP->fx_addsy)
1353 1.1 christos || S_GET_SEGMENT (fixP->fx_addsy) != sec))
1354 1.1 christos /* The symbol is undefined (or is defined but not in this section).
1355 1.1 christos Let the linker figure it out. */
1356 1.1 christos return 0;
1357 1.1 christos
1358 1.1 christos rv = fixP->fx_frag->fr_address + fixP->fx_where;
1359 1.1 christos switch (fixP->fx_r_type)
1360 1.1 christos {
1361 1.1 christos case BFD_RELOC_8_PCREL:
1362 1.1 christos rv += 1;
1363 1.1 christos break;
1364 1.1 christos case BFD_RELOC_16_PCREL:
1365 1.1 christos rv += 2;
1366 1.1 christos break;
1367 1.1 christos default:
1368 1.1 christos break;
1369 1.1 christos }
1370 1.1 christos return rv;
1371 1.1 christos }
1372 1.1 christos
1373 1.1 christos void
1374 1.1 christos md_apply_fix (struct fix * f ATTRIBUTE_UNUSED,
1375 1.1 christos valueT * t ATTRIBUTE_UNUSED,
1376 1.1 christos segT s ATTRIBUTE_UNUSED)
1377 1.1 christos {
1378 1.1 christos char * op;
1379 1.1 christos unsigned long val;
1380 1.1 christos
1381 1.1 christos if (f->fx_addsy && S_FORCE_RELOC (f->fx_addsy, 1))
1382 1.1 christos return;
1383 1.1 christos if (f->fx_subsy && S_FORCE_RELOC (f->fx_subsy, 1))
1384 1.1 christos return;
1385 1.1 christos
1386 1.1 christos op = f->fx_frag->fr_literal + f->fx_where;
1387 1.1 christos val = (unsigned long) * t;
1388 1.1 christos
1389 1.1 christos switch (f->fx_r_type)
1390 1.1 christos {
1391 1.1 christos case BFD_RELOC_NONE:
1392 1.1 christos break;
1393 1.1 christos
1394 1.1 christos case BFD_RELOC_RL78_RELAX:
1395 1.1 christos f->fx_done = 1;
1396 1.1 christos break;
1397 1.1.1.1.2.1 pgoyette
1398 1.1.1.1.2.1 pgoyette case BFD_RELOC_8_PCREL:
1399 1.1.1.1.2.1 pgoyette if ((long)val < -128 || (long)val > 127)
1400 1.1.1.1.2.1 pgoyette as_bad_where (f->fx_file, f->fx_line,
1401 1.1.1.1.2.1 pgoyette _("value of %ld too large for 8-bit branch"),
1402 1.1.1.1.2.1 pgoyette val);
1403 1.1.1.1.2.1 pgoyette /* Fall through. */
1404 1.1 christos case BFD_RELOC_8:
1405 1.1 christos case BFD_RELOC_RL78_SADDR: /* We need to store the 8 LSB, but this works. */
1406 1.1 christos op[0] = val;
1407 1.1 christos break;
1408 1.1.1.1.2.1 pgoyette
1409 1.1.1.1.2.1 pgoyette case BFD_RELOC_16_PCREL:
1410 1.1.1.1.2.1 pgoyette if ((long)val < -32768 || (long)val > 32767)
1411 1.1.1.1.2.1 pgoyette as_bad_where (f->fx_file, f->fx_line,
1412 1.1.1.1.2.1 pgoyette _("value of %ld too large for 16-bit branch"),
1413 1.1.1.1.2.1 pgoyette val);
1414 1.1.1.1.2.1 pgoyette /* Fall through. */
1415 1.1 christos case BFD_RELOC_16:
1416 1.1 christos case BFD_RELOC_RL78_CODE:
1417 1.1 christos op[0] = val;
1418 1.1 christos op[1] = val >> 8;
1419 1.1 christos break;
1420 1.1 christos
1421 1.1 christos case BFD_RELOC_24:
1422 1.1 christos op[0] = val;
1423 1.1 christos op[1] = val >> 8;
1424 1.1 christos op[2] = val >> 16;
1425 1.1 christos break;
1426 1.1 christos
1427 1.1 christos case BFD_RELOC_32:
1428 1.1 christos op[0] = val;
1429 1.1 christos op[1] = val >> 8;
1430 1.1 christos op[2] = val >> 16;
1431 1.1 christos op[3] = val >> 24;
1432 1.1.1.1.2.1 pgoyette break;
1433 1.1.1.1.2.1 pgoyette
1434 1.1.1.1.2.1 pgoyette case BFD_RELOC_RL78_DIFF:
1435 1.1.1.1.2.1 pgoyette op[0] = val;
1436 1.1.1.1.2.1 pgoyette if (f->fx_size > 1)
1437 1.1.1.1.2.1 pgoyette op[1] = val >> 8;
1438 1.1.1.1.2.1 pgoyette if (f->fx_size > 2)
1439 1.1.1.1.2.1 pgoyette op[2] = val >> 16;
1440 1.1.1.1.2.1 pgoyette if (f->fx_size > 3)
1441 1.1.1.1.2.1 pgoyette op[3] = val >> 24;
1442 1.1.1.1.2.1 pgoyette break;
1443 1.1.1.1.2.1 pgoyette
1444 1.1.1.1.2.1 pgoyette case BFD_RELOC_RL78_HI8:
1445 1.1.1.1.2.1 pgoyette val = val >> 16;
1446 1.1.1.1.2.1 pgoyette op[0] = val;
1447 1.1.1.1.2.1 pgoyette break;
1448 1.1.1.1.2.1 pgoyette
1449 1.1.1.1.2.1 pgoyette case BFD_RELOC_RL78_HI16:
1450 1.1.1.1.2.1 pgoyette val = val >> 16;
1451 1.1.1.1.2.1 pgoyette op[0] = val;
1452 1.1.1.1.2.1 pgoyette op[1] = val >> 8;
1453 1.1.1.1.2.1 pgoyette break;
1454 1.1.1.1.2.1 pgoyette
1455 1.1.1.1.2.1 pgoyette case BFD_RELOC_RL78_LO16:
1456 1.1.1.1.2.1 pgoyette op[0] = val;
1457 1.1.1.1.2.1 pgoyette op[1] = val >> 8;
1458 1.1 christos break;
1459 1.1 christos
1460 1.1 christos default:
1461 1.1 christos as_bad (_("Unknown reloc in md_apply_fix: %s"),
1462 1.1 christos bfd_get_reloc_code_name (f->fx_r_type));
1463 1.1 christos break;
1464 1.1 christos }
1465 1.1 christos
1466 1.1 christos if (f->fx_addsy == NULL)
1467 1.1 christos f->fx_done = 1;
1468 1.1 christos }
1469 1.1 christos
1470 1.1 christos valueT
1471 1.1 christos md_section_align (segT segment, valueT size)
1472 1.1.1.1.2.1 pgoyette {
1473 1.1 christos int align = bfd_get_section_alignment (stdoutput, segment);
1474 return ((size + (1 << align) - 1) & -(1 << align));
1475 }
1476