1 /* m88k.c -- Assembler for the Motorola 88000
2 Contributed by Devon Bowen of Buffalo University
3 and Torbjorn Granlund of the Swedish Institute of Computer Science.
4 Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1999,
5 2000, 2001, 2002
6 Free Software Foundation, Inc.
7
8 This file is part of GAS, the GNU Assembler.
9
10 GAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14
15 GAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with GAS; see the file COPYING. If not, write to the Free
22 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 02111-1307, USA. */
24
25 #include "as.h"
26 #include "safe-ctype.h"
27 #include "subsegs.h"
28 #include "m88k-opcode.h"
29
30 #if defined (OBJ_ELF)
31 #include "elf/m88k.h"
32 #endif
33
34 #ifdef BFD_ASSEMBLER
35 #define RELOC_LO16 BFD_RELOC_LO16
36 #define RELOC_HI16 BFD_RELOC_HI16
37 #define RELOC_PC16 BFD_RELOC_18_PCREL_S2
38 #define RELOC_PC26 BFD_RELOC_28_PCREL_S2
39 #define RELOC_32 BFD_RELOC_32
40 #define NO_RELOC BFD_RELOC_NONE
41 #endif
42
43 struct field_val_assoc
44 {
45 char *name;
46 unsigned val;
47 };
48
49 struct field_val_assoc m88100_cr_regs[] =
50 {
51 {"PID", 0},
52 {"PSR", 1},
53 {"EPSR", 2},
54 {"SSBR", 3},
55 {"SXIP", 4},
56 {"SNIP", 5},
57 {"SFIP", 6},
58 {"VBR", 7},
59 {"DMT0", 8},
60 {"DMD0", 9},
61 {"DMA0", 10},
62 {"DMT1", 11},
63 {"DMD1", 12},
64 {"DMA1", 13},
65 {"DMT2", 14},
66 {"DMD2", 15},
67 {"DMA2", 16},
68 {"SR0", 17},
69 {"SR1", 18},
70 {"SR2", 19},
71 {"SR3", 20},
72
73 {NULL, 0},
74 };
75
76 struct field_val_assoc m88110_cr_regs[] =
77 {
78 {"PID", 0},
79 {"PSR", 1},
80 {"EPSR", 2},
81 {"EXIP", 4},
82 {"ENIP", 5},
83 {"VBR", 7},
84 {"SRX", 16},
85 {"SR0", 17},
86 {"SR1", 18},
87 {"SR2", 19},
88 {"SR3", 20},
89 {"ICMD", 25},
90 {"ICTL", 26},
91 {"ISAR", 27},
92 {"ISAP", 28},
93 {"IUAP", 29},
94 {"IIR", 30},
95 {"IBP", 31},
96 {"IPPU", 32},
97 {"IPPL", 33},
98 {"ISR", 34},
99 {"ILAR", 35},
100 {"IPAR", 36},
101 {"DCMD", 40},
102 {"DCTL", 41},
103 {"DSAR", 42},
104 {"DSAP", 43},
105 {"DUAP", 44},
106 {"DIR", 45},
107 {"DBP", 46},
108 {"DPPU", 47},
109 {"DPPL", 48},
110 {"DSR", 49},
111 {"DLAR", 50},
112 {"DPAR", 51},
113
114 {NULL, 0},
115 };
116
117 struct field_val_assoc fcr_regs[] =
118 {
119 {"FPECR", 0},
120 {"FPHS1", 1},
121 {"FPLS1", 2},
122 {"FPHS2", 3},
123 {"FPLS2", 4},
124 {"FPPT", 5},
125 {"FPRH", 6},
126 {"FPRL", 7},
127 {"FPIT", 8},
128
129 {"FPSR", 62},
130 {"FPCR", 63},
131
132 {NULL, 0},
133 };
134
135 struct field_val_assoc cmpslot[] =
136 {
137 /* Integer Floating point */
138 {"nc", 0},
139 {"cp", 1},
140 {"eq", 2},
141 {"ne", 3},
142 {"gt", 4},
143 {"le", 5},
144 {"lt", 6},
145 {"ge", 7},
146 {"hi", 8}, {"ou", 8},
147 {"ls", 9}, {"ib", 9},
148 {"lo", 10}, {"in", 10},
149 {"hs", 11}, {"ob", 11},
150 {"be", 12}, {"ue", 12},
151 {"nb", 13}, {"lg", 13},
152 {"he", 14}, {"ug", 14},
153 {"nh", 15}, {"ule", 15},
154 {"ul", 16},
155 {"uge", 17},
156
157 {NULL, 0},
158 };
159
160 struct field_val_assoc cndmsk[] =
161 {
162 {"gt0", 1},
163 {"eq0", 2},
164 {"ge0", 3},
165 {"lt0", 12},
166 {"ne0", 13},
167 {"le0", 14},
168
169 {NULL, 0},
170 };
171
172 struct m88k_insn
173 {
174 unsigned long opcode;
175 expressionS exp;
176 enum m88k_reloc_type reloc;
177 };
178
179 static char *get_bf PARAMS ((char *param, unsigned *valp));
180 static char *get_cmp PARAMS ((char *param, unsigned *valp));
181 static char *get_cnd PARAMS ((char *param, unsigned *valp));
182 static char *get_bf2 PARAMS ((char *param, int bc));
183 static char *get_bf_offset_expression PARAMS ((char *param, unsigned *offsetp));
184 static char *get_cr PARAMS ((char *param, unsigned *regnop));
185 static char *get_fcr PARAMS ((char *param, unsigned *regnop));
186 static char *get_imm16 PARAMS ((char *param, struct m88k_insn *insn));
187 static char *get_o6 PARAMS ((char *param, unsigned *valp));
188 static char *match_name PARAMS ((char *, struct field_val_assoc *, unsigned *));
189 static char *get_reg PARAMS ((char *param, unsigned *regnop, unsigned int reg_prefix));
190 static char *get_vec9 PARAMS ((char *param, unsigned *valp));
191 static char *getval PARAMS ((char *param, unsigned int *valp));
192 static char *get_pcr PARAMS ((char *param, struct m88k_insn *insn,
193 enum m88k_reloc_type reloc));
194
195 static int calcop PARAMS ((struct m88k_opcode *format,
196 char *param, struct m88k_insn *insn));
197
198 static void s_m88k_88110 PARAMS ((int));
199
200 static struct hash_control *op_hash = NULL;
201
202 /* Current cpu (either 88100 or 88110, or 0 if unspecified). Defaults to
203 zero, overriden with -m<cpu> options or assembler pseudo-ops. */
204 static int current_cpu = 0;
205
206 /* These chars start a comment anywhere in a source file (except inside
207 another comment. */
208 #if defined(OBJ_ELF)
209 const char comment_chars[] = "|";
210 #elif defined(OBJ_AOUT)
211 const char comment_chars[] = "|#";
212 #else
213 const char comment_chars[] = ";";
214 #endif
215
216 /* These chars only start a comment at the beginning of a line. */
217 #if defined(OBJ_AOUT)
218 const char line_comment_chars[] = ";";
219 #else
220 const char line_comment_chars[] = "#";
221 #endif
222
223 #if defined(OBJ_ELF)
224 const char line_separator_chars[] = ";";
225 #else
226 const char line_separator_chars[] = "";
227 #endif
228
229 /* Chars that can be used to separate mant from exp in floating point nums */
230 const char EXP_CHARS[] = "eE";
231
232 /* Chars that mean this number is a floating point constant */
233 /* as in 0f123.456 */
234 /* or 0H1.234E-12 (see exp chars above) */
235 const char FLT_CHARS[] = "dDfF";
236
237 const pseudo_typeS md_pseudo_table[] =
238 {
239 #ifndef OBJ_ELF
240 {"align", s_align_bytes, 4},
241 #else
242 /* handled with s_align_ptwo in read.c potable[] */
243 #endif
244 {"bss", s_lcomm, 1},
245 {"def", s_set, 0},
246 {"half", cons, 2},
247 {"requires_88110", s_m88k_88110, 0},
248 {"sbss", s_lcomm, 1},
249 #if !defined(OBJ_ELF) || !defined(TE_OpenBSD) /* i.e. NO_PSEUDO_DOT == 1 */
250 /* Force set to be treated as an instruction. */
251 {"set", NULL, 0},
252 {".set", s_set, 0},
253 #endif
254 {"uahalf", cons, 2},
255 {"uaword", cons, 4},
256 {"word", cons, 4}, /* override potable[] which has word == short */
257 {NULL, NULL, 0}
258 };
259
260 static void
s_m88k_88110(i)261 s_m88k_88110(i)
262 int i ATTRIBUTE_UNUSED;
263 {
264 current_cpu = 88110;
265 }
266
267 void
md_begin()268 md_begin ()
269 {
270 const char *retval = NULL;
271 unsigned int i = 0;
272
273 /* Initialize hash table. */
274 op_hash = hash_new ();
275
276 while (*m88k_opcodes[i].name)
277 {
278 char *name = m88k_opcodes[i].name;
279
280 /* Hash each mnemonic and record its position. */
281 retval = hash_insert (op_hash, name, &m88k_opcodes[i]);
282
283 if (retval != NULL)
284 as_fatal (_("Can't hash instruction '%s':%s"),
285 m88k_opcodes[i].name, retval);
286
287 /* Skip to next unique mnemonic or end of list. */
288 for (i++; !strcmp (m88k_opcodes[i].name, name); i++)
289 ;
290 }
291
292 #ifdef OBJ_ELF
293 record_alignment (text_section, 2);
294 record_alignment (data_section, 2);
295 record_alignment (bss_section, 2);
296
297 bfd_set_private_flags (stdoutput, 0);
298 #endif
299 }
300
301 const char *md_shortopts = "m:";
302 struct option md_longopts[] = {
303 {NULL, no_argument, NULL, 0}
304 };
305 size_t md_longopts_size = sizeof (md_longopts);
306
307 int
md_parse_option(c,arg)308 md_parse_option (c, arg)
309 int c;
310 char *arg;
311 {
312 switch (c)
313 {
314 case 'm':
315 if (strcmp (arg, "88100") == 0)
316 current_cpu = 88100;
317 else if (strcmp (arg, "88110") == 0)
318 current_cpu = 88110;
319 else
320 as_bad (_("Option `%s' is not recognized."), arg);
321 break;
322
323 default:
324 return 0;
325 }
326
327 return 1;
328 }
329
330 void
md_show_usage(stream)331 md_show_usage (stream)
332 FILE *stream;
333 {
334 fputs (_("\
335 M88k options:\n\
336 -m88100 | -m88110 select processor type\n"),
337 stream);
338 }
339
340 #ifdef OBJ_ELF
341 enum m88k_pic_reloc_type {
342 pic_reloc_none,
343 pic_reloc_abdiff,
344 pic_reloc_gotrel,
345 pic_reloc_plt
346 };
347
348 static bfd_reloc_code_real_type
m88k_get_reloc_code(struct m88k_insn * insn)349 m88k_get_reloc_code(struct m88k_insn *insn)
350 {
351 switch (insn->exp.X_md)
352 {
353 default:
354 case pic_reloc_none:
355 return insn->reloc;
356
357 case pic_reloc_abdiff:
358 if (insn->reloc == BFD_RELOC_LO16)
359 return BFD_RELOC_LO16_BASEREL;
360 if (insn->reloc == BFD_RELOC_HI16)
361 return BFD_RELOC_HI16_BASEREL;
362 break;
363
364 case pic_reloc_gotrel:
365 if (insn->reloc == BFD_RELOC_LO16)
366 return BFD_RELOC_LO16_GOTOFF;
367 if (insn->reloc == BFD_RELOC_HI16)
368 return BFD_RELOC_HI16_GOTOFF;
369 break;
370
371 case pic_reloc_plt:
372 if (insn->reloc == BFD_RELOC_32)
373 return BFD_RELOC_32_PLTOFF;
374 if (insn->reloc == BFD_RELOC_28_PCREL_S2)
375 return BFD_RELOC_32_PLT_PCREL;
376 break;
377 }
378
379 as_bad ("Can't process pic type %d relocation type %d",
380 insn->exp.X_md, insn->reloc);
381
382 return BFD_RELOC_NONE;
383 }
384 #else
385 #define m88k_get_reloc_code(insn) (insn).reloc
386 #endif
387
388 void
md_assemble(op)389 md_assemble (op)
390 char *op;
391 {
392 char *param, *thisfrag;
393 char c;
394 struct m88k_opcode *format;
395 struct m88k_insn insn;
396 fixS *fixP;
397
398 assert (op);
399
400 /* Skip over instruction to find parameters. */
401 for (param = op; *param != 0 && !ISSPACE (*param); param++)
402 ;
403 c = *param;
404 *param++ = '\0';
405
406 /* Try to find the instruction in the hash table. */
407 /* XXX will not match XRF flavours of 88100 instructions on 88110 */
408 if ((format = (struct m88k_opcode *) hash_find (op_hash, op)) == NULL)
409 {
410 as_bad (_("Invalid mnemonic '%s'"), op);
411 return;
412 }
413
414 /* Try parsing this instruction into insn. */
415 insn.exp.X_add_symbol = 0;
416 insn.exp.X_op_symbol = 0;
417 insn.exp.X_add_number = 0;
418 insn.exp.X_op = O_illegal;
419 insn.exp.X_md = pic_reloc_none;
420 insn.reloc = NO_RELOC;
421
422 while (!calcop (format, param, &insn))
423 {
424 /* If it doesn't parse try the next instruction. */
425 if (!strcmp (format[0].name, format[1].name))
426 format++;
427 else
428 {
429 as_fatal (_("Parameter syntax error"));
430 return;
431 }
432 }
433
434 /* Grow the current frag and plop in the opcode. */
435 thisfrag = frag_more (4);
436 md_number_to_chars (thisfrag, insn.opcode, 4);
437
438 /* If this instruction requires labels mark it for later. */
439 switch (insn.reloc)
440 {
441 case NO_RELOC:
442 break;
443
444 case RELOC_LO16:
445 case RELOC_HI16:
446 fixP = fix_new_exp (frag_now,
447 thisfrag - frag_now->fr_literal + 2,
448 2,
449 &insn.exp,
450 0,
451 m88k_get_reloc_code(&insn));
452 fixP->fx_no_overflow = 1;
453 break;
454
455 #ifdef M88KCOFF
456 case RELOC_IW16:
457 fix_new_exp (frag_now,
458 thisfrag - frag_now->fr_literal,
459 4,
460 &insn.exp,
461 0,
462 m88k_get_reloc_code(&insn));
463 break;
464 #endif
465
466 case RELOC_PC16:
467 #ifdef OBJ_ELF
468 fix_new_exp (frag_now,
469 thisfrag - frag_now->fr_literal ,
470 4,
471 &insn.exp,
472 1,
473 m88k_get_reloc_code(&insn));
474 #else
475 fix_new_exp (frag_now,
476 thisfrag - frag_now->fr_literal + 2,
477 2,
478 &insn.exp,
479 1,
480 m88k_get_reloc_code(&insn));
481 #endif
482 break;
483
484 case RELOC_PC26:
485 fix_new_exp (frag_now,
486 thisfrag - frag_now->fr_literal,
487 4,
488 &insn.exp,
489 1,
490 m88k_get_reloc_code(&insn));
491 break;
492
493 case RELOC_32:
494 fix_new_exp (frag_now,
495 thisfrag - frag_now->fr_literal,
496 4,
497 &insn.exp,
498 0,
499 m88k_get_reloc_code(&insn));
500 break;
501
502 default:
503 as_fatal (_("Unknown relocation type"));
504 break;
505 }
506 }
507
508 static int
calcop(format,param,insn)509 calcop (format, param, insn)
510 struct m88k_opcode *format;
511 char *param;
512 struct m88k_insn *insn;
513 {
514 char *fmt = format->op_spec;
515 int f;
516 unsigned val;
517 unsigned opcode;
518 unsigned int reg_prefix = 'r';
519
520 insn->opcode = format->opcode;
521 opcode = 0;
522
523 /*
524 * Instructions which have no arguments (such as rte) will get
525 * correctly reported only if param == "", although there could be
526 * whitespace following the instruction.
527 * Rather than eating whitespace here, let's assume everything is
528 * fine. If there were non-wanted arguments, they will be parsed as
529 * an incorrect opcode at the offending line, so that's not too bad.
530 * -- miod
531 */
532 if (*fmt == '\0')
533 return 1;
534
535 for (;;)
536 {
537 if (param == NULL)
538 return 0;
539
540 f = *fmt++;
541 switch (f)
542 {
543 case 0:
544 insn->opcode |= opcode;
545 return (*param == 0 || *param == '\n');
546
547 default:
548 if (f != *param++)
549 return 0;
550 break;
551
552 case 'd':
553 param = get_reg (param, &val, reg_prefix);
554 reg_prefix = 'r';
555 opcode |= val << 21;
556 break;
557
558 case 'o':
559 param = get_o6 (param, &val);
560 opcode |= ((val >> 2) << 7);
561 break;
562
563 case 'x':
564 reg_prefix = 'x';
565 break;
566
567 case '1':
568 param = get_reg (param, &val, reg_prefix);
569 reg_prefix = 'r';
570 opcode |= val << 16;
571 break;
572
573 case '2':
574 param = get_reg (param, &val, reg_prefix);
575 reg_prefix = 'r';
576 opcode |= val;
577 break;
578
579 case '3':
580 param = get_reg (param, &val, 'r');
581 opcode |= (val << 16) | val;
582 break;
583
584 case 'I':
585 param = get_imm16 (param, insn);
586 break;
587
588 case 'b':
589 param = get_bf (param, &val);
590 opcode |= val;
591 break;
592
593 case 'p':
594 param = get_pcr (param, insn, RELOC_PC16);
595 break;
596
597 case 'P':
598 param = get_pcr (param, insn, RELOC_PC26);
599 break;
600
601 case 'B':
602 param = get_cmp (param, &val);
603 opcode |= val;
604 break;
605
606 case 'M':
607 param = get_cnd (param, &val);
608 opcode |= val;
609 break;
610
611 case 'c':
612 param = get_cr (param, &val);
613 opcode |= val << 5;
614 break;
615
616 case 'f':
617 param = get_fcr (param, &val);
618 opcode |= val << 5;
619 break;
620
621 case 'V':
622 param = get_vec9 (param, &val);
623 opcode |= val;
624 break;
625
626 case '?':
627 /* Having this here repeats the warning sometimes.
628 But can't we stand that? */
629 as_warn (_("Use of obsolete instruction"));
630 break;
631 }
632 }
633 }
634
635 static char *
match_name(param,assoc_tab,valp)636 match_name (param, assoc_tab, valp)
637 char *param;
638 struct field_val_assoc *assoc_tab;
639 unsigned *valp;
640 {
641 int i;
642 char *name;
643 int name_len;
644
645 for (i = 0;; i++)
646 {
647 name = assoc_tab[i].name;
648 if (name == NULL)
649 return NULL;
650 name_len = strlen (name);
651 if (!strncmp (param, name, name_len))
652 {
653 *valp = assoc_tab[i].val;
654 return param + name_len;
655 }
656 }
657 }
658
659 static char *
get_reg(param,regnop,reg_prefix)660 get_reg (param, regnop, reg_prefix)
661 char *param;
662 unsigned *regnop;
663 unsigned int reg_prefix;
664 {
665 unsigned c;
666 unsigned regno;
667
668 #ifdef REGISTER_PREFIX
669 c = *param++;
670 if (c != REGISTER_PREFIX)
671 return NULL;
672 #endif
673
674 c = *param++;
675 if (c == reg_prefix)
676 {
677 regno = *param++ - '0';
678 if (regno < 10)
679 {
680 if (regno == 0)
681 {
682 *regnop = 0;
683 return param;
684 }
685 c = *param - '0';
686 if (c < 10)
687 {
688 regno = regno * 10 + c;
689 if (c < 32)
690 {
691 *regnop = regno;
692 return param + 1;
693 }
694 }
695 else
696 {
697 *regnop = regno;
698 return param;
699 }
700 }
701 return NULL;
702 }
703 else if (c == 's' && param[0] == 'p')
704 {
705 *regnop = 31;
706 return param + 1;
707 }
708
709 return NULL;
710 }
711
712 static char *
get_imm16(param,insn)713 get_imm16 (param, insn)
714 char *param;
715 struct m88k_insn *insn;
716 {
717 enum m88k_reloc_type reloc = NO_RELOC;
718 unsigned int val;
719 char *save_ptr;
720 #ifdef REGISTER_PREFIX
721 int found_prefix = 0;
722 #endif
723
724 #ifdef REGISTER_PREFIX
725 if (*param == REGISTER_PREFIX)
726 {
727 param++;
728 found_prefix = 1;
729 }
730 #endif
731
732 if (!strncmp (param, "hi16", 4) && !ISALNUM (param[4]))
733 {
734 reloc = RELOC_HI16;
735 param += 4;
736 }
737 else if (!strncmp (param, "lo16", 4) && !ISALNUM (param[4]))
738 {
739 reloc = RELOC_LO16;
740 param += 4;
741 }
742 #ifdef M88KCOFF
743 else if (!strncmp (param, "iw16", 4) && !ISALNUM (param[4]))
744 {
745 reloc = RELOC_IW16;
746 param += 4;
747 }
748 #endif
749
750 #ifdef REGISTER_PREFIX
751 if (found_prefix && reloc == NO_RELOC)
752 return NULL;
753 #endif
754
755 save_ptr = input_line_pointer;
756 input_line_pointer = param;
757 expression (&insn->exp);
758 param = input_line_pointer;
759 input_line_pointer = save_ptr;
760
761 val = insn->exp.X_add_number;
762
763 if (insn->exp.X_op == O_constant)
764 {
765 /* Insert the value now, and reset reloc to NO_RELOC. */
766 if (reloc == NO_RELOC)
767 {
768 /* Warn about too big expressions if not surrounded by xx16. */
769 if (val > 0xffff)
770 as_warn (_("Expression truncated to 16 bits"));
771 }
772
773 if (reloc == RELOC_HI16)
774 val >>= 16;
775
776 insn->opcode |= val & 0xffff;
777 reloc = NO_RELOC;
778 }
779 else if (reloc == NO_RELOC)
780 /* We accept a symbol even without lo16, hi16, etc, and assume
781 lo16 was intended. */
782 reloc = RELOC_LO16;
783
784 insn->reloc = reloc;
785
786 return param;
787 }
788
789 static char *
get_pcr(param,insn,reloc)790 get_pcr (param, insn, reloc)
791 char *param;
792 struct m88k_insn *insn;
793 enum m88k_reloc_type reloc;
794 {
795 char *saveptr, *saveparam;
796
797 saveptr = input_line_pointer;
798 input_line_pointer = param;
799
800 expression (&insn->exp);
801
802 saveparam = input_line_pointer;
803 input_line_pointer = saveptr;
804
805 /* Botch: We should relocate now if O_constant. */
806 insn->reloc = reloc;
807
808 return saveparam;
809 }
810
811 static char *
get_cmp(param,valp)812 get_cmp (param, valp)
813 char *param;
814 unsigned *valp;
815 {
816 unsigned int val;
817 char *save_ptr;
818
819 save_ptr = param;
820
821 #ifdef REGISTER_PREFIX
822 /* SVR4 compiler prefixes condition codes with the register prefix */
823 if (*param == REGISTER_PREFIX)
824 param++;
825 #endif
826 param = match_name (param, cmpslot, valp);
827 val = *valp;
828
829 if (param == NULL)
830 {
831 param = save_ptr;
832
833 save_ptr = input_line_pointer;
834 input_line_pointer = param;
835 val = get_absolute_expression ();
836 param = input_line_pointer;
837 input_line_pointer = save_ptr;
838
839 if (val >= 32)
840 {
841 as_warn (_("Expression truncated to 5 bits"));
842 val %= 32;
843 }
844 }
845
846 *valp = val << 21;
847 return param;
848 }
849
850 static char *
get_cnd(param,valp)851 get_cnd (param, valp)
852 char *param;
853 unsigned *valp;
854 {
855 unsigned int val;
856
857 if (ISDIGIT (*param))
858 {
859 param = getval (param, &val);
860
861 if (val >= 32)
862 {
863 as_warn (_("Expression truncated to 5 bits"));
864 val %= 32;
865 }
866 }
867 else
868 {
869 #ifdef REGISTER_PREFIX
870 /* SVR4 compiler prefixes condition codes with the register prefix */
871 if (*param == REGISTER_PREFIX)
872 param++;
873 #endif
874
875 param[0] = TOLOWER (param[0]);
876 param[1] = TOLOWER (param[1]);
877
878 param = match_name (param, cndmsk, valp);
879
880 if (param == NULL)
881 return NULL;
882
883 val = *valp;
884 }
885
886 *valp = val << 21;
887 return param;
888 }
889
890 static char *
get_bf2(param,bc)891 get_bf2 (param, bc)
892 char *param;
893 int bc;
894 {
895 int depth = 0;
896 int c;
897
898 for (;;)
899 {
900 c = *param;
901 if (c == 0)
902 return param;
903 else if (c == '(')
904 depth++;
905 else if (c == ')')
906 depth--;
907 else if (c == bc && depth <= 0)
908 return param;
909 param++;
910 }
911 }
912
913 static char *
get_bf_offset_expression(param,offsetp)914 get_bf_offset_expression (param, offsetp)
915 char *param;
916 unsigned *offsetp;
917 {
918 unsigned offset;
919
920 #ifdef REGISTER_PREFIX
921 /* SVR4 compiler prefixes condition codes with the register prefix */
922 if (*param == REGISTER_PREFIX && ISALPHA (param[1]))
923 param++;
924 #endif
925
926 if (ISALPHA (param[0]))
927 {
928 param[0] = TOLOWER (param[0]);
929 param[1] = TOLOWER (param[1]);
930
931 param = match_name (param, cmpslot, offsetp);
932
933 return param;
934 }
935 else
936 {
937 input_line_pointer = param;
938 offset = get_absolute_expression ();
939 param = input_line_pointer;
940 }
941
942 *offsetp = offset;
943 return param;
944 }
945
946 static char *
get_bf(param,valp)947 get_bf (param, valp)
948 char *param;
949 unsigned *valp;
950 {
951 unsigned offset = 0;
952 unsigned width = 0;
953 char *xp;
954 char *save_ptr;
955
956 xp = get_bf2 (param, '<');
957
958 save_ptr = input_line_pointer;
959 input_line_pointer = param;
960 if (*xp == 0)
961 {
962 /* We did not find '<'. We have an offset (width implicitly 32). */
963 param = get_bf_offset_expression (param, &offset);
964 input_line_pointer = save_ptr;
965 if (param == NULL)
966 return NULL;
967 }
968 else
969 {
970 *xp++ = 0; /* Overwrite the '<' */
971 param = get_bf2 (xp, '>');
972 if (*param == 0)
973 return NULL;
974 *param++ = 0; /* Overwrite the '>' */
975
976 width = get_absolute_expression ();
977 xp = get_bf_offset_expression (xp, &offset);
978 input_line_pointer = save_ptr;
979
980 if (xp + 1 != param)
981 return NULL;
982 }
983
984 *valp = ((width % 32) << 5) | (offset % 32);
985
986 return param;
987 }
988
989 static char *
get_cr(param,regnop)990 get_cr (param, regnop)
991 char *param;
992 unsigned *regnop;
993 {
994 unsigned regno;
995 unsigned c;
996
997 #ifdef REGISTER_PREFIX
998 if (*param++ != REGISTER_PREFIX)
999 return NULL;
1000 #endif
1001
1002 if (!strncmp (param, "cr", 2))
1003 {
1004 param += 2;
1005
1006 regno = *param++ - '0';
1007 if (regno < 10)
1008 {
1009 if (regno == 0)
1010 {
1011 *regnop = 0;
1012 return param;
1013 }
1014 c = *param - '0';
1015 if (c < 10)
1016 {
1017 regno = regno * 10 + c;
1018 if (c < 64)
1019 {
1020 *regnop = regno;
1021 return param + 1;
1022 }
1023 }
1024 else
1025 {
1026 *regnop = regno;
1027 return param;
1028 }
1029 }
1030 return NULL;
1031 }
1032
1033 param = match_name (param,
1034 current_cpu == 88110 ? m88110_cr_regs : m88100_cr_regs,
1035 regnop);
1036
1037 return param;
1038 }
1039
1040 static char *
get_fcr(param,regnop)1041 get_fcr (param, regnop)
1042 char *param;
1043 unsigned *regnop;
1044 {
1045 unsigned regno;
1046 unsigned c;
1047
1048 #ifdef REGISTER_PREFIX
1049 if (*param++ != REGISTER_PREFIX)
1050 return NULL;
1051 #endif
1052
1053 if (!strncmp (param, "fcr", 3))
1054 {
1055 param += 3;
1056
1057 regno = *param++ - '0';
1058 if (regno < 10)
1059 {
1060 if (regno == 0)
1061 {
1062 *regnop = 0;
1063 return param;
1064 }
1065 c = *param - '0';
1066 if (c < 10)
1067 {
1068 regno = regno * 10 + c;
1069 if (c < 64)
1070 {
1071 *regnop = regno;
1072 return param + 1;
1073 }
1074 }
1075 else
1076 {
1077 *regnop = regno;
1078 return param;
1079 }
1080 }
1081 return NULL;
1082 }
1083
1084 param = match_name (param, fcr_regs, regnop);
1085
1086 return param;
1087 }
1088
1089 static char *
get_vec9(param,valp)1090 get_vec9 (param, valp)
1091 char *param;
1092 unsigned *valp;
1093 {
1094 unsigned val;
1095 char *save_ptr;
1096
1097 save_ptr = input_line_pointer;
1098 input_line_pointer = param;
1099 val = get_absolute_expression ();
1100 param = input_line_pointer;
1101 input_line_pointer = save_ptr;
1102
1103 if (val >= 1 << 9)
1104 as_warn (_("Expression truncated to 9 bits"));
1105
1106 *valp = val % (1 << 9);
1107
1108 return param;
1109 }
1110
1111 static char *
get_o6(param,valp)1112 get_o6 (param, valp)
1113 char *param;
1114 unsigned *valp;
1115 {
1116 unsigned val;
1117 char *save_ptr;
1118
1119 save_ptr = input_line_pointer;
1120 input_line_pointer = param;
1121 val = get_absolute_expression ();
1122 param = input_line_pointer;
1123 input_line_pointer = save_ptr;
1124
1125 if (val & 0x3)
1126 as_warn (_("Removed lower 2 bits of expression"));
1127
1128 *valp = val;
1129
1130 return (param);
1131 }
1132
1133 #define hexval(z) \
1134 (ISDIGIT (z) ? (z) - '0' : \
1135 ISLOWER (z) ? (z) - 'a' + 10 : \
1136 ISUPPER (z) ? (z) - 'A' + 10 : (unsigned) -1)
1137
1138 static char *
getval(param,valp)1139 getval (param, valp)
1140 char *param;
1141 unsigned int *valp;
1142 {
1143 unsigned int val = 0;
1144 unsigned int c;
1145
1146 c = *param++;
1147 if (c == '0')
1148 {
1149 c = *param++;
1150 if (c == 'x' || c == 'X')
1151 {
1152 c = *param++;
1153 c = hexval (c);
1154 while (c < 16)
1155 {
1156 val = val * 16 + c;
1157 c = *param++;
1158 c = hexval (c);
1159 }
1160 }
1161 else
1162 {
1163 c -= '0';
1164 while (c < 8)
1165 {
1166 val = val * 8 + c;
1167 c = *param++ - '0';
1168 }
1169 }
1170 }
1171 else
1172 {
1173 c -= '0';
1174 while (c < 10)
1175 {
1176 val = val * 10 + c;
1177 c = *param++ - '0';
1178 }
1179 }
1180
1181 *valp = val;
1182 return param - 1;
1183 }
1184
1185 void
md_number_to_chars(buf,val,nbytes)1186 md_number_to_chars (buf, val, nbytes)
1187 char *buf;
1188 valueT val;
1189 int nbytes;
1190 {
1191 number_to_chars_bigendian (buf, val, nbytes);
1192 }
1193
1194 #define MAX_LITTLENUMS 6
1195
1196 /* Turn a string in input_line_pointer into a floating point constant of type
1197 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
1198 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
1199 */
1200 char *
md_atof(type,litP,sizeP)1201 md_atof (type, litP, sizeP)
1202 char type;
1203 char *litP;
1204 int *sizeP;
1205 {
1206 int prec;
1207 LITTLENUM_TYPE words[MAX_LITTLENUMS];
1208 LITTLENUM_TYPE *wordP;
1209 char *t;
1210
1211 switch (type)
1212 {
1213 case 'f':
1214 case 'F':
1215 case 's':
1216 case 'S':
1217 prec = 2;
1218 break;
1219
1220 case 'd':
1221 case 'D':
1222 case 'r':
1223 case 'R':
1224 prec = 4;
1225 break;
1226
1227 case 'x':
1228 case 'X':
1229 prec = 6;
1230 break;
1231
1232 case 'p':
1233 case 'P':
1234 prec = 6;
1235 break;
1236
1237 default:
1238 *sizeP = 0;
1239 return _("Bad call to MD_ATOF()");
1240 }
1241 t = atof_ieee (input_line_pointer, type, words);
1242 if (t)
1243 input_line_pointer = t;
1244
1245 *sizeP = prec * sizeof (LITTLENUM_TYPE);
1246 for (wordP = words; prec--;)
1247 {
1248 md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
1249 litP += sizeof (LITTLENUM_TYPE);
1250 }
1251 return 0;
1252 }
1253
1254 int md_short_jump_size = 4;
1255 int md_long_jump_size = 4;
1256
1257 void
md_create_short_jump(ptr,from_addr,to_addr,frag,to_symbol)1258 md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
1259 char *ptr;
1260 addressT from_addr ATTRIBUTE_UNUSED;
1261 addressT to_addr ATTRIBUTE_UNUSED;
1262 fragS *frag;
1263 symbolS *to_symbol;
1264 {
1265 /* Since all instructions have the same width, it does not make sense to
1266 try and abuse a conditional instruction to get a short displacement
1267 (such as bb1 0, %r0, address). */
1268 md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol);
1269 }
1270
1271 void
md_create_long_jump(ptr,from_addr,to_addr,frag,to_symbol)1272 md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
1273 char *ptr;
1274 addressT from_addr ATTRIBUTE_UNUSED;
1275 addressT to_addr ATTRIBUTE_UNUSED;
1276 fragS *frag;
1277 symbolS *to_symbol;
1278 {
1279 ptr[0] = (char) 0xc0; /* br to_addr */
1280 ptr[1] = 0x00;
1281 ptr[2] = 0x00;
1282 ptr[3] = 0x00;
1283 fix_new (frag,
1284 ptr - frag->fr_literal,
1285 4,
1286 to_symbol,
1287 (offsetT) 0,
1288 0,
1289 RELOC_PC26);
1290 }
1291
1292 int
md_estimate_size_before_relax(fragP,segment_type)1293 md_estimate_size_before_relax (fragP, segment_type)
1294 fragS *fragP ATTRIBUTE_UNUSED;
1295 segT segment_type ATTRIBUTE_UNUSED;
1296 {
1297 as_fatal (_("Relaxation should never occur"));
1298 return (-1);
1299 }
1300
1301 #ifdef M88KCOFF
1302
1303 /* These functions are needed if we are linking with obj-coffbfd.c.
1304 That file may be replaced by a more BFD oriented version at some
1305 point. If that happens, these functions should be reexamined.
1306
1307 Ian Lance Taylor, Cygnus Support, 13 July 1993. */
1308
1309 /* Given a fixS structure (created by a call to fix_new, above),
1310 return the BFD relocation type to use for it. */
1311
1312 short
tc_coff_fix2rtype(fixp)1313 tc_coff_fix2rtype (fixp)
1314 fixS *fixp;
1315 {
1316 switch (fixp->fx_r_type)
1317 {
1318 case RELOC_LO16:
1319 return R_LVRT16;
1320 case RELOC_HI16:
1321 return R_HVRT16;
1322 case RELOC_PC16:
1323 return R_PCR16L;
1324 case RELOC_PC26:
1325 return R_PCR26L;
1326 case RELOC_32:
1327 return R_VRT32;
1328 case RELOC_IW16:
1329 return R_VRT16;
1330 default:
1331 abort ();
1332 }
1333 }
1334
1335 /* Apply a fixS to the object file. Since COFF does not use addends
1336 in relocs, the addend is actually stored directly in the object
1337 file itself. */
1338
1339 void
md_apply_fix3(fixP,valP,seg)1340 md_apply_fix3 (fixP, valP, seg)
1341 fixS *fixP;
1342 valueT * valP;
1343 segT seg ATTRIBUTE_UNUSED;
1344 {
1345 long val = * (long *) valP;
1346 char *buf;
1347
1348 buf = fixP->fx_frag->fr_literal + fixP->fx_where;
1349 fixP->fx_addnumber = val;
1350 fixP->fx_offset = 0;
1351
1352 switch (fixP->fx_r_type)
1353 {
1354 case RELOC_IW16:
1355 fixP->fx_offset = val >> 16;
1356 buf[2] = val >> 8;
1357 buf[3] = val;
1358 break;
1359
1360 case RELOC_LO16:
1361 fixP->fx_offset = val >> 16;
1362 buf[0] = val >> 8;
1363 buf[1] = val;
1364 break;
1365
1366 case RELOC_HI16:
1367 buf[0] = val >> 24;
1368 buf[1] = val >> 16;
1369 break;
1370
1371 case RELOC_PC16:
1372 buf[0] = val >> 10;
1373 buf[1] = val >> 2;
1374 break;
1375
1376 case RELOC_PC26:
1377 buf[0] |= (val >> 26) & 0x03;
1378 buf[1] = val >> 18;
1379 buf[2] = val >> 10;
1380 buf[3] = val >> 2;
1381 break;
1382
1383 case RELOC_32:
1384 buf[0] = val >> 24;
1385 buf[1] = val >> 16;
1386 buf[2] = val >> 8;
1387 buf[3] = val;
1388 break;
1389
1390 default:
1391 abort ();
1392 }
1393
1394 if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
1395 fixP->fx_done = 1;
1396 }
1397
1398 #endif /* M88KCOFF */
1399
1400 /* Fill in rs_align_code fragments. */
1401
1402 void
m88k_handle_align(fragp)1403 m88k_handle_align (fragp)
1404 fragS *fragp;
1405 {
1406 static const unsigned char nop_pattern[] = { 0xf4, 0x00, 0x58, 0x00 };
1407
1408 int bytes;
1409 char *p;
1410
1411 if (fragp->fr_type != rs_align_code)
1412 return;
1413
1414 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
1415 p = fragp->fr_literal + fragp->fr_fix;
1416
1417 if (bytes & 3)
1418 {
1419 int fix = bytes & 3;
1420 memset (p, 0, fix);
1421 p += fix;
1422 bytes -= fix;
1423 fragp->fr_fix += fix;
1424 }
1425
1426 memcpy (p, nop_pattern, 4);
1427 fragp->fr_var = 4;
1428 }
1429
1430 /* Where a PC relative offset is calculated from. On the m88k they
1431 are calculated from just after the instruction. */
1432
1433 long
md_pcrel_from(fixp)1434 md_pcrel_from (fixp)
1435 fixS *fixp;
1436 {
1437 switch (fixp->fx_r_type)
1438 {
1439 case RELOC_PC16:
1440 #ifdef OBJ_ELF
1441 /* FALLTHROUGH */
1442 #else
1443 return fixp->fx_frag->fr_address + fixp->fx_where - 2;
1444 #endif
1445 case RELOC_PC26:
1446 #ifdef OBJ_ELF
1447 case BFD_RELOC_32_PLT_PCREL:
1448 #endif
1449 return fixp->fx_frag->fr_address + fixp->fx_where;
1450 default:
1451 abort ();
1452 }
1453 /*NOTREACHED*/
1454 }
1455
1456 #ifdef OBJ_ELF
1457
1458 valueT
md_section_align(segment,size)1459 md_section_align (segment, size)
1460 segT segment ATTRIBUTE_UNUSED;
1461 valueT size;
1462 {
1463 return size;
1464 }
1465
1466 /* Generate the BFD reloc to be stuck in the object file from the
1467 fixup used internally in the assembler. */
1468
1469 arelent *
tc_gen_reloc(sec,fixp)1470 tc_gen_reloc (sec, fixp)
1471 asection *sec ATTRIBUTE_UNUSED;
1472 fixS *fixp;
1473 {
1474 arelent *reloc;
1475 bfd_reloc_code_real_type code;
1476
1477 reloc = (arelent *) xmalloc (sizeof (arelent));
1478 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
1479 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
1480 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
1481
1482 /* Make sure none of our internal relocations make it this far.
1483 They'd better have been fully resolved by this point. */
1484 assert ((int) fixp->fx_r_type > 0);
1485
1486 code = fixp->fx_r_type;
1487 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
1488 if (reloc->howto == NULL)
1489 {
1490 as_bad_where (fixp->fx_file, fixp->fx_line,
1491 _("cannot represent `%s' relocation in object file"),
1492 bfd_get_reloc_code_name (code));
1493 return NULL;
1494 }
1495
1496 if (!fixp->fx_pcrel != !reloc->howto->pc_relative)
1497 {
1498 as_fatal (_("internal error? cannot generate `%s' relocation"),
1499 bfd_get_reloc_code_name (code));
1500 }
1501 assert (!fixp->fx_pcrel == !reloc->howto->pc_relative);
1502
1503 reloc->addend = fixp->fx_offset;
1504
1505 return reloc;
1506 }
1507
1508 /* Apply a fixS to the object file. This is called for all the
1509 fixups we generated by the call to fix_new_exp, above. In the call
1510 above we used a reloc code which was the largest legal reloc code
1511 plus the operand index. Here we undo that to recover the operand
1512 index. At this point all symbol values should be fully resolved,
1513 and we attempt to completely resolve the reloc. If we can not do
1514 that, we determine the correct reloc code and put it back in the
1515 fixup.
1516
1517 This is the ELF version.
1518 */
1519
1520 void
md_apply_fix3(fixP,valP,seg)1521 md_apply_fix3 (fixP, valP, seg)
1522 fixS *fixP;
1523 valueT * valP;
1524 segT seg ATTRIBUTE_UNUSED;
1525 {
1526 valueT val = * (valueT *) valP;
1527 char *buf;
1528 long insn;
1529
1530 buf = fixP->fx_frag->fr_literal + fixP->fx_where;
1531
1532 if (fixP->fx_subsy != NULL)
1533 as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
1534
1535 if (fixP->fx_addsy)
1536 {
1537 #if 0
1538 /* can't empty 26-bit relocation values with memset() */
1539 if (fixP->fx_r_type == BFD_RELOC_28_PCREL_S2)
1540 {
1541 insn = bfd_getb32 ((unsigned char *) buf);
1542 insn &= ~0x03ffffff;
1543 bfd_putb32(insn, buf);
1544 }
1545 else
1546 memset(buf, 0, fixP->fx_size);
1547 #endif
1548
1549 if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
1550 && !S_IS_DEFINED (fixP->fx_addsy)
1551 && !S_IS_WEAK (fixP->fx_addsy))
1552 S_SET_WEAK (fixP->fx_addsy);
1553
1554 return;
1555 }
1556
1557 switch (fixP->fx_r_type)
1558 {
1559 case BFD_RELOC_VTABLE_INHERIT:
1560 case BFD_RELOC_VTABLE_ENTRY:
1561 return;
1562
1563 case BFD_RELOC_HI16_BASEREL:
1564 case BFD_RELOC_LO16_BASEREL:
1565 case BFD_RELOC_HI16_GOTOFF:
1566 case BFD_RELOC_LO16_GOTOFF:
1567 case BFD_RELOC_32_PLTOFF:
1568 return;
1569
1570 case BFD_RELOC_LO16:
1571 case BFD_RELOC_HI16:
1572 if (fixP->fx_pcrel)
1573 abort ();
1574 buf[0] = val >> 8;
1575 buf[1] = val;
1576 break;
1577
1578 case BFD_RELOC_18_PCREL_S2:
1579 if ((val & 0x03) != 0)
1580 as_bad_where (fixP->fx_file, fixP->fx_line,
1581 "Branch to unaligned address (%lx)", (long)val);
1582 buf[2] = val >> 10;
1583 buf[3] = val >> 2;
1584 break;
1585
1586 case BFD_RELOC_32_PLT_PCREL:
1587 case BFD_RELOC_28_PCREL_S2:
1588 if ((val & 0x03) != 0)
1589 as_bad_where (fixP->fx_file, fixP->fx_line,
1590 "Branch to unaligned address (%lx)", (long)val);
1591 buf[0] |= (val >> 26) & 0x03;
1592 buf[1] = val >> 18;
1593 buf[2] = val >> 10;
1594 buf[3] = val >> 2;
1595 break;
1596
1597 case BFD_RELOC_32:
1598 insn = val;
1599 bfd_putb32(insn, buf);
1600 break;
1601
1602 default:
1603 abort ();
1604 }
1605
1606 if (/* fixP->fx_addsy == NULL && */ fixP->fx_pcrel == 0)
1607 fixP->fx_done = 1;
1608 }
1609
1610 /* Set the ELF specific flags. */
1611 void
m88k_elf_final_processing()1612 m88k_elf_final_processing ()
1613 {
1614 if (current_cpu == 88110)
1615 elf_elfheader (stdoutput)->e_flags |= EF_M88110;
1616 }
1617
1618 inline static char *
m88k_end_of_name(const char * suffix,const char * pattern,size_t patlen)1619 m88k_end_of_name (const char *suffix, const char *pattern, size_t patlen)
1620 {
1621 if (strncmp (suffix, pattern, patlen) == 0
1622 && ! is_part_of_name (suffix[patlen]))
1623 return suffix + patlen;
1624
1625 return NULL;
1626 }
1627
1628 int
m88k_parse_name(name,expressionP,nextcharP)1629 m88k_parse_name (name, expressionP, nextcharP)
1630 const char *name;
1631 expressionS *expressionP;
1632 char *nextcharP;
1633 {
1634 char *next = input_line_pointer;
1635 char *next_end;
1636 enum m88k_pic_reloc_type reloc_type = pic_reloc_none;
1637 symbolS *symbolP;
1638 segT segment;
1639
1640 if (*nextcharP != '#')
1641 return 0;
1642
1643 if ((next_end = m88k_end_of_name (next + 1, "abdiff", 6)) != NULL)
1644 {
1645 reloc_type = pic_reloc_abdiff;
1646 }
1647 else if ((next_end = m88k_end_of_name (next + 1, "got_rel", 7)) != NULL)
1648 {
1649 reloc_type = pic_reloc_gotrel;
1650 }
1651 else if ((next_end = m88k_end_of_name (next + 1, "plt", 3)) != NULL)
1652 {
1653 reloc_type = pic_reloc_plt;
1654 }
1655 else
1656 return 0;
1657
1658 symbolP = symbol_find_or_make (name);
1659 segment = S_GET_SEGMENT (symbolP);
1660 if (segment == absolute_section)
1661 {
1662 expressionP->X_op = O_constant;
1663 expressionP->X_add_number = S_GET_VALUE (symbolP);
1664 }
1665 else if (segment == reg_section)
1666 {
1667 expressionP->X_op = O_register;
1668 expressionP->X_add_number = S_GET_VALUE (symbolP);
1669 }
1670 else
1671 {
1672 expressionP->X_op = O_symbol;
1673 expressionP->X_add_symbol = symbolP;
1674 expressionP->X_add_number = 0;
1675 }
1676 expressionP->X_md = reloc_type;
1677
1678 *input_line_pointer = *nextcharP;
1679 input_line_pointer = next_end;
1680 *nextcharP = *input_line_pointer;
1681 *input_line_pointer = '\0';
1682
1683 return 1;
1684 }
1685
1686 int
m88k_fix_adjustable(fix)1687 m88k_fix_adjustable (fix)
1688 fixS *fix;
1689 {
1690 return (fix->fx_r_type != BFD_RELOC_LO16_GOTOFF
1691 && fix->fx_r_type != BFD_RELOC_HI16_GOTOFF
1692 && fix->fx_r_type != BFD_RELOC_VTABLE_INHERIT
1693 && fix->fx_r_type != BFD_RELOC_VTABLE_ENTRY
1694 && (fix->fx_pcrel
1695 || (fix->fx_subsy != NULL
1696 && (S_GET_SEGMENT (fix->fx_subsy)
1697 == S_GET_SEGMENT (fix->fx_addsy)))
1698 || S_IS_LOCAL (fix->fx_addsy)));
1699 }
1700 #endif /* OBJ_ELF */
1701
1702 #ifdef OBJ_AOUT
1703
1704 /* Round up a section size to the appropriate boundary. */
1705 valueT
md_section_align(segment,size)1706 md_section_align (segment, size)
1707 segT segment ATTRIBUTE_UNUSED;
1708 valueT size;
1709 {
1710 #ifdef BFD_ASSEMBLER
1711 /* For a.out, force the section size to be aligned. If we don't do
1712 this, BFD will align it for us, but it will not write out the
1713 final bytes of the section. This may be a bug in BFD, but it is
1714 easier to fix it here since that is how the other a.out targets
1715 work. */
1716 int align;
1717
1718 align = bfd_get_section_alignment (stdoutput, segment);
1719 valueT mask = ((valueT) 1 << align) - 1;
1720
1721 return (size + mask) & ~mask;
1722 #else
1723 return (size + 7) & ~7;
1724 #endif
1725 }
1726
1727 const int md_reloc_size = 12; /* sizeof(struct relocation_info); */
1728
1729 void
tc_aout_fix_to_chars(where,fixP,segment_address_in_file)1730 tc_aout_fix_to_chars (where, fixP, segment_address_in_file)
1731 char *where;
1732 fixS *fixP;
1733 relax_addressT segment_address_in_file;
1734 {
1735 long r_symbolnum;
1736 long r_addend = 0;
1737 long r_address;
1738
1739 know (fixP->fx_addsy != NULL);
1740
1741 r_address = fixP->fx_frag->fr_address + fixP->fx_where
1742 - segment_address_in_file;
1743 md_number_to_chars (where, r_address, 4);
1744
1745 r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy)
1746 ? S_GET_TYPE (fixP->fx_addsy)
1747 : fixP->fx_addsy->sy_number);
1748
1749 where[4] = (r_symbolnum >> 16) & 0x0ff;
1750 where[5] = (r_symbolnum >> 8) & 0x0ff;
1751 where[6] = r_symbolnum & 0x0ff;
1752 where[7] = ((((!S_IS_DEFINED (fixP->fx_addsy)) << 7) & 0x80) | (0 & 0x70) |
1753 (fixP->fx_r_type & 0xf));
1754
1755 if (fixP->fx_addsy->sy_frag) {
1756 r_addend = fixP->fx_addsy->sy_frag->fr_address;
1757 }
1758
1759 if (fixP->fx_pcrel) {
1760 r_addend -= r_address;
1761 } else {
1762 r_addend = fixP->fx_addnumber;
1763 }
1764
1765 md_number_to_chars(&where[8], r_addend, 4);
1766 }
1767
1768 void
tc_headers_hook(headers)1769 tc_headers_hook(headers)
1770 object_headers *headers;
1771 {
1772 #if defined(TE_NetBSD) || defined(TE_OpenBSD)
1773 N_SET_INFO(headers->header, OMAGIC, M_88K_OPENBSD, 0);
1774 headers->header.a_info = htonl(headers->header.a_info);
1775 #endif
1776 }
1777
1778 #endif /* OBJ_AOUT */
1779