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