Convert unmaintained files over to ISO-C90 and fix formatting.
[platform/upstream/binutils.git] / gas / config / tc-m88k.c
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, 2003, 2005
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 struct field_val_assoc
31 {
32   char *name;
33   unsigned val;
34 };
35
36 struct field_val_assoc cr_regs[] =
37 {
38   {"PID", 0},
39   {"PSR", 1},
40   {"EPSR", 2},
41   {"SSBR", 3},
42   {"SXIP", 4},
43   {"SNIP", 5},
44   {"SFIP", 6},
45   {"VBR", 7},
46   {"DMT0", 8},
47   {"DMD0", 9},
48   {"DMA0", 10},
49   {"DMT1", 11},
50   {"DMD1", 12},
51   {"DMA1", 13},
52   {"DMT2", 14},
53   {"DMD2", 15},
54   {"DMA2", 16},
55   {"SR0", 17},
56   {"SR1", 18},
57   {"SR2", 19},
58   {"SR3", 20},
59
60   {NULL, 0},
61 };
62
63 struct field_val_assoc fcr_regs[] =
64 {
65   {"FPECR", 0},
66   {"FPHS1", 1},
67   {"FPLS1", 2},
68   {"FPHS2", 3},
69   {"FPLS2", 4},
70   {"FPPT", 5},
71   {"FPRH", 6},
72   {"FPRL", 7},
73   {"FPIT", 8},
74
75   {"FPSR", 62},
76   {"FPCR", 63},
77
78   {NULL, 0},
79 };
80
81 struct field_val_assoc cmpslot[] =
82 {
83 /* Integer      Floating point.  */
84   {"nc", 0},
85   {"cp", 1},
86   {"eq", 2},
87   {"ne", 3},
88   {"gt", 4},
89   {"le", 5},
90   {"lt", 6},
91   {"ge", 7},
92   {"hi", 8},    {"ou", 8},
93   {"ls", 9},    {"ib", 9},
94   {"lo", 10},   {"in", 10},
95   {"hs", 11},   {"ob", 11},
96   {"be", 12},   {"ue", 12},
97   {"nb", 13},   {"lg", 13},
98   {"he", 14},   {"ug", 14},
99   {"nh", 15},   {"ule", 15},
100                 {"ul", 16},
101                 {"uge", 17},
102
103   {NULL, 0},
104 };
105
106 struct field_val_assoc cndmsk[] =
107 {
108   {"gt0", 1},
109   {"eq0", 2},
110   {"ge0", 3},
111   {"lt0", 12},
112   {"ne0", 13},
113   {"le0", 14},
114
115   {NULL, 0},
116 };
117
118 struct m88k_insn
119 {
120   unsigned long opcode;
121   expressionS exp;
122   enum reloc_type reloc;
123 };
124
125 extern char *myname;
126 static struct hash_control *op_hash = NULL;
127
128 /* These bits should be turned off in the first address of every segment.  */
129 int md_seg_align = 7;
130
131 /* These chars start a comment anywhere in a source file (except inside
132    another comment.  */
133 const char comment_chars[] = ";";
134
135 /* These chars only start a comment at the beginning of a line.  */
136 const char line_comment_chars[] = "#";
137
138 const char line_separator_chars[] = "";
139
140 /* Chars that can be used to separate mant from exp in floating point nums.  */
141 const char EXP_CHARS[] = "eE";
142
143 /* Chars that mean this number is a floating point constant.
144    as in 0f123.456
145    or    0H1.234E-12 (see exp chars above).  */
146 const char FLT_CHARS[] = "dDfF";
147
148 void
149 md_begin (void)
150 {
151   const char *retval = NULL;
152   unsigned int i = 0;
153
154   /* Initialize hash table.  */
155   op_hash = hash_new ();
156
157   while (*m88k_opcodes[i].name)
158     {
159       char *name = m88k_opcodes[i].name;
160
161       /* Hash each mnemonic and record its position.  */
162       retval = hash_insert (op_hash, name, &m88k_opcodes[i]);
163
164       if (retval != NULL)
165         as_fatal (_("Can't hash instruction '%s':%s"),
166                   m88k_opcodes[i].name, retval);
167
168       /* Skip to next unique mnemonic or end of list.  */
169       for (i++; !strcmp (m88k_opcodes[i].name, name); i++)
170         ;
171     }
172 }
173 \f
174 const char *md_shortopts = "";
175 struct option md_longopts[] =
176 {
177   {NULL, no_argument, NULL, 0}
178 };
179 size_t md_longopts_size = sizeof (md_longopts);
180
181 int
182 md_parse_option (int c ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED)
183 {
184   return 0;
185 }
186
187 void
188 md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
189 {
190 }
191 \f
192 static char *
193 get_o6 (char *param, unsigned *valp)
194 {
195   unsigned val;
196   char *save_ptr;
197
198   save_ptr = input_line_pointer;
199   input_line_pointer = param;
200   val = get_absolute_expression ();
201   param = input_line_pointer;
202   input_line_pointer = save_ptr;
203
204   if (val & 0x3)
205     as_warn (_("Removed lower 2 bits of expression"));
206
207   *valp = val;
208
209   return (param);
210 }
211
212 static char *
213 get_vec9 (char *param, unsigned *valp)
214 {
215   unsigned val;
216   char *save_ptr;
217
218   save_ptr = input_line_pointer;
219   input_line_pointer = param;
220   val = get_absolute_expression ();
221   param = input_line_pointer;
222   input_line_pointer = save_ptr;
223
224   if (val >= 1 << 9)
225     as_warn (_("Expression truncated to 9 bits"));
226
227   *valp = val % (1 << 9);
228
229   return param;
230 }
231
232 static char *
233 get_bf2 (char *param, int bc)
234 {
235   int depth = 0;
236   int c;
237
238   for (;;)
239     {
240       c = *param;
241       if (c == 0)
242         return param;
243       else if (c == '(')
244         depth++;
245       else if (c == ')')
246         depth--;
247       else if (c == bc && depth <= 0)
248         return param;
249       param++;
250     }
251 }
252
253 static char *
254 match_name (char *param,
255             struct field_val_assoc *assoc_tab,
256             unsigned *valp)
257 {
258   int i;
259   char *name;
260   int name_len;
261
262   for (i = 0;; i++)
263     {
264       name = assoc_tab[i].name;
265       if (name == NULL)
266         return NULL;
267       name_len = strlen (name);
268       if (!strncmp (param, name, name_len))
269         {
270           *valp = assoc_tab[i].val;
271           return param + name_len;
272         }
273     }
274 }
275
276 static char *
277 get_bf_offset_expression (char *param, unsigned *offsetp)
278 {
279   unsigned offset;
280
281   if (ISALPHA (param[0]))
282     {
283       param[0] = TOLOWER (param[0]);
284       param[1] = TOLOWER (param[1]);
285
286       param = match_name (param, cmpslot, offsetp);
287
288       return param;
289     }
290   else
291     {
292       input_line_pointer = param;
293       offset = get_absolute_expression ();
294       param = input_line_pointer;
295     }
296
297   *offsetp = offset;
298   return param;
299 }
300
301 static char *
302 get_bf (char *param, unsigned *valp)
303 {
304   unsigned offset = 0;
305   unsigned width = 0;
306   char *xp;
307   char *save_ptr;
308
309   xp = get_bf2 (param, '<');
310
311   save_ptr = input_line_pointer;
312   input_line_pointer = param;
313   if (*xp == 0)
314     {
315       /* We did not find '<'.  We have an offset (width implicitly 32).  */
316       param = get_bf_offset_expression (param, &offset);
317       input_line_pointer = save_ptr;
318       if (param == NULL)
319         return NULL;
320     }
321   else
322     {
323       *xp++ = 0;                /* Overwrite the '<'.  */
324       param = get_bf2 (xp, '>');
325       if (*param == 0)
326         return NULL;
327       *param++ = 0;             /* Overwrite the '>'.  */
328
329       width = get_absolute_expression ();
330       xp = get_bf_offset_expression (xp, &offset);
331       input_line_pointer = save_ptr;
332
333       if (xp + 1 != param)
334         return NULL;
335     }
336
337   *valp = ((width % 32) << 5) | (offset % 32);
338
339   return param;
340 }
341
342 static char *
343 get_cr (char *param, unsigned *regnop)
344 {
345   unsigned regno;
346   unsigned c;
347
348   if (!strncmp (param, "cr", 2))
349     {
350       param += 2;
351
352       regno = *param++ - '0';
353       if (regno < 10)
354         {
355           if (regno == 0)
356             {
357               *regnop = 0;
358               return param;
359             }
360           c = *param - '0';
361           if (c < 10)
362             {
363               regno = regno * 10 + c;
364               if (c < 64)
365                 {
366                   *regnop = regno;
367                   return param + 1;
368                 }
369             }
370           else
371             {
372               *regnop = regno;
373               return param;
374             }
375         }
376       return NULL;
377     }
378
379   param = match_name (param, cr_regs, regnop);
380
381   return param;
382 }
383
384 static char *
385 get_fcr (char *param, unsigned *regnop)
386 {
387   unsigned regno;
388   unsigned c;
389
390   if (!strncmp (param, "fcr", 3))
391     {
392       param += 3;
393
394       regno = *param++ - '0';
395       if (regno < 10)
396         {
397           if (regno == 0)
398             {
399               *regnop = 0;
400               return param;
401             }
402           c = *param - '0';
403           if (c < 10)
404             {
405               regno = regno * 10 + c;
406               if (c < 64)
407                 {
408                   *regnop = regno;
409                   return param + 1;
410                 }
411             }
412           else
413             {
414               *regnop = regno;
415               return param;
416             }
417         }
418       return NULL;
419     }
420
421   param = match_name (param, fcr_regs, regnop);
422
423   return param;
424 }
425
426 #define hexval(z) \
427   (ISDIGIT (z) ? (z) - '0' :                                            \
428    ISLOWER (z) ? (z) - 'a' + 10 :                                       \
429    ISUPPER (z) ? (z) - 'A' + 10 : (unsigned) -1)
430
431 static char *
432 getval (char *param, unsigned int *valp)
433 {
434   unsigned int val = 0;
435   unsigned int c;
436
437   c = *param++;
438   if (c == '0')
439     {
440       c = *param++;
441       if (c == 'x' || c == 'X')
442         {
443           c = *param++;
444           c = hexval (c);
445           while (c < 16)
446             {
447               val = val * 16 + c;
448               c = *param++;
449               c = hexval (c);
450             }
451         }
452       else
453         {
454           c -= '0';
455           while (c < 8)
456             {
457               val = val * 8 + c;
458               c = *param++ - '0';
459             }
460         }
461     }
462   else
463     {
464       c -= '0';
465       while (c < 10)
466         {
467           val = val * 10 + c;
468           c = *param++ - '0';
469         }
470     }
471
472   *valp = val;
473   return param - 1;
474 }
475
476 static char *
477 get_cnd (char *param, unsigned *valp)
478 {
479   unsigned int val;
480
481   if (ISDIGIT (*param))
482     {
483       param = getval (param, &val);
484
485       if (val >= 32)
486         {
487           as_warn (_("Expression truncated to 5 bits"));
488           val %= 32;
489         }
490     }
491   else
492     {
493       param[0] = TOLOWER (param[0]);
494       param[1] = TOLOWER (param[1]);
495
496       param = match_name (param, cndmsk, valp);
497
498       if (param == NULL)
499         return NULL;
500
501       val = *valp;
502     }
503
504   *valp = val << 21;
505   return param;
506 }
507
508 static char *
509 get_reg (char *param, unsigned *regnop, unsigned int reg_prefix)
510 {
511   unsigned c;
512   unsigned regno;
513
514   c = *param++;
515   if (c == reg_prefix)
516     {
517       regno = *param++ - '0';
518       if (regno < 10)
519         {
520           if (regno == 0)
521             {
522               *regnop = 0;
523               return param;
524             }
525           c = *param - '0';
526           if (c < 10)
527             {
528               regno = regno * 10 + c;
529               if (c < 32)
530                 {
531                   *regnop = regno;
532                   return param + 1;
533                 }
534             }
535           else
536             {
537               *regnop = regno;
538               return param;
539             }
540         }
541       return NULL;
542     }
543   else if (c == 's' && param[0] == 'p')
544     {
545       *regnop = 31;
546       return param + 1;
547     }
548
549   return 0;
550 }
551
552 static char *
553 get_imm16 (char *param, struct m88k_insn *insn)
554 {
555   enum reloc_type reloc = NO_RELOC;
556   unsigned int val;
557   char *save_ptr;
558
559   if (!strncmp (param, "hi16", 4) && !ISALNUM (param[4]))
560     {
561       reloc = RELOC_HI16;
562       param += 4;
563     }
564   else if (!strncmp (param, "lo16", 4) && !ISALNUM (param[4]))
565     {
566       reloc = RELOC_LO16;
567       param += 4;
568     }
569   else if (!strncmp (param, "iw16", 4) && !ISALNUM (param[4]))
570     {
571       reloc = RELOC_IW16;
572       param += 4;
573     }
574
575   save_ptr = input_line_pointer;
576   input_line_pointer = param;
577   expression (&insn->exp);
578   param = input_line_pointer;
579   input_line_pointer = save_ptr;
580
581   val = insn->exp.X_add_number;
582
583   if (insn->exp.X_op == O_constant)
584     {
585       /* Insert the value now, and reset reloc to NO_RELOC.  */
586       if (reloc == NO_RELOC)
587         {
588           /* Warn about too big expressions if not surrounded by xx16.  */
589           if (val > 0xffff)
590             as_warn (_("Expression truncated to 16 bits"));
591         }
592
593       if (reloc == RELOC_HI16)
594         val >>= 16;
595
596       insn->opcode |= val & 0xffff;
597       reloc = NO_RELOC;
598     }
599   else if (reloc == NO_RELOC)
600     /* We accept a symbol even without lo16, hi16, etc, and assume
601        lo16 was intended.  */
602     reloc = RELOC_LO16;
603
604   insn->reloc = reloc;
605
606   return param;
607 }
608
609 static char *
610 get_pcr (char *param, struct m88k_insn *insn, enum reloc_type reloc)
611 {
612   char *saveptr, *saveparam;
613
614   saveptr = input_line_pointer;
615   input_line_pointer = param;
616
617   expression (&insn->exp);
618
619   saveparam = input_line_pointer;
620   input_line_pointer = saveptr;
621
622   /* Botch: We should relocate now if O_constant.  */
623   insn->reloc = reloc;
624
625   return saveparam;
626 }
627
628 static char *
629 get_cmp (char *param, unsigned *valp)
630 {
631   unsigned int val;
632   char *save_ptr;
633
634   save_ptr = param;
635
636   param = match_name (param, cmpslot, valp);
637   val = *valp;
638
639   if (param == NULL)
640     {
641       param = save_ptr;
642
643       save_ptr = input_line_pointer;
644       input_line_pointer = param;
645       val = get_absolute_expression ();
646       param = input_line_pointer;
647       input_line_pointer = save_ptr;
648
649       if (val >= 32)
650         {
651           as_warn (_("Expression truncated to 5 bits"));
652           val %= 32;
653         }
654     }
655
656   *valp = val << 21;
657   return param;
658 }
659
660 static int
661 calcop (struct m88k_opcode *format,
662         char *param,
663         struct m88k_insn *insn)
664 {
665   char *fmt = format->op_spec;
666   int f;
667   unsigned val;
668   unsigned opcode;
669   unsigned int reg_prefix = 'r';
670
671   insn->opcode = format->opcode;
672   opcode = 0;
673
674   for (;;)
675     {
676       if (param == 0)
677         return 0;
678       f = *fmt++;
679       switch (f)
680         {
681         case 0:
682           insn->opcode |= opcode;
683           return (*param == 0 || *param == '\n');
684
685         default:
686           if (f != *param++)
687             return 0;
688           break;
689
690         case 'd':
691           param = get_reg (param, &val, reg_prefix);
692           reg_prefix = 'r';
693           opcode |= val << 21;
694           break;
695
696         case 'o':
697           param = get_o6 (param, &val);
698           opcode |= ((val >> 2) << 7);
699           break;
700
701         case 'x':
702           reg_prefix = 'x';
703           break;
704
705         case '1':
706           param = get_reg (param, &val, reg_prefix);
707           reg_prefix = 'r';
708           opcode |= val << 16;
709           break;
710
711         case '2':
712           param = get_reg (param, &val, reg_prefix);
713           reg_prefix = 'r';
714           opcode |= val;
715           break;
716
717         case '3':
718           param = get_reg (param, &val, 'r');
719           opcode |= (val << 16) | val;
720           break;
721
722         case 'I':
723           param = get_imm16 (param, insn);
724           break;
725
726         case 'b':
727           param = get_bf (param, &val);
728           opcode |= val;
729           break;
730
731         case 'p':
732           param = get_pcr (param, insn, RELOC_PC16);
733           break;
734
735         case 'P':
736           param = get_pcr (param, insn, RELOC_PC26);
737           break;
738
739         case 'B':
740           param = get_cmp (param, &val);
741           opcode |= val;
742           break;
743
744         case 'M':
745           param = get_cnd (param, &val);
746           opcode |= val;
747           break;
748
749         case 'c':
750           param = get_cr (param, &val);
751           opcode |= val << 5;
752           break;
753
754         case 'f':
755           param = get_fcr (param, &val);
756           opcode |= val << 5;
757           break;
758
759         case 'V':
760           param = get_vec9 (param, &val);
761           opcode |= val;
762           break;
763
764         case '?':
765           /* Having this here repeats the warning somtimes.
766            But can't we stand that?  */
767           as_warn (_("Use of obsolete instruction"));
768           break;
769         }
770     }
771 }
772
773 void
774 md_assemble (char *op)
775 {
776   char *param, *thisfrag;
777   char c;
778   struct m88k_opcode *format;
779   struct m88k_insn insn;
780
781   assert (op);
782
783   /* Skip over instruction to find parameters.  */
784   for (param = op; *param != 0 && !ISSPACE (*param); param++)
785     ;
786   c = *param;
787   *param++ = '\0';
788
789   /* Try to find the instruction in the hash table.  */
790   if ((format = (struct m88k_opcode *) hash_find (op_hash, op)) == NULL)
791     {
792       as_bad (_("Invalid mnemonic '%s'"), op);
793       return;
794     }
795
796   /* Try parsing this instruction into insn.  */
797   insn.exp.X_add_symbol = 0;
798   insn.exp.X_op_symbol = 0;
799   insn.exp.X_add_number = 0;
800   insn.exp.X_op = O_illegal;
801   insn.reloc = NO_RELOC;
802
803   while (!calcop (format, param, &insn))
804     {
805       /* If it doesn't parse try the next instruction.  */
806       if (!strcmp (format[0].name, format[1].name))
807         format++;
808       else
809         {
810           as_fatal (_("Parameter syntax error"));
811           return;
812         }
813     }
814
815   /* Grow the current frag and plop in the opcode.  */
816   thisfrag = frag_more (4);
817   md_number_to_chars (thisfrag, insn.opcode, 4);
818
819   /* If this instruction requires labels mark it for later.  */
820   switch (insn.reloc)
821     {
822     case NO_RELOC:
823       break;
824
825     case RELOC_LO16:
826     case RELOC_HI16:
827       fix_new_exp (frag_now,
828                    thisfrag - frag_now->fr_literal + 2,
829                    2,
830                    &insn.exp,
831                    0,
832                    insn.reloc);
833       break;
834
835     case RELOC_IW16:
836       fix_new_exp (frag_now,
837                    thisfrag - frag_now->fr_literal,
838                    4,
839                    &insn.exp,
840                    0,
841                    insn.reloc);
842       break;
843
844     case RELOC_PC16:
845       fix_new_exp (frag_now,
846                    thisfrag - frag_now->fr_literal + 2,
847                    2,
848                    &insn.exp,
849                    1,
850                    insn.reloc);
851       break;
852
853     case RELOC_PC26:
854       fix_new_exp (frag_now,
855                    thisfrag - frag_now->fr_literal,
856                    4,
857                    &insn.exp,
858                    1,
859                    insn.reloc);
860       break;
861
862     default:
863       as_fatal (_("Unknown relocation type"));
864       break;
865     }
866 }
867
868 void
869 md_number_to_chars (char *buf, valueT val, int nbytes)
870 {
871   number_to_chars_bigendian (buf, val, nbytes);
872 }
873
874 #define MAX_LITTLENUMS 6
875
876 /* Turn a string in input_line_pointer into a floating point constant of type
877    type, and store the appropriate bytes in *litP.  The number of LITTLENUMS
878    emitted is stored in *sizeP .  An error message is returned, or NULL on OK.  */
879
880 char *
881 md_atof (int type, char *litP, int *sizeP)
882 {
883   int prec;
884   LITTLENUM_TYPE words[MAX_LITTLENUMS];
885   LITTLENUM_TYPE *wordP;
886   char *t;
887
888   switch (type)
889     {
890     case 'f':
891     case 'F':
892     case 's':
893     case 'S':
894       prec = 2;
895       break;
896
897     case 'd':
898     case 'D':
899     case 'r':
900     case 'R':
901       prec = 4;
902       break;
903
904     case 'x':
905     case 'X':
906       prec = 6;
907       break;
908
909     case 'p':
910     case 'P':
911       prec = 6;
912       break;
913
914     default:
915       *sizeP = 0;
916       return _("Bad call to MD_ATOF()");
917     }
918   t = atof_ieee (input_line_pointer, type, words);
919   if (t)
920     input_line_pointer = t;
921
922   *sizeP = prec * sizeof (LITTLENUM_TYPE);
923   for (wordP = words; prec--;)
924     {
925       md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
926       litP += sizeof (LITTLENUM_TYPE);
927     }
928   return 0;
929 }
930
931 int md_short_jump_size = 4;
932
933 void
934 md_create_short_jump (char *ptr,
935                       addressT from_addr ATTRIBUTE_UNUSED,
936                       addressT to_addr ATTRIBUTE_UNUSED,
937                       fragS *frag,
938                       symbolS *to_symbol)
939 {
940   ptr[0] = (char) 0xc0;
941   ptr[1] = 0x00;
942   ptr[2] = 0x00;
943   ptr[3] = 0x00;
944   fix_new (frag,
945            ptr - frag->fr_literal,
946            4,
947            to_symbol,
948            (offsetT) 0,
949            0,
950            RELOC_PC26);         /* Botch: Shouldn't this be RELOC_PC16? */
951 }
952
953 int md_long_jump_size = 4;
954
955 void
956 md_create_long_jump (char *ptr,
957                      addressT from_addr ATTRIBUTE_UNUSED,
958                      addressT to_addr ATTRIBUTE_UNUSED,
959                      fragS *frag,
960                      symbolS *to_symbol)
961 {
962   ptr[0] = (char) 0xc0;
963   ptr[1] = 0x00;
964   ptr[2] = 0x00;
965   ptr[3] = 0x00;
966   fix_new (frag,
967            ptr - frag->fr_literal,
968            4,
969            to_symbol,
970            (offsetT) 0,
971            0,
972            RELOC_PC26);
973 }
974
975 int
976 md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
977                                segT segment_type ATTRIBUTE_UNUSED)
978 {
979   as_fatal (_("Relaxation should never occur"));
980   return -1;
981 }
982
983 #ifdef M88KCOFF
984
985 /* These functions are needed if we are linking with obj-coffbfd.c.
986    That file may be replaced by a more BFD oriented version at some
987    point.  If that happens, these functions should be reexamined.
988
989    Ian Lance Taylor, Cygnus Support, 13 July 1993.  */
990
991 /* Given a fixS structure (created by a call to fix_new, above),
992    return the BFD relocation type to use for it.  */
993
994 short
995 tc_coff_fix2rtype (fixS *fixp)
996 {
997   switch (fixp->fx_r_type)
998     {
999     case RELOC_LO16:
1000       return R_LVRT16;
1001     case RELOC_HI16:
1002       return R_HVRT16;
1003     case RELOC_PC16:
1004       return R_PCR16L;
1005     case RELOC_PC26:
1006       return R_PCR26L;
1007     case RELOC_32:
1008       return R_VRT32;
1009     case RELOC_IW16:
1010       return R_VRT16;
1011     default:
1012       abort ();
1013     }
1014 }
1015
1016 /* Apply a fixS to the object file.  Since COFF does not use addends
1017    in relocs, the addend is actually stored directly in the object
1018    file itself.  */
1019
1020 void
1021 md_apply_fix3 (fixS *fixP, valueT * valP, segT seg ATTRIBUTE_UNUSED)
1022 {
1023   long val = * (long *) valP;
1024   char *buf;
1025
1026   buf = fixP->fx_frag->fr_literal + fixP->fx_where;
1027   fixP->fx_offset = 0;
1028
1029   switch (fixP->fx_r_type)
1030     {
1031     case RELOC_IW16:
1032       fixP->fx_offset = val >> 16;
1033       buf[2] = val >> 8;
1034       buf[3] = val;
1035       break;
1036
1037     case RELOC_LO16:
1038       fixP->fx_offset = val >> 16;
1039       buf[0] = val >> 8;
1040       buf[1] = val;
1041       break;
1042
1043     case RELOC_HI16:
1044       fixP->fx_offset = val >> 16;
1045       buf[0] = val >> 8;
1046       buf[1] = val;
1047       break;
1048
1049     case RELOC_PC16:
1050       buf[0] = val >> 10;
1051       buf[1] = val >> 2;
1052       break;
1053
1054     case RELOC_PC26:
1055       buf[0] |= (val >> 26) & 0x03;
1056       buf[1] = val >> 18;
1057       buf[2] = val >> 10;
1058       buf[3] = val >> 2;
1059       break;
1060
1061     case RELOC_32:
1062       buf[0] = val >> 24;
1063       buf[1] = val >> 16;
1064       buf[2] = val >> 8;
1065       buf[3] = val;
1066       break;
1067
1068     default:
1069       abort ();
1070     }
1071
1072   if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
1073     fixP->fx_done = 1;
1074 }
1075
1076 /* Where a PC relative offset is calculated from.  On the m88k they
1077    are calculated from just after the instruction.  */
1078
1079 long
1080 md_pcrel_from (fixS *fixp)
1081 {
1082   switch (fixp->fx_r_type)
1083     {
1084     case RELOC_PC16:
1085       return fixp->fx_frag->fr_address + fixp->fx_where - 2;
1086     case RELOC_PC26:
1087       return fixp->fx_frag->fr_address + fixp->fx_where;
1088     default:
1089       abort ();
1090     }
1091 }
1092
1093 /* Fill in rs_align_code fragments.  */
1094
1095 void
1096 m88k_handle_align (fragS *fragp)
1097 {
1098   static const unsigned char nop_pattern[] = { 0xf4, 0x00, 0x58, 0x00 };
1099
1100   int bytes;
1101   char *p;
1102
1103   if (fragp->fr_type != rs_align_code)
1104     return;
1105
1106   bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
1107   p = fragp->fr_literal + fragp->fr_fix;
1108
1109   if (bytes & 3)
1110     {
1111       int fix = bytes & 3;
1112       memset (p, 0, fix);
1113       p += fix;
1114       bytes -= fix;
1115       fragp->fr_fix += fix;
1116     }
1117
1118   memcpy (p, nop_pattern, 4);
1119   fragp->fr_var = 4;
1120 }
1121
1122 #endif /* M88KCOFF */
1123
1124 const pseudo_typeS md_pseudo_table[] =
1125 {
1126   {"align", s_align_bytes, 4},
1127   {"def", s_set, 0},
1128   {"dfloat", float_cons, 'd'},
1129   {"ffloat", float_cons, 'f'},
1130   {"half", cons, 2},
1131   {"bss", s_lcomm, 1},
1132   {"string", stringer, 0},
1133   {"word", cons, 4},
1134   /* Force set to be treated as an instruction.  */
1135   {"set", NULL, 0},
1136   {".set", s_set, 0},
1137   {NULL, NULL, 0}
1138 };