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