tc-moxie.c revision 1.1.1.1.2.1 1 1.1 christos /* tc-moxie.c -- Assemble code for moxie
2 1.1.1.1.2.1 pgoyette Copyright (C) 2009-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
18 1.1 christos the Free Software Foundation, 51 Franklin Street - Fifth Floor,
19 1.1 christos Boston, MA 02110-1301, USA. */
20 1.1 christos
21 1.1 christos /* Contributed by Anthony Green <green (at) moxielogic.com>. */
22 1.1 christos
23 1.1 christos #include "as.h"
24 1.1 christos #include "safe-ctype.h"
25 1.1 christos #include "opcode/moxie.h"
26 1.1 christos #include "elf/moxie.h"
27 1.1 christos
28 1.1 christos extern const moxie_opc_info_t moxie_opc_info[128];
29 1.1 christos
30 1.1 christos const char comment_chars[] = "#";
31 1.1 christos const char line_separator_chars[] = ";";
32 1.1 christos const char line_comment_chars[] = "#";
33 1.1 christos
34 1.1 christos static int pending_reloc;
35 1.1 christos static struct hash_control *opcode_hash_control;
36 1.1 christos
37 1.1 christos const pseudo_typeS md_pseudo_table[] =
38 1.1 christos {
39 1.1 christos {0, 0, 0}
40 1.1 christos };
41 1.1 christos
42 1.1 christos const char FLT_CHARS[] = "rRsSfFdDxXpP";
43 1.1 christos const char EXP_CHARS[] = "eE";
44 1.1 christos
45 1.1.1.1.2.1 pgoyette static valueT md_chars_to_number (char * buf, int n);
46 1.1.1.1.2.1 pgoyette
47 1.1.1.1.2.1 pgoyette /* Byte order. */
48 1.1.1.1.2.1 pgoyette extern int target_big_endian;
49 1.1 christos
50 1.1 christos void
51 1.1 christos md_operand (expressionS *op __attribute__((unused)))
52 1.1 christos {
53 1.1 christos /* Empty for now. */
54 1.1 christos }
55 1.1 christos
56 1.1 christos /* This function is called once, at assembler startup time. It sets
57 1.1 christos up the hash table with all the opcodes in it, and also initializes
58 1.1 christos some aliases for compatibility with other assemblers. */
59 1.1 christos
60 1.1 christos void
61 1.1 christos md_begin (void)
62 1.1 christos {
63 1.1 christos int count;
64 1.1 christos const moxie_opc_info_t *opcode;
65 1.1 christos opcode_hash_control = hash_new ();
66 1.1 christos
67 1.1 christos /* Insert names into hash table. */
68 1.1 christos for (count = 0, opcode = moxie_form1_opc_info; count++ < 64; opcode++)
69 1.1 christos hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
70 1.1 christos
71 1.1 christos for (count = 0, opcode = moxie_form2_opc_info; count++ < 4; opcode++)
72 1.1 christos hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
73 1.1 christos
74 1.1 christos for (count = 0, opcode = moxie_form3_opc_info; count++ < 10; opcode++)
75 1.1 christos hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
76 1.1 christos
77 1.1.1.1.2.1 pgoyette target_big_endian = TARGET_BYTES_BIG_ENDIAN;
78 1.1.1.1.2.1 pgoyette
79 1.1 christos bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
80 1.1 christos }
81 1.1 christos
82 1.1 christos /* Parse an expression and then restore the input line pointer. */
83 1.1 christos
84 1.1 christos static char *
85 1.1 christos parse_exp_save_ilp (char *s, expressionS *op)
86 1.1 christos {
87 1.1 christos char *save = input_line_pointer;
88 1.1 christos
89 1.1 christos input_line_pointer = s;
90 1.1 christos expression (op);
91 1.1 christos s = input_line_pointer;
92 1.1 christos input_line_pointer = save;
93 1.1 christos return s;
94 1.1 christos }
95 1.1 christos
96 1.1 christos static int
97 1.1 christos parse_register_operand (char **ptr)
98 1.1 christos {
99 1.1 christos int reg;
100 1.1 christos char *s = *ptr;
101 1.1 christos
102 1.1 christos if (*s != '$')
103 1.1 christos {
104 1.1 christos as_bad (_("expecting register"));
105 1.1 christos ignore_rest_of_line ();
106 1.1 christos return -1;
107 1.1 christos }
108 1.1 christos if (s[1] == 'f' && s[2] == 'p')
109 1.1 christos {
110 1.1 christos *ptr += 3;
111 1.1 christos return 0;
112 1.1 christos }
113 1.1 christos if (s[1] == 's' && s[2] == 'p')
114 1.1 christos {
115 1.1 christos *ptr += 3;
116 1.1 christos return 1;
117 1.1 christos }
118 1.1 christos if (s[1] == 'r')
119 1.1 christos {
120 1.1 christos reg = s[2] - '0';
121 1.1 christos if ((reg < 0) || (reg > 9))
122 1.1 christos {
123 1.1 christos as_bad (_("illegal register number"));
124 1.1 christos ignore_rest_of_line ();
125 1.1 christos return -1;
126 1.1 christos }
127 1.1 christos if (reg == 1)
128 1.1 christos {
129 1.1 christos int r2 = s[3] - '0';
130 1.1 christos if ((r2 >= 0) && (r2 <= 3))
131 1.1 christos {
132 1.1 christos reg = 10 + r2;
133 1.1 christos *ptr += 1;
134 1.1 christos }
135 1.1 christos }
136 1.1 christos }
137 1.1 christos else
138 1.1 christos {
139 1.1 christos as_bad (_("illegal register number"));
140 1.1 christos ignore_rest_of_line ();
141 1.1 christos return -1;
142 1.1 christos }
143 1.1 christos
144 1.1 christos *ptr += 3;
145 1.1 christos
146 1.1 christos return reg + 2;
147 1.1 christos }
148 1.1 christos
149 1.1 christos /* This is the guts of the machine-dependent assembler. STR points to
150 1.1 christos a machine dependent instruction. This function is supposed to emit
151 1.1 christos the frags/bytes it assembles to. */
152 1.1 christos
153 1.1 christos void
154 1.1 christos md_assemble (char *str)
155 1.1 christos {
156 1.1 christos char *op_start;
157 1.1 christos char *op_end;
158 1.1 christos
159 1.1 christos moxie_opc_info_t *opcode;
160 1.1 christos char *p;
161 1.1 christos char pend;
162 1.1 christos
163 1.1 christos unsigned short iword = 0;
164 1.1 christos
165 1.1 christos int nlen = 0;
166 1.1 christos
167 1.1 christos /* Drop leading whitespace. */
168 1.1 christos while (*str == ' ')
169 1.1 christos str++;
170 1.1 christos
171 1.1 christos /* Find the op code end. */
172 1.1 christos op_start = str;
173 1.1 christos for (op_end = str;
174 1.1 christos *op_end && !is_end_of_line[*op_end & 0xff] && *op_end != ' ';
175 1.1 christos op_end++)
176 1.1 christos nlen++;
177 1.1 christos
178 1.1 christos pend = *op_end;
179 1.1 christos *op_end = 0;
180 1.1 christos
181 1.1 christos if (nlen == 0)
182 1.1 christos as_bad (_("can't find opcode "));
183 1.1 christos opcode = (moxie_opc_info_t *) hash_find (opcode_hash_control, op_start);
184 1.1 christos *op_end = pend;
185 1.1 christos
186 1.1 christos if (opcode == NULL)
187 1.1 christos {
188 1.1 christos as_bad (_("unknown opcode %s"), op_start);
189 1.1 christos return;
190 1.1 christos }
191 1.1 christos
192 1.1 christos p = frag_more (2);
193 1.1 christos
194 1.1 christos switch (opcode->itype)
195 1.1 christos {
196 1.1 christos case MOXIE_F2_A8V:
197 1.1 christos iword = (1<<15) | (opcode->opcode << 12);
198 1.1 christos while (ISSPACE (*op_end))
199 1.1 christos op_end++;
200 1.1 christos {
201 1.1 christos expressionS arg;
202 1.1 christos int reg;
203 1.1 christos reg = parse_register_operand (&op_end);
204 1.1 christos iword += (reg << 8);
205 1.1 christos if (*op_end != ',')
206 1.1 christos as_warn (_("expecting comma delimited register operands"));
207 1.1 christos op_end++;
208 1.1 christos op_end = parse_exp_save_ilp (op_end, &arg);
209 1.1 christos fix_new_exp (frag_now,
210 1.1.1.1.2.1 pgoyette ((p + (target_big_endian ? 1 : 0)) - frag_now->fr_literal),
211 1.1 christos 1,
212 1.1 christos &arg,
213 1.1 christos 0,
214 1.1 christos BFD_RELOC_8);
215 1.1 christos }
216 1.1 christos break;
217 1.1 christos case MOXIE_F1_AB:
218 1.1 christos iword = opcode->opcode << 8;
219 1.1 christos while (ISSPACE (*op_end))
220 1.1 christos op_end++;
221 1.1 christos {
222 1.1 christos int dest, src;
223 1.1 christos dest = parse_register_operand (&op_end);
224 1.1 christos if (*op_end != ',')
225 1.1 christos as_warn (_("expecting comma delimited register operands"));
226 1.1 christos op_end++;
227 1.1 christos src = parse_register_operand (&op_end);
228 1.1 christos iword += (dest << 4) + src;
229 1.1 christos while (ISSPACE (*op_end))
230 1.1 christos op_end++;
231 1.1 christos if (*op_end != 0)
232 1.1 christos as_warn (_("extra stuff on line ignored"));
233 1.1 christos }
234 1.1 christos break;
235 1.1 christos case MOXIE_F1_A4:
236 1.1 christos iword = opcode->opcode << 8;
237 1.1 christos while (ISSPACE (*op_end))
238 1.1 christos op_end++;
239 1.1 christos {
240 1.1 christos expressionS arg;
241 1.1 christos char *where;
242 1.1 christos int regnum;
243 1.1 christos
244 1.1 christos regnum = parse_register_operand (&op_end);
245 1.1 christos while (ISSPACE (*op_end))
246 1.1 christos op_end++;
247 1.1 christos
248 1.1 christos iword += (regnum << 4);
249 1.1 christos
250 1.1 christos if (*op_end != ',')
251 1.1 christos {
252 1.1 christos as_bad (_("expecting comma delimited operands"));
253 1.1 christos ignore_rest_of_line ();
254 1.1 christos return;
255 1.1 christos }
256 1.1 christos op_end++;
257 1.1 christos
258 1.1 christos op_end = parse_exp_save_ilp (op_end, &arg);
259 1.1 christos where = frag_more (4);
260 1.1 christos fix_new_exp (frag_now,
261 1.1 christos (where - frag_now->fr_literal),
262 1.1 christos 4,
263 1.1 christos &arg,
264 1.1 christos 0,
265 1.1 christos BFD_RELOC_32);
266 1.1 christos }
267 1.1 christos break;
268 1.1 christos case MOXIE_F1_M:
269 1.1 christos case MOXIE_F1_4:
270 1.1 christos iword = opcode->opcode << 8;
271 1.1 christos while (ISSPACE (*op_end))
272 1.1 christos op_end++;
273 1.1 christos {
274 1.1 christos expressionS arg;
275 1.1 christos char *where;
276 1.1 christos
277 1.1 christos op_end = parse_exp_save_ilp (op_end, &arg);
278 1.1 christos where = frag_more (4);
279 1.1 christos fix_new_exp (frag_now,
280 1.1 christos (where - frag_now->fr_literal),
281 1.1 christos 4,
282 1.1 christos &arg,
283 1.1 christos 0,
284 1.1 christos BFD_RELOC_32);
285 1.1 christos }
286 1.1 christos break;
287 1.1 christos case MOXIE_F1_NARG:
288 1.1 christos iword = opcode->opcode << 8;
289 1.1 christos while (ISSPACE (*op_end))
290 1.1 christos op_end++;
291 1.1 christos if (*op_end != 0)
292 1.1 christos as_warn (_("extra stuff on line ignored"));
293 1.1 christos break;
294 1.1 christos case MOXIE_F1_A:
295 1.1 christos iword = opcode->opcode << 8;
296 1.1 christos while (ISSPACE (*op_end))
297 1.1 christos op_end++;
298 1.1 christos {
299 1.1 christos int reg;
300 1.1 christos reg = parse_register_operand (&op_end);
301 1.1 christos while (ISSPACE (*op_end))
302 1.1 christos op_end++;
303 1.1 christos if (*op_end != 0)
304 1.1 christos as_warn (_("extra stuff on line ignored"));
305 1.1 christos iword += (reg << 4);
306 1.1 christos }
307 1.1 christos break;
308 1.1 christos case MOXIE_F1_ABi:
309 1.1 christos iword = opcode->opcode << 8;
310 1.1 christos while (ISSPACE (*op_end))
311 1.1 christos op_end++;
312 1.1 christos {
313 1.1 christos int a, b;
314 1.1 christos a = parse_register_operand (&op_end);
315 1.1 christos if (*op_end != ',')
316 1.1 christos as_warn (_("expecting comma delimited register operands"));
317 1.1 christos op_end++;
318 1.1 christos if (*op_end != '(')
319 1.1 christos {
320 1.1 christos as_bad (_("expecting indirect register `($rA)'"));
321 1.1 christos ignore_rest_of_line ();
322 1.1 christos return;
323 1.1 christos }
324 1.1 christos op_end++;
325 1.1 christos b = parse_register_operand (&op_end);
326 1.1 christos if (*op_end != ')')
327 1.1 christos {
328 1.1 christos as_bad (_("missing closing parenthesis"));
329 1.1 christos ignore_rest_of_line ();
330 1.1 christos return;
331 1.1 christos }
332 1.1 christos op_end++;
333 1.1 christos iword += (a << 4) + b;
334 1.1 christos while (ISSPACE (*op_end))
335 1.1 christos op_end++;
336 1.1 christos if (*op_end != 0)
337 1.1 christos as_warn (_("extra stuff on line ignored"));
338 1.1 christos }
339 1.1 christos break;
340 1.1 christos case MOXIE_F1_AiB:
341 1.1 christos iword = opcode->opcode << 8;
342 1.1 christos while (ISSPACE (*op_end))
343 1.1 christos op_end++;
344 1.1 christos {
345 1.1 christos int a, b;
346 1.1 christos if (*op_end != '(')
347 1.1 christos {
348 1.1 christos as_bad (_("expecting indirect register `($rA)'"));
349 1.1 christos ignore_rest_of_line ();
350 1.1 christos return;
351 1.1 christos }
352 1.1 christos op_end++;
353 1.1 christos a = parse_register_operand (&op_end);
354 1.1 christos if (*op_end != ')')
355 1.1 christos {
356 1.1 christos as_bad (_("missing closing parenthesis"));
357 1.1 christos ignore_rest_of_line ();
358 1.1 christos return;
359 1.1 christos }
360 1.1 christos op_end++;
361 1.1 christos if (*op_end != ',')
362 1.1 christos as_warn (_("expecting comma delimited register operands"));
363 1.1 christos op_end++;
364 1.1 christos b = parse_register_operand (&op_end);
365 1.1 christos iword += (a << 4) + b;
366 1.1 christos while (ISSPACE (*op_end))
367 1.1 christos op_end++;
368 1.1 christos if (*op_end != 0)
369 1.1 christos as_warn (_("extra stuff on line ignored"));
370 1.1 christos }
371 1.1 christos break;
372 1.1 christos case MOXIE_F1_4A:
373 1.1 christos iword = opcode->opcode << 8;
374 1.1 christos while (ISSPACE (*op_end))
375 1.1 christos op_end++;
376 1.1 christos {
377 1.1 christos expressionS arg;
378 1.1 christos char *where;
379 1.1 christos int a;
380 1.1 christos
381 1.1 christos op_end = parse_exp_save_ilp (op_end, &arg);
382 1.1 christos where = frag_more (4);
383 1.1 christos fix_new_exp (frag_now,
384 1.1 christos (where - frag_now->fr_literal),
385 1.1 christos 4,
386 1.1 christos &arg,
387 1.1 christos 0,
388 1.1 christos BFD_RELOC_32);
389 1.1 christos
390 1.1 christos if (*op_end != ',')
391 1.1 christos {
392 1.1 christos as_bad (_("expecting comma delimited operands"));
393 1.1 christos ignore_rest_of_line ();
394 1.1 christos return;
395 1.1 christos }
396 1.1 christos op_end++;
397 1.1 christos
398 1.1 christos a = parse_register_operand (&op_end);
399 1.1 christos while (ISSPACE (*op_end))
400 1.1 christos op_end++;
401 1.1 christos if (*op_end != 0)
402 1.1 christos as_warn (_("extra stuff on line ignored"));
403 1.1 christos
404 1.1 christos iword += (a << 4);
405 1.1 christos }
406 1.1 christos break;
407 1.1.1.1.2.1 pgoyette case MOXIE_F1_ABi2:
408 1.1 christos iword = opcode->opcode << 8;
409 1.1 christos while (ISSPACE (*op_end))
410 1.1 christos op_end++;
411 1.1 christos {
412 1.1 christos expressionS arg;
413 1.1 christos char *offset;
414 1.1 christos int a, b;
415 1.1 christos
416 1.1 christos a = parse_register_operand (&op_end);
417 1.1 christos while (ISSPACE (*op_end))
418 1.1 christos op_end++;
419 1.1 christos
420 1.1 christos if (*op_end != ',')
421 1.1 christos {
422 1.1 christos as_bad (_("expecting comma delimited operands"));
423 1.1 christos ignore_rest_of_line ();
424 1.1 christos return;
425 1.1 christos }
426 1.1 christos op_end++;
427 1.1 christos
428 1.1 christos op_end = parse_exp_save_ilp (op_end, &arg);
429 1.1.1.1.2.1 pgoyette offset = frag_more (2);
430 1.1 christos fix_new_exp (frag_now,
431 1.1 christos (offset - frag_now->fr_literal),
432 1.1.1.1.2.1 pgoyette 2,
433 1.1 christos &arg,
434 1.1 christos 0,
435 1.1.1.1.2.1 pgoyette BFD_RELOC_16);
436 1.1 christos
437 1.1 christos if (*op_end != '(')
438 1.1 christos {
439 1.1 christos as_bad (_("expecting indirect register `($rX)'"));
440 1.1 christos ignore_rest_of_line ();
441 1.1 christos return;
442 1.1 christos }
443 1.1 christos op_end++;
444 1.1 christos b = parse_register_operand (&op_end);
445 1.1 christos if (*op_end != ')')
446 1.1 christos {
447 1.1 christos as_bad (_("missing closing parenthesis"));
448 1.1 christos ignore_rest_of_line ();
449 1.1 christos return;
450 1.1 christos }
451 1.1 christos op_end++;
452 1.1 christos
453 1.1 christos while (ISSPACE (*op_end))
454 1.1 christos op_end++;
455 1.1 christos if (*op_end != 0)
456 1.1 christos as_warn (_("extra stuff on line ignored"));
457 1.1 christos
458 1.1 christos iword += (a << 4) + b;
459 1.1 christos }
460 1.1 christos break;
461 1.1.1.1.2.1 pgoyette case MOXIE_F1_AiB2:
462 1.1 christos iword = opcode->opcode << 8;
463 1.1 christos while (ISSPACE (*op_end))
464 1.1 christos op_end++;
465 1.1 christos {
466 1.1 christos expressionS arg;
467 1.1 christos char *offset;
468 1.1 christos int a, b;
469 1.1 christos
470 1.1 christos op_end = parse_exp_save_ilp (op_end, &arg);
471 1.1.1.1.2.1 pgoyette offset = frag_more (2);
472 1.1 christos fix_new_exp (frag_now,
473 1.1 christos (offset - frag_now->fr_literal),
474 1.1.1.1.2.1 pgoyette 2,
475 1.1 christos &arg,
476 1.1 christos 0,
477 1.1.1.1.2.1 pgoyette BFD_RELOC_16);
478 1.1 christos
479 1.1 christos if (*op_end != '(')
480 1.1 christos {
481 1.1 christos as_bad (_("expecting indirect register `($rX)'"));
482 1.1 christos ignore_rest_of_line ();
483 1.1 christos return;
484 1.1 christos }
485 1.1 christos op_end++;
486 1.1 christos a = parse_register_operand (&op_end);
487 1.1 christos if (*op_end != ')')
488 1.1 christos {
489 1.1 christos as_bad (_("missing closing parenthesis"));
490 1.1 christos ignore_rest_of_line ();
491 1.1 christos return;
492 1.1 christos }
493 1.1 christos op_end++;
494 1.1 christos
495 1.1 christos if (*op_end != ',')
496 1.1 christos {
497 1.1 christos as_bad (_("expecting comma delimited operands"));
498 1.1 christos ignore_rest_of_line ();
499 1.1 christos return;
500 1.1 christos }
501 1.1 christos op_end++;
502 1.1 christos
503 1.1 christos b = parse_register_operand (&op_end);
504 1.1 christos while (ISSPACE (*op_end))
505 1.1 christos op_end++;
506 1.1 christos
507 1.1 christos while (ISSPACE (*op_end))
508 1.1 christos op_end++;
509 1.1 christos if (*op_end != 0)
510 1.1 christos as_warn (_("extra stuff on line ignored"));
511 1.1 christos
512 1.1 christos iword += (a << 4) + b;
513 1.1 christos }
514 1.1 christos break;
515 1.1 christos case MOXIE_F2_NARG:
516 1.1 christos iword = opcode->opcode << 12;
517 1.1 christos while (ISSPACE (*op_end))
518 1.1 christos op_end++;
519 1.1 christos if (*op_end != 0)
520 1.1 christos as_warn (_("extra stuff on line ignored"));
521 1.1 christos break;
522 1.1 christos case MOXIE_F3_PCREL:
523 1.1 christos iword = (3<<14) | (opcode->opcode << 10);
524 1.1 christos while (ISSPACE (*op_end))
525 1.1 christos op_end++;
526 1.1 christos {
527 1.1 christos expressionS arg;
528 1.1 christos
529 1.1 christos op_end = parse_exp_save_ilp (op_end, &arg);
530 1.1 christos fix_new_exp (frag_now,
531 1.1 christos (p - frag_now->fr_literal),
532 1.1 christos 2,
533 1.1 christos &arg,
534 1.1 christos TRUE,
535 1.1 christos BFD_RELOC_MOXIE_10_PCREL);
536 1.1 christos }
537 1.1 christos break;
538 1.1 christos default:
539 1.1 christos abort ();
540 1.1 christos }
541 1.1 christos
542 1.1 christos md_number_to_chars (p, iword, 2);
543 1.1 christos
544 1.1 christos while (ISSPACE (*op_end))
545 1.1 christos op_end++;
546 1.1 christos
547 1.1 christos if (*op_end != 0)
548 1.1 christos as_warn (_("extra stuff on line ignored"));
549 1.1 christos
550 1.1 christos if (pending_reloc)
551 1.1 christos as_bad (_("Something forgot to clean up\n"));
552 1.1 christos }
553 1.1 christos
554 1.1 christos /* Turn a string in input_line_pointer into a floating point constant
555 1.1 christos of type type, and store the appropriate bytes in *LITP. The number
556 1.1 christos of LITTLENUMS emitted is stored in *SIZEP . An error message is
557 1.1 christos returned, or NULL on OK. */
558 1.1 christos
559 1.1 christos char *
560 1.1 christos md_atof (int type, char *litP, int *sizeP)
561 1.1 christos {
562 1.1 christos int prec;
563 1.1 christos LITTLENUM_TYPE words[4];
564 1.1 christos char *t;
565 1.1 christos int i;
566 1.1 christos
567 1.1 christos switch (type)
568 1.1 christos {
569 1.1 christos case 'f':
570 1.1 christos prec = 2;
571 1.1 christos break;
572 1.1 christos
573 1.1 christos case 'd':
574 1.1 christos prec = 4;
575 1.1 christos break;
576 1.1 christos
577 1.1 christos default:
578 1.1 christos *sizeP = 0;
579 1.1 christos return _("bad call to md_atof");
580 1.1 christos }
581 1.1 christos
582 1.1 christos t = atof_ieee (input_line_pointer, type, words);
583 1.1 christos if (t)
584 1.1 christos input_line_pointer = t;
585 1.1 christos
586 1.1 christos *sizeP = prec * 2;
587 1.1 christos
588 1.1 christos for (i = prec - 1; i >= 0; i--)
589 1.1 christos {
590 1.1 christos md_number_to_chars (litP, (valueT) words[i], 2);
591 1.1 christos litP += 2;
592 1.1 christos }
593 1.1 christos
594 1.1 christos return NULL;
595 1.1 christos }
596 1.1.1.1.2.1 pgoyette
597 1.1.1.1.2.1 pgoyette enum options
598 1.1.1.1.2.1 pgoyette {
599 1.1.1.1.2.1 pgoyette OPTION_EB = OPTION_MD_BASE,
600 1.1.1.1.2.1 pgoyette OPTION_EL,
601 1.1.1.1.2.1 pgoyette };
602 1.1 christos
603 1.1 christos struct option md_longopts[] =
604 1.1 christos {
605 1.1.1.1.2.1 pgoyette { "EB", no_argument, NULL, OPTION_EB},
606 1.1.1.1.2.1 pgoyette { "EL", no_argument, NULL, OPTION_EL},
607 1.1.1.1.2.1 pgoyette { NULL, no_argument, NULL, 0}
608 1.1 christos };
609 1.1.1.1.2.1 pgoyette
610 1.1 christos size_t md_longopts_size = sizeof (md_longopts);
611 1.1.1.1.2.1 pgoyette
612 1.1.1.1.2.1 pgoyette const char *md_shortopts = "";
614 1.1 christos
615 1.1 christos int
616 1.1 christos md_parse_option (int c ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED)
617 1.1.1.1.2.1 pgoyette {
618 1.1.1.1.2.1 pgoyette switch (c)
619 1.1.1.1.2.1 pgoyette {
620 1.1.1.1.2.1 pgoyette case OPTION_EB:
621 1.1.1.1.2.1 pgoyette target_big_endian = 1;
622 1.1.1.1.2.1 pgoyette break;
623 1.1.1.1.2.1 pgoyette case OPTION_EL:
624 1.1.1.1.2.1 pgoyette target_big_endian = 0;
625 1.1.1.1.2.1 pgoyette break;
626 1.1.1.1.2.1 pgoyette default:
627 1.1.1.1.2.1 pgoyette return 0;
628 1.1.1.1.2.1 pgoyette }
629 1.1.1.1.2.1 pgoyette
630 1.1 christos return 1;
631 1.1 christos }
632 1.1 christos
633 1.1 christos void
634 1.1 christos md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
635 1.1.1.1.2.1 pgoyette {
636 1.1.1.1.2.1 pgoyette fprintf (stream, _("\
637 1.1.1.1.2.1 pgoyette -EB assemble for a big endian system (default)\n\
638 1.1 christos -EL assemble for a little endian system\n"));
639 1.1 christos }
640 1.1 christos
641 1.1 christos /* Apply a fixup to the object file. */
642 1.1 christos
643 1.1.1.1.2.1 pgoyette void
644 1.1 christos md_apply_fix (fixS *fixP ATTRIBUTE_UNUSED,
645 1.1 christos valueT * valP ATTRIBUTE_UNUSED, segT seg ATTRIBUTE_UNUSED)
646 1.1 christos {
647 1.1 christos char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
648 1.1 christos long val = *valP;
649 1.1 christos long newval;
650 1.1 christos long max, min;
651 1.1 christos
652 1.1 christos max = min = 0;
653 1.1 christos switch (fixP->fx_r_type)
654 1.1 christos {
655 1.1.1.1.2.1 pgoyette case BFD_RELOC_32:
656 1.1.1.1.2.1 pgoyette if (target_big_endian)
657 1.1.1.1.2.1 pgoyette {
658 1.1.1.1.2.1 pgoyette buf[0] = val >> 24;
659 1.1.1.1.2.1 pgoyette buf[1] = val >> 16;
660 1.1.1.1.2.1 pgoyette buf[2] = val >> 8;
661 1.1.1.1.2.1 pgoyette buf[3] = val >> 0;
662 1.1.1.1.2.1 pgoyette }
663 1.1.1.1.2.1 pgoyette else
664 1.1.1.1.2.1 pgoyette {
665 1.1.1.1.2.1 pgoyette buf[3] = val >> 24;
666 1.1.1.1.2.1 pgoyette buf[2] = val >> 16;
667 1.1.1.1.2.1 pgoyette buf[1] = val >> 8;
668 1.1.1.1.2.1 pgoyette buf[0] = val >> 0;
669 1.1.1.1.2.1 pgoyette }
670 1.1 christos buf += 4;
671 1.1 christos break;
672 1.1 christos
673 1.1.1.1.2.1 pgoyette case BFD_RELOC_16:
674 1.1.1.1.2.1 pgoyette if (target_big_endian)
675 1.1.1.1.2.1 pgoyette {
676 1.1.1.1.2.1 pgoyette buf[0] = val >> 8;
677 1.1.1.1.2.1 pgoyette buf[1] = val >> 0;
678 1.1.1.1.2.1 pgoyette }
679 1.1.1.1.2.1 pgoyette else
680 1.1.1.1.2.1 pgoyette {
681 1.1.1.1.2.1 pgoyette buf[1] = val >> 8;
682 1.1.1.1.2.1 pgoyette buf[0] = val >> 0;
683 1.1.1.1.2.1 pgoyette }
684 1.1 christos buf += 2;
685 1.1 christos break;
686 1.1 christos
687 1.1 christos case BFD_RELOC_8:
688 1.1 christos *buf++ = val;
689 1.1 christos break;
690 1.1 christos
691 1.1 christos case BFD_RELOC_MOXIE_10_PCREL:
692 1.1 christos if (!val)
693 1.1 christos break;
694 1.1 christos if (val < -1024 || val > 1022)
695 1.1 christos as_bad_where (fixP->fx_file, fixP->fx_line,
696 1.1 christos _("pcrel too far BFD_RELOC_MOXIE_10"));
697 1.1 christos /* 11 bit offset even numbered, so we remove right bit. */
698 1.1 christos val >>= 1;
699 1.1 christos newval = md_chars_to_number (buf, 2);
700 1.1 christos newval |= val & 0x03ff;
701 1.1 christos md_number_to_chars (buf, newval, 2);
702 1.1 christos break;
703 1.1 christos
704 1.1 christos default:
705 1.1 christos abort ();
706 1.1 christos }
707 1.1 christos
708 1.1 christos if (max != 0 && (val < min || val > max))
709 1.1 christos as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range"));
710 1.1 christos
711 1.1 christos if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
712 1.1 christos fixP->fx_done = 1;
713 1.1 christos }
714 1.1.1.1.2.1 pgoyette
715 1.1 christos /* Put number into target byte order. */
716 1.1 christos
717 1.1.1.1.2.1 pgoyette void
718 1.1 christos md_number_to_chars (char * ptr, valueT use, int nbytes)
719 1.1.1.1.2.1 pgoyette {
720 1.1.1.1.2.1 pgoyette if (target_big_endian)
721 1.1.1.1.2.1 pgoyette number_to_chars_bigendian (ptr, use, nbytes);
722 1.1.1.1.2.1 pgoyette else
723 1.1 christos number_to_chars_littleendian (ptr, use, nbytes);
724 1.1 christos }
725 1.1 christos
726 1.1 christos /* Convert from target byte order to host byte order. */
727 1.1.1.1.2.1 pgoyette
728 1.1.1.1.2.1 pgoyette static valueT
729 1.1 christos md_chars_to_number (char * buf, int n)
730 1.1.1.1.2.1 pgoyette {
731 1.1.1.1.2.1 pgoyette valueT result = 0;
732 1.1 christos unsigned char * where = (unsigned char *) buf;
733 1.1.1.1.2.1 pgoyette
734 1.1.1.1.2.1 pgoyette if (target_big_endian)
735 1.1.1.1.2.1 pgoyette {
736 1.1.1.1.2.1 pgoyette while (n--)
737 1.1.1.1.2.1 pgoyette {
738 1.1.1.1.2.1 pgoyette result <<= 8;
739 1.1.1.1.2.1 pgoyette result |= (*where++ & 255);
740 1.1.1.1.2.1 pgoyette }
741 1.1.1.1.2.1 pgoyette }
742 1.1 christos else
743 1.1.1.1.2.1 pgoyette {
744 1.1.1.1.2.1 pgoyette while (n--)
745 1.1.1.1.2.1 pgoyette {
746 1.1.1.1.2.1 pgoyette result <<= 8;
747 1.1.1.1.2.1 pgoyette result |= (where[n] & 255);
748 1.1 christos }
749 1.1 christos }
750 1.1.1.1.2.1 pgoyette
751 1.1 christos return result;
752 1.1 christos }
753 1.1 christos
754 1.1 christos /* Generate a machine-dependent relocation. */
755 1.1 christos arelent *
756 1.1 christos tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
757 1.1 christos {
758 1.1 christos arelent *relP;
759 1.1 christos bfd_reloc_code_real_type code;
760 1.1 christos
761 1.1 christos switch (fixP->fx_r_type)
762 1.1 christos {
763 1.1 christos case BFD_RELOC_32:
764 1.1 christos code = fixP->fx_r_type;
765 1.1 christos break;
766 1.1 christos case BFD_RELOC_MOXIE_10_PCREL:
767 1.1 christos code = fixP->fx_r_type;
768 1.1 christos break;
769 1.1 christos default:
770 1.1 christos as_bad_where (fixP->fx_file, fixP->fx_line,
771 1.1 christos _("Semantics error. This type of operand can not be relocated, it must be an assembly-time constant"));
772 1.1 christos return 0;
773 1.1 christos }
774 1.1 christos
775 1.1 christos relP = xmalloc (sizeof (arelent));
776 1.1 christos gas_assert (relP != 0);
777 1.1 christos relP->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
778 1.1 christos *relP->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
779 1.1 christos relP->address = fixP->fx_frag->fr_address + fixP->fx_where;
780 1.1 christos
781 1.1 christos relP->addend = fixP->fx_offset;
782 1.1 christos
783 1.1 christos /* This is the standard place for KLUDGEs to work around bugs in
784 1.1 christos bfd_install_relocation (first such note in the documentation
785 1.1 christos appears with binutils-2.8).
786 1.1 christos
787 1.1 christos That function bfd_install_relocation does the wrong thing with
788 1.1 christos putting stuff into the addend of a reloc (it should stay out) for a
789 1.1 christos weak symbol. The really bad thing is that it adds the
790 1.1 christos "segment-relative offset" of the symbol into the reloc. In this
791 1.1 christos case, the reloc should instead be relative to the symbol with no
792 1.1 christos other offset than the assembly code shows; and since the symbol is
793 1.1 christos weak, any local definition should be ignored until link time (or
794 1.1 christos thereafter).
795 1.1 christos To wit: weaksym+42 should be weaksym+42 in the reloc,
796 1.1 christos not weaksym+(offset_from_segment_of_local_weaksym_definition)
797 1.1 christos
798 1.1 christos To "work around" this, we subtract the segment-relative offset of
799 1.1 christos "known" weak symbols. This evens out the extra offset.
800 1.1 christos
801 1.1 christos That happens for a.out but not for ELF, since for ELF,
802 1.1 christos bfd_install_relocation uses the "special function" field of the
803 1.1 christos howto, and does not execute the code that needs to be undone. */
804 1.1 christos
805 1.1 christos if (OUTPUT_FLAVOR == bfd_target_aout_flavour
806 1.1 christos && fixP->fx_addsy && S_IS_WEAK (fixP->fx_addsy)
807 1.1 christos && ! bfd_is_und_section (S_GET_SEGMENT (fixP->fx_addsy)))
808 1.1 christos {
809 1.1 christos relP->addend -= S_GET_VALUE (fixP->fx_addsy);
810 1.1 christos }
811 1.1 christos
812 1.1 christos relP->howto = bfd_reloc_type_lookup (stdoutput, code);
813 1.1 christos if (! relP->howto)
814 1.1 christos {
815 1.1 christos const char *name;
816 1.1 christos
817 1.1 christos name = S_GET_NAME (fixP->fx_addsy);
818 1.1 christos if (name == NULL)
819 1.1 christos name = _("<unknown>");
820 1.1 christos as_fatal (_("Cannot generate relocation type for symbol %s, code %s"),
821 1.1 christos name, bfd_get_reloc_code_name (code));
822 1.1 christos }
823 1.1 christos
824 1.1 christos return relP;
825 1.1 christos }
826 1.1 christos
827 1.1 christos /* Decide from what point a pc-relative relocation is relative to,
828 1.1 christos relative to the pc-relative fixup. Er, relatively speaking. */
829 1.1 christos long
830 1.1 christos md_pcrel_from (fixS *fixP)
831 1.1 christos {
832 1.1 christos valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
833 1.1 christos
834 1.1 christos switch (fixP->fx_r_type)
835 1.1 christos {
836 1.1 christos case BFD_RELOC_32:
837 1.1 christos return addr + 4;
838 1.1.1.1.2.1 pgoyette case BFD_RELOC_MOXIE_10_PCREL:
839 1.1.1.1.2.1 pgoyette /* Offset is from the end of the instruction. */
840 1.1 christos return addr + 2;
841 1.1 christos default:
842 1.1 christos abort ();
843 1.1 christos return addr;
844 1.1 christos }
845 }
846