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