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