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