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