]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gas/config/tc-m88k.c
* read.c (read_a_source_file): If NO_PSEUDO_DOT is defined, look
[thirdparty/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 (C) 1989, 1990, 1991, 1993 Free Software Foundation, Inc.
5
6 This file is part of GAS, the GNU Assembler.
7
8 GAS is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 1, or (at your option)
11 any later version.
12
13 GAS is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GAS; see the file COPYING. If not, write to
20 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21
22 #include <ctype.h>
23 #include "as.h"
24 #include "m88k-opcode.h"
25
26 char *getval ();
27 char *get_reg ();
28 char *get_imm16 ();
29 char *get_bf ();
30 char *get_pcr ();
31 char *get_cmp ();
32 char *get_cnd ();
33 char *get_cr ();
34 char *get_fcr ();
35 char *get_vec9 ();
36
37 struct field_val_assoc
38 {
39 char *name;
40 unsigned val;
41 };
42
43 struct field_val_assoc cr_regs[] =
44 {
45 {"PID", 0},
46 {"PSR", 1},
47 {"EPSR", 2},
48 {"SSBR", 3},
49 {"SXIP", 4},
50 {"SNIP", 5},
51 {"SFIP", 6},
52 {"VBR", 7},
53 {"DMT0", 8},
54 {"DMD0", 9},
55 {"DMA0", 10},
56 {"DMT1", 11},
57 {"DMD1", 12},
58 {"DMA1", 13},
59 {"DMT2", 14},
60 {"DMD2", 15},
61 {"DMA2", 16},
62 {"SR0", 17},
63 {"SR1", 18},
64 {"SR2", 19},
65 {"SR3", 20},
66
67 {NULL, 0},
68 };
69
70 struct field_val_assoc fcr_regs[] =
71 {
72 {"FPECR", 0},
73 {"FPHS1", 1},
74 {"FPLS1", 2},
75 {"FPHS2", 3},
76 {"FPLS2", 4},
77 {"FPPT", 5},
78 {"FPRH", 6},
79 {"FPRL", 7},
80 {"FPIT", 8},
81
82 {"FPSR", 62},
83 {"FPCR", 63},
84
85 {NULL, 0},
86 };
87
88 struct field_val_assoc cmpslot[] =
89 {
90 /* Integer Floating point */
91 {"nc", 0},
92 {"cp", 1},
93 {"eq", 2},
94 {"ne", 3},
95 {"gt", 4},
96 {"le", 5},
97 {"lt", 6},
98 {"ge", 7},
99 {"hi", 8}, {"ou", 8},
100 {"ls", 9}, {"ib", 9},
101 {"lo", 10}, {"in", 10},
102 {"hs", 11}, {"ob", 11},
103 {"be", 12}, {"ue", 12},
104 {"nb", 13}, {"lg", 13},
105 {"he", 14}, {"ug", 14},
106 {"nh", 15}, {"ule", 15},
107 {"ul", 16},
108 {"uge", 17},
109
110 {NULL, 0},
111 };
112
113 struct field_val_assoc cndmsk[] =
114 {
115 {"gt0", 1},
116 {"eq0", 2},
117 {"ge0", 3},
118 {"lt0", 12},
119 {"ne0", 13},
120 {"le0", 14},
121
122 {NULL, 0},
123 };
124
125 struct m88k_insn
126 {
127 unsigned long opcode;
128 expressionS exp;
129 enum reloc_type reloc;
130 };
131
132 extern char *myname;
133 static struct hash_control *op_hash = NULL;
134
135 /* These bits should be turned off in the first address of every segment */
136 int md_seg_align = 7;
137
138 /* These chars start a comment anywhere in a source file (except inside
139 another comment */
140 const char comment_chars[] = ";";
141
142 /* These chars only start a comment at the beginning of a line. */
143 const char line_comment_chars[] = "#";
144
145 const char line_separator_chars[] = "";
146
147 /* Chars that can be used to separate mant from exp in floating point nums */
148 const char EXP_CHARS[] = "eE";
149
150 /* Chars that mean this number is a floating point constant */
151 /* as in 0f123.456 */
152 /* or 0H1.234E-12 (see exp chars above) */
153 const char FLT_CHARS[] = "dDfF";
154
155 extern void float_cons (), cons (), s_globl (), s_space (),
156 s_set (), s_lcomm ();
157 static void s_file ();
158
159 const pseudo_typeS md_pseudo_table[] =
160 {
161 {"align", s_align_bytes, 4},
162 {"def", s_set, 0},
163 {"dfloat", float_cons, 'd'},
164 {"ffloat", float_cons, 'f'},
165 {"global", s_globl, 0},
166 {"half", cons, 2},
167 {"bss", s_lcomm, 1},
168 {"string", stringer, 0},
169 {"word", cons, 4},
170 {"zero", s_space, 0},
171 {0}
172 };
173
174 void
175 md_begin ()
176 {
177 char *retval = NULL;
178 unsigned int i = 0;
179
180 /* initialize hash table */
181
182 op_hash = hash_new ();
183 if (op_hash == NULL)
184 as_fatal ("Could not initialize hash table");
185
186 /* loop until you see the end of the list */
187
188 while (*m88k_opcodes[i].name)
189 {
190 char *name = m88k_opcodes[i].name;
191
192 /* hash each mnemonic and record its position */
193
194 retval = hash_insert (op_hash, name, &m88k_opcodes[i]);
195
196 if (retval != NULL && *retval != '\0')
197 as_fatal ("Can't hash instruction '%s':%s",
198 m88k_opcodes[i].name, retval);
199
200 /* skip to next unique mnemonic or end of list */
201
202 for (i++; !strcmp (m88k_opcodes[i].name, name); i++)
203 ;
204 }
205 }
206
207 int
208 md_parse_option (argP, cntP, vecP)
209 char **argP;
210 int *cntP;
211 char ***vecP;
212 {
213 return 0;
214 }
215
216 void
217 md_assemble (op)
218 char *op;
219 {
220 char *param, *thisfrag;
221 char c;
222 struct m88k_opcode *format;
223 struct m88k_insn insn;
224
225 assert (op);
226
227 /* skip over instruction to find parameters */
228
229 for (param = op; *param != 0 && !isspace (*param); param++)
230 ;
231 c = *param;
232 *param++ = '\0';
233
234 /* try to find the instruction in the hash table */
235
236 if ((format = (struct m88k_opcode *) hash_find (op_hash, op)) == NULL)
237 {
238 as_bad ("Invalid mnemonic '%s'", op);
239 return;
240 }
241
242 /* try parsing this instruction into insn */
243
244 insn.exp.X_add_symbol = 0;
245 insn.exp.X_op_symbol = 0;
246 insn.exp.X_add_number = 0;
247 insn.exp.X_op = O_illegal;
248 insn.reloc = NO_RELOC;
249
250 while (!calcop (format, param, &insn))
251 {
252 /* if it doesn't parse try the next instruction */
253
254 if (!strcmp (format[0].name, format[1].name))
255 format++;
256 else
257 {
258 as_fatal ("Parameter syntax error");
259 return;
260 }
261 }
262
263 /* grow the current frag and plop in the opcode */
264
265 thisfrag = frag_more (4);
266 md_number_to_chars (thisfrag, insn.opcode, 4);
267
268 /* if this instruction requires labels mark it for later */
269
270 switch (insn.reloc)
271 {
272 case NO_RELOC:
273 break;
274
275 case RELOC_LO16:
276 case RELOC_HI16:
277 fix_new_exp (frag_now,
278 thisfrag - frag_now->fr_literal + 2,
279 2,
280 &insn.exp,
281 0,
282 insn.reloc);
283 break;
284
285 case RELOC_IW16:
286 fix_new_exp (frag_now,
287 thisfrag - frag_now->fr_literal,
288 4,
289 &insn.exp,
290 0,
291 insn.reloc);
292 break;
293
294 case RELOC_PC16:
295 fix_new_exp (frag_now,
296 thisfrag - frag_now->fr_literal + 2,
297 2,
298 &insn.exp,
299 1,
300 insn.reloc);
301 break;
302
303 case RELOC_PC26:
304 fix_new_exp (frag_now,
305 thisfrag - frag_now->fr_literal,
306 4,
307 &insn.exp,
308 1,
309 insn.reloc);
310 break;
311
312 default:
313 as_fatal ("Unknown relocation type");
314 break;
315 }
316 }
317
318 int
319 calcop (format, param, insn)
320 struct m88k_opcode *format;
321 char *param;
322 struct m88k_insn *insn;
323 {
324 char *fmt = format->op_spec;
325 int f;
326 unsigned val;
327 unsigned opcode;
328 int reg_prefix = 'r';
329
330 insn->opcode = format->opcode;
331 opcode = 0;
332
333 for (;;)
334 {
335 if (param == 0)
336 return 0;
337 f = *fmt++;
338 switch (f)
339 {
340 case 0:
341 insn->opcode |= opcode;
342 return *param == 0;
343
344 default:
345 if (f != *param++)
346 return 0;
347 break;
348
349 case 'd':
350 param = get_reg (param, &val, reg_prefix);
351 reg_prefix = 'r';
352 opcode |= val << 21;
353 break;
354
355 case 'x':
356 reg_prefix = 'x';
357 break;
358
359 case '1':
360 param = get_reg (param, &val, reg_prefix);
361 reg_prefix = 'r';
362 opcode |= val << 16;
363 break;
364
365 case '2':
366 param = get_reg (param, &val, reg_prefix);
367 reg_prefix = 'r';
368 opcode |= val;
369 break;
370
371 case '3':
372 param = get_reg (param, &val, 'r');
373 opcode |= (val << 16) | val;
374 break;
375
376 case 'I':
377 param = get_imm16 (param, insn);
378 break;
379
380 case 'b':
381 param = get_bf (param, &val);
382 opcode |= val;
383 break;
384
385 case 'p':
386 param = get_pcr (param, insn, RELOC_PC16);
387 break;
388
389 case 'P':
390 param = get_pcr (param, insn, RELOC_PC26);
391 break;
392
393 case 'B':
394 param = get_cmp (param, &val);
395 opcode |= val;
396 break;
397
398 case 'M':
399 param = get_cnd (param, &val);
400 opcode |= val;
401 break;
402
403 case 'c':
404 param = get_cr (param, &val);
405 opcode |= val << 5;
406 break;
407
408 case 'f':
409 param = get_fcr (param, &val);
410 opcode |= val << 5;
411 break;
412
413 case 'V':
414 param = get_vec9 (param, &val);
415 opcode |= val;
416 break;
417
418 case '?':
419 /* Having this here repeats the warning somtimes.
420 But can't we stand that? */
421 as_warn ("Use of obsolete instruction");
422 break;
423 }
424 }
425 }
426
427 char *
428 match_name (param, assoc_tab, valp)
429 char *param;
430 struct field_val_assoc *assoc_tab;
431 unsigned *valp;
432 {
433 int i;
434 char *name;
435 int name_len;
436
437 for (i = 0;; i++)
438 {
439 name = assoc_tab[i].name;
440 if (name == NULL)
441 return NULL;
442 name_len = strlen (name);
443 if (!strncmp (param, name, name_len))
444 {
445 *valp = assoc_tab[i].val;
446 return param + name_len;
447 }
448 }
449 }
450
451 char *
452 get_reg (param, regnop, reg_prefix)
453 char *param;
454 unsigned *regnop;
455 int reg_prefix;
456 {
457 unsigned c;
458 unsigned regno;
459
460 c = *param++;
461 if (c == reg_prefix)
462 {
463 regno = *param++ - '0';
464 if (regno < 10)
465 {
466 if (regno == 0)
467 {
468 *regnop = 0;
469 return param;
470 }
471 c = *param - '0';
472 if (c < 10)
473 {
474 regno = regno * 10 + c;
475 if (c < 32)
476 {
477 *regnop = regno;
478 return param + 1;
479 }
480 }
481 else
482 {
483 *regnop = regno;
484 return param;
485 }
486 }
487 return NULL;
488 }
489 else if (c == 's' && param[0] == 'p')
490 {
491 *regnop = 31;
492 return param + 1;
493 }
494
495 return 0;
496 }
497
498 char *
499 get_imm16 (param, insn)
500 char *param;
501 struct m88k_insn *insn;
502 {
503 enum reloc_type reloc = NO_RELOC;
504 unsigned int val;
505 char *save_ptr;
506
507 if (!strncmp (param, "hi16", 4) && !isalnum (param[4]))
508 {
509 reloc = RELOC_HI16;
510 param += 4;
511 }
512 else if (!strncmp (param, "lo16", 4) && !isalnum (param[4]))
513 {
514 reloc = RELOC_LO16;
515 param += 4;
516 }
517 else if (!strncmp (param, "iw16", 4) && !isalnum (param[4]))
518 {
519 reloc = RELOC_IW16;
520 param += 4;
521 }
522
523 save_ptr = input_line_pointer;
524 input_line_pointer = param;
525 expression (&insn->exp);
526 param = input_line_pointer;
527 input_line_pointer = save_ptr;
528
529 val = insn->exp.X_add_number;
530
531 if (insn->exp.X_op == O_constant)
532 {
533 /* Insert the value now, and reset reloc to NO_RELOC. */
534 if (reloc == NO_RELOC)
535 {
536 /* Warn about too big expressions if not surrounded by xx16. */
537 if (val > 0xffff)
538 as_warn ("Expression truncated to 16 bits");
539 }
540
541 if (reloc == RELOC_HI16)
542 val >>= 16;
543
544 insn->opcode |= val & 0xffff;
545 reloc = NO_RELOC;
546 }
547 else if (reloc == NO_RELOC)
548 /* We accept a symbol even without lo16, hi16, etc, and assume
549 lo16 was intended. */
550 reloc = RELOC_LO16;
551
552 insn->reloc = reloc;
553
554 return param;
555 }
556
557 char *
558 get_pcr (param, insn, reloc)
559 char *param;
560 struct m88k_insn *insn;
561 enum reloc_type reloc;
562 {
563 char *saveptr, *saveparam;
564
565 saveptr = input_line_pointer;
566 input_line_pointer = param;
567
568 expression (&insn->exp);
569
570 saveparam = input_line_pointer;
571 input_line_pointer = saveptr;
572
573 /* Botch: We should relocate now if O_constant. */
574 insn->reloc = reloc;
575
576 return saveparam;
577 }
578
579 char *
580 get_cmp (param, valp)
581 char *param;
582 unsigned *valp;
583 {
584 unsigned int val;
585 char *save_ptr;
586
587 save_ptr = param;
588
589 param = match_name (param, cmpslot, valp);
590 val = *valp;
591
592 if (param == NULL)
593 {
594 param = save_ptr;
595
596 save_ptr = input_line_pointer;
597 input_line_pointer = param;
598 val = get_absolute_expression ();
599 param = input_line_pointer;
600 input_line_pointer = save_ptr;
601
602 if (val >= 32)
603 {
604 as_warn ("Expression truncated to 5 bits");
605 val %= 32;
606 }
607 }
608
609 *valp = val << 21;
610 return param;
611 }
612
613 char *
614 get_cnd (param, valp)
615 char *param;
616 unsigned *valp;
617 {
618 unsigned int val;
619
620 if (isdigit (*param))
621 {
622 param = getval (param, &val);
623
624 if (val >= 32)
625 {
626 as_warn ("Expression truncated to 5 bits");
627 val %= 32;
628 }
629 }
630 else
631 {
632 if (isupper (*param))
633 *param = tolower (*param);
634
635 if (isupper (param[1]))
636 param[1] = tolower (param[1]);
637
638 param = match_name (param, cndmsk, valp);
639
640 if (param == NULL)
641 return NULL;
642
643 val = *valp;
644 }
645
646 *valp = val << 21;
647 return param;
648 }
649
650 char *
651 get_bf2 (param, bc)
652 char *param;
653 int bc;
654 {
655 int depth = 0;
656 int c;
657
658 for (;;)
659 {
660 c = *param;
661 if (c == 0)
662 return param;
663 else if (c == '(')
664 depth++;
665 else if (c == ')')
666 depth--;
667 else if (c == bc && depth <= 0)
668 return param;
669 param++;
670 }
671 }
672
673 char *
674 get_bf_offset_expression (param, offsetp)
675 char *param;
676 unsigned *offsetp;
677 {
678 unsigned offset;
679
680 if (isalpha (param[0]))
681 {
682 if (isupper (param[0]))
683 param[0] = tolower (param[0]);
684 if (isupper (param[1]))
685 param[1] = tolower (param[1]);
686
687 param = match_name (param, cmpslot, offsetp);
688
689 return param;
690 }
691 else
692 {
693 input_line_pointer = param;
694 offset = get_absolute_expression ();
695 param = input_line_pointer;
696 }
697
698 *offsetp = offset;
699 return param;
700 }
701
702 char *
703 get_bf (param, valp)
704 char *param;
705 unsigned *valp;
706 {
707 unsigned offset = 0;
708 unsigned width = 0;
709 char *xp;
710 char *save_ptr;
711
712 xp = get_bf2 (param, '<');
713
714 save_ptr = input_line_pointer;
715 input_line_pointer = param;
716 if (*xp == 0)
717 {
718 /* We did not find '<'. We have an offset (width implicitly 32). */
719 param = get_bf_offset_expression (param, &offset);
720 input_line_pointer = save_ptr;
721 if (param == NULL)
722 return NULL;
723 }
724 else
725 {
726 *xp++ = 0; /* Overwrite the '<' */
727 param = get_bf2 (xp, '>');
728 if (*param == 0)
729 return NULL;
730 *param++ = 0; /* Overwrite the '>' */
731
732 width = get_absolute_expression ();
733 xp = get_bf_offset_expression (xp, &offset);
734 input_line_pointer = save_ptr;
735
736 if (xp + 1 != param)
737 return NULL;
738 }
739
740 *valp = ((width % 32) << 5) | (offset % 32);
741
742 return param;
743 }
744
745 char *
746 get_cr (param, regnop)
747 char *param;
748 unsigned *regnop;
749 {
750 unsigned regno;
751 unsigned c;
752 int i;
753 int name_len;
754
755 if (!strncmp (param, "cr", 2))
756 {
757 param += 2;
758
759 regno = *param++ - '0';
760 if (regno < 10)
761 {
762 if (regno == 0)
763 {
764 *regnop = 0;
765 return param;
766 }
767 c = *param - '0';
768 if (c < 10)
769 {
770 regno = regno * 10 + c;
771 if (c < 64)
772 {
773 *regnop = regno;
774 return param + 1;
775 }
776 }
777 else
778 {
779 *regnop = regno;
780 return param;
781 }
782 }
783 return NULL;
784 }
785
786 param = match_name (param, cr_regs, regnop);
787
788 return param;
789 }
790
791 char *
792 get_fcr (param, regnop)
793 char *param;
794 unsigned *regnop;
795 {
796 unsigned regno;
797 unsigned c;
798 int i;
799 int name_len;
800
801 if (!strncmp (param, "fcr", 3))
802 {
803 param += 3;
804
805 regno = *param++ - '0';
806 if (regno < 10)
807 {
808 if (regno == 0)
809 {
810 *regnop = 0;
811 return param;
812 }
813 c = *param - '0';
814 if (c < 10)
815 {
816 regno = regno * 10 + c;
817 if (c < 64)
818 {
819 *regnop = regno;
820 return param + 1;
821 }
822 }
823 else
824 {
825 *regnop = regno;
826 return param;
827 }
828 }
829 return NULL;
830 }
831
832 param = match_name (param, fcr_regs, regnop);
833
834 return param;
835 }
836
837 char *
838 get_vec9 (param, valp)
839 char *param;
840 unsigned *valp;
841 {
842 unsigned val;
843 char *save_ptr;
844
845 save_ptr = input_line_pointer;
846 input_line_pointer = param;
847 val = get_absolute_expression ();
848 param = input_line_pointer;
849 input_line_pointer = save_ptr;
850
851 if (val >= 1 << 9)
852 as_warn ("Expression truncated to 9 bits");
853
854 *valp = val % (1 << 9);
855
856 return param;
857 }
858
859 #define hexval(z) \
860 (isdigit (z) ? (z) - '0' : \
861 islower (z) ? (z) - 'a' + 10 : \
862 isupper (z) ? (z) - 'A' + 10 : -1)
863
864 char *
865 getval (param, valp)
866 char *param;
867 unsigned int *valp;
868 {
869 unsigned int val = 0;
870 unsigned int c;
871
872 c = *param++;
873 if (c == '0')
874 {
875 c = *param++;
876 if (c == 'x' || c == 'X')
877 {
878 c = *param++;
879 c = hexval (c);
880 while (c < 16)
881 {
882 val = val * 16 + c;
883 c = *param++;
884 c = hexval (c);
885 }
886 }
887 else
888 {
889 c -= '0';
890 while (c < 8)
891 {
892 val = val * 8 + c;
893 c = *param++ - '0';
894 }
895 }
896 }
897 else
898 {
899 c -= '0';
900 while (c < 10)
901 {
902 val = val * 10 + c;
903 c = *param++ - '0';
904 }
905 }
906
907 *valp = val;
908 return param - 1;
909 }
910
911 void
912 md_number_to_chars (buf, val, nbytes)
913 char *buf;
914 valueT val;
915 int nbytes;
916 {
917 switch (nbytes)
918 {
919 case 4:
920 *buf++ = val >> 24;
921 *buf++ = val >> 16;
922 case 2:
923 *buf++ = val >> 8;
924 case 1:
925 *buf = val;
926 break;
927
928 default:
929 abort ();
930 }
931 }
932
933 #if 0
934
935 /* This routine is never called. What is it for?
936 Ian Taylor, Cygnus Support 13 Jul 1993 */
937
938 void
939 md_number_to_imm (buf, val, nbytes, fixP, seg_type)
940 unsigned char *buf;
941 unsigned int val;
942 int nbytes;
943 fixS *fixP;
944 int seg_type;
945 {
946 if (seg_type != N_TEXT || fixP->fx_r_type == NO_RELOC)
947 {
948 switch (nbytes)
949 {
950 case 4:
951 *buf++ = val >> 24;
952 *buf++ = val >> 16;
953 case 2:
954 *buf++ = val >> 8;
955 case 1:
956 *buf = val;
957 break;
958
959 default:
960 abort ();
961 }
962 return;
963 }
964
965 switch (fixP->fx_r_type)
966 {
967 case RELOC_IW16:
968 buf[2] = val >> 8;
969 buf[3] = val;
970 break;
971
972 case RELOC_LO16:
973 buf[0] = val >> 8;
974 buf[1] = val;
975 break;
976
977 case RELOC_HI16:
978 buf[0] = val >> 24;
979 buf[1] = val >> 16;
980 break;
981
982 case RELOC_PC16:
983 val += 4;
984 buf[0] = val >> 10;
985 buf[1] = val >> 2;
986 break;
987
988 case RELOC_PC26:
989 val += 4;
990 buf[0] |= (val >> 26) & 0x03;
991 buf[1] = val >> 18;
992 buf[2] = val >> 10;
993 buf[3] = val >> 2;
994 break;
995
996 case RELOC_32:
997 buf[0] = val >> 24;
998 buf[1] = val >> 16;
999 buf[2] = val >> 8;
1000 buf[3] = val;
1001 break;
1002
1003 default:
1004 as_fatal ("Bad relocation type");
1005 break;
1006 }
1007 }
1008
1009 #endif /* 0 */
1010
1011 void
1012 md_number_to_disp (buf, val, nbytes)
1013 char *buf;
1014 int val;
1015 int nbytes;
1016 {
1017 as_fatal ("md_number_to_disp not defined");
1018 md_number_to_chars (buf, val, nbytes);
1019 }
1020
1021 void
1022 md_number_to_field (buf, val, nbytes)
1023 char *buf;
1024 int val;
1025 int nbytes;
1026 {
1027 as_fatal ("md_number_to_field not defined");
1028 md_number_to_chars (buf, val, nbytes);
1029 }
1030
1031 #define MAX_LITTLENUMS 6
1032
1033 /* Turn a string in input_line_pointer into a floating point constant of type
1034 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
1035 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
1036 */
1037 char *
1038 md_atof (type, litP, sizeP)
1039 char type;
1040 char *litP;
1041 int *sizeP;
1042 {
1043 int prec;
1044 LITTLENUM_TYPE words[MAX_LITTLENUMS];
1045 LITTLENUM_TYPE *wordP;
1046 char *t;
1047 char *atof_ieee ();
1048
1049 switch (type)
1050 {
1051 case 'f':
1052 case 'F':
1053 case 's':
1054 case 'S':
1055 prec = 2;
1056 break;
1057
1058 case 'd':
1059 case 'D':
1060 case 'r':
1061 case 'R':
1062 prec = 4;
1063 break;
1064
1065 case 'x':
1066 case 'X':
1067 prec = 6;
1068 break;
1069
1070 case 'p':
1071 case 'P':
1072 prec = 6;
1073 break;
1074
1075 default:
1076 *sizeP = 0;
1077 return "Bad call to MD_ATOF()";
1078 }
1079 t = atof_ieee (input_line_pointer, type, words);
1080 if (t)
1081 input_line_pointer = t;
1082
1083 *sizeP = prec * sizeof (LITTLENUM_TYPE);
1084 for (wordP = words; prec--;)
1085 {
1086 md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
1087 litP += sizeof (LITTLENUM_TYPE);
1088 }
1089 return ""; /* Someone should teach Dean about null pointers */
1090 }
1091
1092 int md_short_jump_size = 4;
1093
1094 void
1095 md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
1096 char *ptr;
1097 addressT from_addr, to_addr;
1098 fragS *frag;
1099 symbolS *to_symbol;
1100 {
1101 ptr[0] = (char) 0xc0;
1102 ptr[1] = 0x00;
1103 ptr[2] = 0x00;
1104 ptr[3] = 0x00;
1105 fix_new (frag,
1106 ptr - frag->fr_literal,
1107 4,
1108 to_symbol,
1109 (offsetT) 0,
1110 0,
1111 RELOC_PC26); /* Botch: Shouldn't this be RELOC_PC16? */
1112 }
1113
1114 int md_long_jump_size = 4;
1115
1116 void
1117 md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
1118 char *ptr;
1119 addressT from_addr, to_addr;
1120 fragS *frag;
1121 symbolS *to_symbol;
1122 {
1123 ptr[0] = (char) 0xc0;
1124 ptr[1] = 0x00;
1125 ptr[2] = 0x00;
1126 ptr[3] = 0x00;
1127 fix_new (frag,
1128 ptr - frag->fr_literal,
1129 4,
1130 to_symbol,
1131 (offsetT) 0,
1132 0,
1133 RELOC_PC26);
1134 }
1135
1136 int
1137 md_estimate_size_before_relax (fragP, segment_type)
1138 fragS *fragP;
1139 segT segment_type;
1140 {
1141 as_fatal ("Relaxation should never occur");
1142 }
1143
1144 const relax_typeS md_relax_table[] =
1145 {0};
1146
1147 void
1148 md_end ()
1149 {
1150 }
1151
1152 #if 0
1153
1154 /* As far as I can tell, this routine is never called. What is it
1155 doing here?
1156 Ian Taylor, Cygnus Support 13 Jul 1993 */
1157
1158
1159 /*
1160 * Risc relocations are completely different, so it needs
1161 * this machine dependent routine to emit them.
1162 */
1163 void
1164 emit_relocations (fixP, segment_address_in_file)
1165 fixS *fixP;
1166 relax_addressT segment_address_in_file;
1167 {
1168 struct reloc_info_m88k ri;
1169 symbolS *symbolP;
1170 extern char *next_object_file_charP;
1171
1172 bzero ((char *) &ri, sizeof (ri));
1173 for (; fixP; fixP = fixP->fx_next)
1174 {
1175 if (fixP->fx_r_type >= NO_RELOC)
1176 {
1177 fprintf (stderr, "fixP->fx_r_type = %d\n", fixP->fx_r_type);
1178 abort ();
1179 }
1180
1181 if ((symbolP = fixP->fx_addsy) != NULL)
1182 {
1183 ri.r_address = fixP->fx_frag->fr_address +
1184 fixP->fx_where - segment_address_in_file;
1185 if ((symbolP->sy_type & N_TYPE) == N_UNDF)
1186 {
1187 ri.r_extern = 1;
1188 ri.r_symbolnum = symbolP->sy_number;
1189 }
1190 else
1191 {
1192 ri.r_extern = 0;
1193 ri.r_symbolnum = symbolP->sy_type & N_TYPE;
1194 }
1195 if (symbolP && symbolP->sy_frag)
1196 {
1197 ri.r_addend = symbolP->sy_frag->fr_address;
1198 }
1199 ri.r_type = fixP->fx_r_type;
1200 if (fixP->fx_pcrel)
1201 {
1202 ri.r_addend -= ri.r_address;
1203 }
1204 else
1205 {
1206 ri.r_addend = fixP->fx_addnumber;
1207 }
1208
1209 append (&next_object_file_charP, (char *) &ri, sizeof (ri));
1210 }
1211 }
1212 return;
1213 }
1214
1215 #endif /* 0 */
1216
1217 #if 0
1218
1219 /* This routine can be subsumed by s_lcomm in read.c.
1220 Ian Taylor, Cygnus Support 13 Jul 1993 */
1221
1222
1223 static void
1224 s_bss ()
1225 {
1226 char *name;
1227 char c;
1228 char *p;
1229 int temp, bss_align;
1230 symbolS *symbolP;
1231
1232 name = input_line_pointer;
1233 c = get_symbol_end ();
1234 p = input_line_pointer;
1235 *p = c;
1236 SKIP_WHITESPACE ();
1237 if (*input_line_pointer != ',')
1238 {
1239 as_warn ("Expected comma after name");
1240 ignore_rest_of_line ();
1241 return;
1242 }
1243 input_line_pointer++;
1244 if ((temp = get_absolute_expression ()) < 0)
1245 {
1246 as_warn ("BSS length (%d.) <0! Ignored.", temp);
1247 ignore_rest_of_line ();
1248 return;
1249 }
1250 *p = 0;
1251 symbolP = symbol_find_or_make (name);
1252 *p = c;
1253 if (*input_line_pointer == ',')
1254 {
1255 input_line_pointer++;
1256 bss_align = get_absolute_expression ();
1257 }
1258 else
1259 bss_align = 0;
1260
1261 if (!S_IS_DEFINED(symbolP)
1262 || S_GET_SEGMENT(symbolP) == SEG_BSS)
1263 {
1264 if (! need_pass_2)
1265 {
1266 char *p;
1267 segT current_seg = now_seg;
1268 subsegT current_subseg = now_subseg;
1269
1270 subseg_new (SEG_BSS, 1); /* switch to bss */
1271
1272 if (bss_align)
1273 frag_align (bss_align, 0);
1274
1275 /* detach from old frag */
1276 if (symbolP->sy_type == N_BSS && symbolP->sy_frag != NULL)
1277 symbolP->sy_frag->fr_symbol = NULL;
1278
1279 symbolP->sy_frag = frag_now;
1280 p = frag_var (rs_org, 1, 1, (relax_substateT)0, symbolP,
1281 temp, (char *)0);
1282 *p = 0;
1283 S_SET_SEGMENT (symbolP, SEG_BSS);
1284
1285 subseg_new (current_seg, current_subseg);
1286 }
1287 }
1288 else
1289 {
1290 as_warn ("Ignoring attempt to re-define symbol %s.", name);
1291 }
1292
1293 while (!is_end_of_line[*input_line_pointer])
1294 {
1295 input_line_pointer++;
1296 }
1297
1298 return;
1299 }
1300
1301 #endif /* 0 */
1302
1303 #ifdef M88KCOFF
1304
1305 /* These functions are needed if we are linking with obj-coffbfd.c.
1306 That file may be replaced by a more BFD oriented version at some
1307 point. If that happens, these functions should be rexamined.
1308
1309 Ian Lance Taylor, Cygnus Support, 13 July 1993. */
1310
1311 /* Given a fixS structure (created by a call to fix_new, above),
1312 return the BFD relocation type to use for it. */
1313
1314 short
1315 tc_coff_fix2rtype (fixp)
1316 fixS *fixp;
1317 {
1318 switch (fixp->fx_r_type)
1319 {
1320 case RELOC_LO16:
1321 return R_LVRT16;
1322 case RELOC_HI16:
1323 return R_HVRT16;
1324 case RELOC_PC16:
1325 return R_PCR16L;
1326 case RELOC_PC26:
1327 return R_PCR26L;
1328 case RELOC_32:
1329 return R_VRT32;
1330 case RELOC_IW16:
1331 return R_VRT16;
1332 default:
1333 abort ();
1334 }
1335 }
1336
1337 /* Apply a fixS to the object file. Since COFF does not use addends
1338 in relocs, the addend is actually stored directly in the object
1339 file itself. */
1340
1341 void
1342 md_apply_fix (fixp, val)
1343 fixS *fixp;
1344 long val;
1345 {
1346 char *buf;
1347
1348 buf = fixp->fx_frag->fr_literal + fixp->fx_where;
1349 fixp->fx_offset = 0;
1350
1351 switch (fixp->fx_r_type)
1352 {
1353 case RELOC_IW16:
1354 fixp->fx_offset = val >> 16;
1355 buf[2] = val >> 8;
1356 buf[3] = val;
1357 break;
1358
1359 case RELOC_LO16:
1360 fixp->fx_offset = val >> 16;
1361 buf[0] = val >> 8;
1362 buf[1] = val;
1363 break;
1364
1365 case RELOC_HI16:
1366 fixp->fx_offset = val >> 16;
1367 buf[0] = val >> 8;
1368 buf[1] = val;
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
1395 /* Where a PC relative offset is calculated from. On the m88k they
1396 are calculated from just after the instruction. */
1397
1398 long
1399 md_pcrel_from (fixp)
1400 fixS *fixp;
1401 {
1402 switch (fixp->fx_r_type)
1403 {
1404 case RELOC_PC16:
1405 return fixp->fx_frag->fr_address + fixp->fx_where - 2;
1406 case RELOC_PC26:
1407 return fixp->fx_frag->fr_address + fixp->fx_where;
1408 default:
1409 abort ();
1410 }
1411 /*NOTREACHED*/
1412 }
1413
1414 #endif /* M88KCOFF */