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