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