xref: /openbsd-src/gnu/usr.bin/binutils/gas/config/tc-m88k.c (revision 43171b1454a64b6bafb8c3f8219aced797e12ee5)
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