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