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