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