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