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