These changes clean things up a bit, and improve Solaris cross
[deliverable/binutils-gdb.git] / gas / config / tc-m88k.c
1 /* m88k.c -- Assembler for the Motorola 88000
2 Contributed by Devon Bowen of Buffalo University
3 and Torbjorn Granlund of the Swedish Institute of Computer Science.
4 Copyright (C) 1989, 1990, 1991 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 const char comment_chars[] = ";";
152
153 /* These chars only start a comment at the beginning of a line. */
154 const char line_comment_chars[] = "#";
155
156 const char line_separator_chars[] = "";
157
158 /* Chars that can be used to separate mant from exp in floating point nums */
159 const char EXP_CHARS[] = "eE";
160
161 /* Chars that mean this number is a floating point constant */
162 /* as in 0f123.456 */
163 /* or 0H1.234E-12 (see exp chars above) */
164 const char FLT_CHARS[] = "dDfF";
165
166 extern void float_cons (), cons (), s_globl (), s_line (),
167 s_space (), s_set (), stringer (), s_lcomm ();
168 static void s_file ();
169 static void s_bss ();
170
171 const pseudo_typeS md_pseudo_table[] =
172 {
173 {"def", s_set, 0},
174 {"dfloat", float_cons, 'd'},
175 {"ffloat", float_cons, 'f'},
176 {"global", s_globl, 0},
177 {"half", cons, 2 },
178 {"bss", s_bss, 0},
179 {"ln", s_line, 0},
180 {"string", stringer, 0},
181 {"word", cons, 4 },
182 {"zero", s_space, 0},
183 {0}
184 };
185
186 void
187 md_begin ()
188 {
189 char *retval = NULL;
190 unsigned int i = 0;
191
192 /* initialize hash table */
193
194 op_hash = hash_new ();
195 if (op_hash == NULL)
196 as_fatal ("Could not initialize hash table");
197
198 /* loop until you see the end of the list */
199
200 while (*m88k_opcodes[i].name)
201 {
202 char *name = m88k_opcodes[i].name;
203
204 /* hash each mnemonic and record its position */
205
206 retval = hash_insert (op_hash, name, &m88k_opcodes[i]);
207
208 if (retval != NULL && *retval != '\0')
209 as_fatal ("Can't hash instruction '%s':%s",
210 m88k_opcodes[i].name, retval);
211
212 /* skip to next unique mnemonic or end of list */
213
214 for (i++; !strcmp (m88k_opcodes[i].name, name); i++)
215 ;
216 }
217 }
218
219 void
220 md_parse_option (argP, cntP, vecP)
221 char **argP;
222 int *cntP;
223 char ***vecP;
224 {
225 as_warn ("unknown option: -%s", *argP);
226 }
227
228 void
229 md_assemble (op)
230 char *op;
231 {
232 char *param, *thisfrag;
233 struct m88k_opcode *format;
234 struct m88k_insn insn;
235
236 assert (op);
237
238 /* skip over instruction to find parameters */
239
240 for (param = op; *param != 0 && !isspace (*param); param++)
241 ;
242 if (*param != 0)
243 *param++ = 0;
244
245 /* try to find the instruction in the hash table */
246
247 if ((format = (struct m88k_opcode *) hash_find (op_hash, op)) == NULL)
248 {
249 as_fatal ("Invalid mnemonic '%s'", op);
250 return;
251 }
252
253 /* try parsing this instruction into insn */
254
255 insn.exp.X_add_symbol = 0;
256 insn.exp.X_subtract_symbol = 0;
257 insn.exp.X_add_number = 0;
258 insn.exp.X_seg = 0;
259 insn.reloc = NO_RELOC;
260
261 while (!calcop (format, param, &insn))
262 {
263 /* if it doesn't parse try the next instruction */
264
265 if (!strcmp (format[0].name, format[1].name))
266 format++;
267 else
268 {
269 as_fatal ("Parameter syntax error");
270 return;
271 }
272 }
273
274 /* grow the current frag and plop in the opcode */
275
276 thisfrag = frag_more (4);
277 md_number_to_chars (thisfrag, insn.opcode, 4);
278
279 /* if this instruction requires labels mark it for later */
280
281 switch (insn.reloc)
282 {
283 case NO_RELOC:
284 break;
285
286 case RELOC_LO16:
287 case RELOC_HI16:
288 fix_new (frag_now,
289 thisfrag - frag_now->fr_literal + 2,
290 2,
291 insn.exp.X_add_symbol,
292 insn.exp.X_subtract_symbol,
293 insn.exp.X_add_number,
294 0,
295 insn.reloc);
296 break;
297
298 case RELOC_IW16:
299 fix_new (frag_now,
300 thisfrag - frag_now->fr_literal,
301 4,
302 insn.exp.X_add_symbol,
303 insn.exp.X_subtract_symbol,
304 insn.exp.X_add_number,
305 0,
306 insn.reloc);
307 break;
308
309 case RELOC_PC16:
310 fix_new (frag_now,
311 thisfrag - frag_now->fr_literal + 2,
312 2,
313 insn.exp.X_add_symbol,
314 insn.exp.X_subtract_symbol,
315 insn.exp.X_add_number,
316 1,
317 insn.reloc);
318 break;
319
320 case RELOC_PC26:
321 fix_new (frag_now,
322 thisfrag - frag_now->fr_literal,
323 4,
324 insn.exp.X_add_symbol,
325 insn.exp.X_subtract_symbol,
326 insn.exp.X_add_number,
327 1,
328 insn.reloc);
329 break;
330
331 default:
332 as_fatal ("Unknown relocation type");
333 break;
334 }
335 }
336
337 int
338 calcop (format, param, insn)
339 struct m88k_opcode *format;
340 char *param;
341 struct m88k_insn *insn;
342 {
343 char *fmt = format->op_spec;
344 int f;
345 unsigned val;
346 unsigned opcode;
347
348 insn->opcode = format->opcode;
349 opcode = 0;
350
351 for (;;)
352 {
353 if (param == 0)
354 return 0;
355 f = *fmt++;
356 switch (f)
357 {
358 case 0:
359 insn->opcode |= opcode;
360 return *param == 0;
361
362 default:
363 if (f != *param++)
364 return 0;
365 break;
366
367 case 'd':
368 param = get_reg (param, &val);
369 opcode |= val << 21;
370 break;
371
372 case '1':
373 param = get_reg (param, &val);
374 opcode |= val << 16;
375 break;
376
377 case '2':
378 param = get_reg (param, &val);
379 opcode |= val;
380 break;
381
382 case '3':
383 param = get_reg (param, &val);
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 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 char *
463 get_reg (param, regnop)
464 char *param;
465 unsigned *regnop;
466 {
467 unsigned c;
468 unsigned regno;
469
470 c = *param++;
471 if (c == 'r')
472 {
473 regno = *param++ - '0';
474 if (regno < 10)
475 {
476 if (regno == 0)
477 {
478 *regnop = 0;
479 return param;
480 }
481 c = *param - '0';
482 if (c < 10)
483 {
484 regno = regno * 10 + c;
485 if (c < 32)
486 {
487 *regnop = regno;
488 return param + 1;
489 }
490 }
491 else
492 {
493 *regnop = regno;
494 return param;
495 }
496 }
497 return NULL;
498 }
499 else if (c == 's' && param[0] == 'p')
500 {
501 *regnop = 31;
502 return param + 1;
503 }
504
505 return 0;
506 }
507
508 char *
509 get_imm16 (param, insn)
510 char *param;
511 struct m88k_insn *insn;
512 {
513 enum reloc_type reloc = NO_RELOC;
514 unsigned int val;
515 segT seg;
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 seg = 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 (seg == SEG_ABSOLUTE)
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 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 segT seg;
576
577 saveptr = input_line_pointer;
578 input_line_pointer = param;
579
580 seg = expression (&insn->exp);
581
582 saveparam = input_line_pointer;
583 input_line_pointer = saveptr;
584
585 /* Botch: We should relocate now if SEG_ABSOLUTE. */
586 insn->reloc = reloc;
587
588 return saveparam;
589 }
590
591 char *
592 get_cmp (param, valp)
593 char *param;
594 unsigned *valp;
595 {
596 unsigned int val;
597 char *save_ptr;
598
599 save_ptr = param;
600
601 param = match_name (param, cmpslot, valp);
602 val = *valp;
603
604 if (param == NULL)
605 {
606 param = save_ptr;
607
608 save_ptr = input_line_pointer;
609 input_line_pointer = param;
610 val = get_absolute_expression ();
611 param = input_line_pointer;
612 input_line_pointer = save_ptr;
613
614 if (val >= 32)
615 {
616 as_warn ("Expression truncated to 5 bits");
617 val %= 32;
618 }
619 }
620
621 *valp = val << 21;
622 return param;
623 }
624
625 char *
626 get_cnd (param, valp)
627 char *param;
628 unsigned *valp;
629 {
630 unsigned int val;
631
632 if (isdigit (*param))
633 {
634 param = getval (param, &val);
635
636 if (val >= 32)
637 {
638 as_warn ("Expression truncated to 5 bits");
639 val %= 32;
640 }
641 }
642 else
643 {
644 if (isupper (*param))
645 *param = tolower (*param);
646
647 if (isupper (param[1]))
648 param[1] = tolower (param[1]);
649
650 param = match_name (param, cndmsk, valp);
651
652 if (param == NULL)
653 return NULL;
654
655 val = *valp;
656 }
657
658 *valp = val << 21;
659 return param;
660 }
661
662 char *
663 get_bf2 (param, bc)
664 char *param;
665 int bc;
666 {
667 int depth = 0;
668 int c;
669
670 for (;;)
671 {
672 c = *param;
673 if (c == 0)
674 return param;
675 else if (c == '(')
676 depth++;
677 else if (c == ')')
678 depth--;
679 else if (c == bc && depth <= 0)
680 return param;
681 param++;
682 }
683 }
684
685 char *
686 get_bf_offset_expression (param, offsetp)
687 char *param;
688 unsigned *offsetp;
689 {
690 unsigned offset;
691
692 if (isalpha (param[0]))
693 {
694 if (isupper (param[0]))
695 param[0] = tolower (param[0]);
696 if (isupper (param[1]))
697 param[1] = tolower (param[1]);
698
699 param = match_name (param, cmpslot, offsetp);
700
701 return param;
702 }
703 else
704 {
705 input_line_pointer = param;
706 offset = get_absolute_expression ();
707 param = input_line_pointer;
708 }
709
710 *offsetp = offset;
711 return param;
712 }
713
714 char *
715 get_bf (param, valp)
716 char *param;
717 unsigned *valp;
718 {
719 unsigned offset = 0;
720 unsigned width = 0;
721 char *xp;
722 char *save_ptr;
723
724 xp = get_bf2 (param, '<');
725
726 save_ptr = input_line_pointer;
727 input_line_pointer = param;
728 if (*xp == 0)
729 {
730 /* We did not find '<'. We have an offset (width implicitly 32). */
731 param = get_bf_offset_expression (param, &offset);
732 if (param == NULL)
733 return NULL;
734 input_line_pointer = save_ptr;
735 }
736 else
737 {
738 *xp++ = 0; /* Overwrite the '<' */
739 param = get_bf2 (xp, '>');
740 if (*param == 0)
741 return NULL;
742 *param++ = 0; /* Overwrite the '>' */
743
744 width = get_absolute_expression ();
745 xp = get_bf_offset_expression (xp, &offset);
746 input_line_pointer = save_ptr;
747
748 if (xp + 1 != param)
749 return NULL;
750 }
751
752 *valp = ((width % 32) << 5) | (offset % 32);
753
754 return param;
755 }
756
757 char *
758 get_cr (param, regnop)
759 char *param;
760 unsigned *regnop;
761 {
762 unsigned regno;
763 unsigned c;
764 int i;
765 int name_len;
766
767 if (!strncmp (param, "cr", 2))
768 {
769 param += 2;
770
771 regno = *param++ - '0';
772 if (regno < 10)
773 {
774 if (regno == 0)
775 {
776 *regnop = 0;
777 return param;
778 }
779 c = *param - '0';
780 if (c < 10)
781 {
782 regno = regno * 10 + c;
783 if (c < 64)
784 {
785 *regnop = regno;
786 return param + 1;
787 }
788 }
789 else
790 {
791 *regnop = regno;
792 return param;
793 }
794 }
795 return NULL;
796 }
797
798 param = match_name (param, cr_regs, regnop);
799
800 return param;
801 }
802
803 char *
804 get_fcr (param, regnop)
805 char *param;
806 unsigned *regnop;
807 {
808 unsigned regno;
809 unsigned c;
810 int i;
811 int name_len;
812
813 if (!strncmp (param, "fcr", 3))
814 {
815 param += 3;
816
817 regno = *param++ - '0';
818 if (regno < 10)
819 {
820 if (regno == 0)
821 {
822 *regnop = 0;
823 return param;
824 }
825 c = *param - '0';
826 if (c < 10)
827 {
828 regno = regno * 10 + c;
829 if (c < 64)
830 {
831 *regnop = regno;
832 return param + 1;
833 }
834 }
835 else
836 {
837 *regnop = regno;
838 return param;
839 }
840 }
841 return NULL;
842 }
843
844 param = match_name (param, fcr_regs, regnop);
845
846 return param;
847 }
848
849 char *
850 get_vec9 (param, valp)
851 char *param;
852 unsigned *valp;
853 {
854 unsigned val;
855 char *save_ptr;
856
857 save_ptr = input_line_pointer;
858 input_line_pointer = param;
859 val = get_absolute_expression ();
860 param = input_line_pointer;
861 input_line_pointer = save_ptr;
862
863 if (val >= 1 << 9)
864 as_warn ("Expression truncated to 9 bits");
865
866 *valp = val % (1 << 9);
867
868 return param;
869 }
870
871 #define hexval(z) \
872 (isdigit (z) ? (z) - '0' : \
873 islower (z) ? (z) - 'a' + 10 : \
874 isupper (z) ? (z) - 'A' + 10 : -1)
875
876 char *
877 getval (param, valp)
878 char *param;
879 unsigned int *valp;
880 {
881 unsigned int val = 0;
882 unsigned int c;
883
884 c = *param++;
885 if (c == '0')
886 {
887 c = *param++;
888 if (c == 'x' || c == 'X')
889 {
890 c = *param++;
891 c = hexval (c);
892 while (c < 16)
893 {
894 val = val * 16 + c;
895 c = *param++;
896 c = hexval (c);
897 }
898 }
899 else
900 {
901 c -= '0';
902 while (c < 8)
903 {
904 val = val * 8 + c;
905 c = *param++ - '0';
906 }
907 }
908 }
909 else
910 {
911 c -= '0';
912 while (c < 10)
913 {
914 val = val * 10 + c;
915 c = *param++ - '0';
916 }
917 }
918
919 *valp = val;
920 return param - 1;
921 }
922
923 void
924 md_number_to_chars (buf, val, nbytes)
925 char *buf;
926 int val;
927 int nbytes;
928 {
929 switch (nbytes)
930 {
931 case 4:
932 *buf++ = val >> 24;
933 *buf++ = val >> 16;
934 case 2:
935 *buf++ = val >> 8;
936 case 1:
937 *buf = val;
938 break;
939
940 default:
941 abort ();
942 }
943 }
944
945 void
946 md_number_to_imm (buf, val, nbytes, fixP, seg_type)
947 unsigned char *buf;
948 unsigned int val;
949 int nbytes;
950 fixS *fixP;
951 int seg_type;
952 {
953 if (seg_type != N_TEXT || fixP->fx_r_type == NO_RELOC)
954 {
955 switch (nbytes)
956 {
957 case 4:
958 *buf++ = val >> 24;
959 *buf++ = val >> 16;
960 case 2:
961 *buf++ = val >> 8;
962 case 1:
963 *buf = val;
964 break;
965
966 default:
967 abort ();
968 }
969 return;
970 }
971
972 switch (fixP->fx_r_type)
973 {
974 case RELOC_IW16:
975 buf[2] = val >> 8;
976 buf[3] = val;
977 break;
978
979 case RELOC_LO16:
980 buf[0] = val >> 8;
981 buf[1] = val;
982 break;
983
984 case RELOC_HI16:
985 buf[0] = val >> 24;
986 buf[1] = val >> 16;
987 break;
988
989 case RELOC_PC16:
990 val += 4;
991 buf[0] = val >> 10;
992 buf[1] = val >> 2;
993 break;
994
995 case RELOC_PC26:
996 val += 4;
997 buf[0] |= (val >> 26) & 0x03;
998 buf[1] = val >> 18;
999 buf[2] = val >> 10;
1000 buf[3] = val >> 2;
1001 break;
1002
1003 case RELOC_32:
1004 buf[0] = val >> 24;
1005 buf[1] = val >> 16;
1006 buf[2] = val >> 8;
1007 buf[3] = val;
1008 break;
1009
1010 default:
1011 as_fatal ("Bad relocation type");
1012 break;
1013 }
1014 }
1015
1016 void
1017 md_number_to_disp (buf, val, nbytes)
1018 char *buf;
1019 int val;
1020 int nbytes;
1021 {
1022 as_fatal ("md_number_to_disp not defined");
1023 md_number_to_chars (buf, val, nbytes);
1024 }
1025
1026 void
1027 md_number_to_field (buf, val, nbytes)
1028 char *buf;
1029 int val;
1030 int nbytes;
1031 {
1032 as_fatal ("md_number_to_field not defined");
1033 md_number_to_chars (buf, val, nbytes);
1034 }
1035
1036 #define MAX_LITTLENUMS 6
1037
1038 /* Turn a string in input_line_pointer into a floating point constant of type
1039 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
1040 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
1041 */
1042 char *
1043 md_atof (type, litP, sizeP)
1044 char type;
1045 char *litP;
1046 int *sizeP;
1047 {
1048 int prec;
1049 LITTLENUM_TYPE words[MAX_LITTLENUMS];
1050 LITTLENUM_TYPE *wordP;
1051 char *t;
1052 char *atof_ieee ();
1053
1054 switch (type)
1055 {
1056 case 'f':
1057 case 'F':
1058 case 's':
1059 case 'S':
1060 prec = 2;
1061 break;
1062
1063 case 'd':
1064 case 'D':
1065 case 'r':
1066 case 'R':
1067 prec = 4;
1068 break;
1069
1070 case 'x':
1071 case 'X':
1072 prec = 6;
1073 break;
1074
1075 case 'p':
1076 case 'P':
1077 prec = 6;
1078 break;
1079
1080 default:
1081 *sizeP=0;
1082 return "Bad call to MD_ATOF()";
1083 }
1084 t=atof_ieee (input_line_pointer, type, words);
1085 if (t)
1086 input_line_pointer=t;
1087
1088 *sizeP=prec * sizeof (LITTLENUM_TYPE);
1089 for (wordP=words;prec--;)
1090 {
1091 md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
1092 litP+=sizeof (LITTLENUM_TYPE);
1093 }
1094 return ""; /* Someone should teach Dean about null pointers */
1095 }
1096
1097 int md_short_jump_size = 4;
1098
1099 void
1100 md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
1101 char *ptr;
1102 long from_addr, to_addr;
1103 fragS *frag;
1104 symbolS *to_symbol;
1105 {
1106 ptr[0] = 0xc0; ptr[1] = 0x00; ptr[2] = 0x00; ptr[3] = 0x00;
1107 fix_new (frag,
1108 ptr - frag->fr_literal,
1109 4,
1110 to_symbol,
1111 (symbolS *) 0,
1112 (long int) 0,
1113 0,
1114 RELOC_PC26); /* Botch: Shouldn't this be RELOC_PC16? */
1115 }
1116
1117 int md_long_jump_size = 4;
1118
1119 void
1120 md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
1121 char *ptr;
1122 long from_addr, to_addr;
1123 fragS *frag;
1124 symbolS *to_symbol;
1125 {
1126 ptr[0] = 0xc0; ptr[1] = 0x00; ptr[2] = 0x00; ptr[3] = 0x00;
1127 fix_new (frag,
1128 ptr - frag->fr_literal,
1129 4,
1130 to_symbol,
1131 (symbolS *) 0,
1132 (long int) 0,
1133 0,
1134 RELOC_PC26);
1135 }
1136
1137 int
1138 md_estimate_size_before_relax (fragP, segment_type)
1139 fragS *fragP;
1140 int segment_type;
1141 {
1142 as_fatal ("Relaxation should never occur");
1143 }
1144
1145 const relax_typeS md_relax_table[] = {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 if (fixP->fx_r_type >= NO_RELOC) {
1176 fprintf (stderr, "fixP->fx_r_type = %d\n", fixP->fx_r_type);
1177 abort ();
1178 }
1179
1180 if ((symbolP = fixP->fx_addsy) != NULL) {
1181 ri.r_address = fixP->fx_frag->fr_address +
1182 fixP->fx_where - segment_address_in_file;
1183 if ((symbolP->sy_type & N_TYPE) == N_UNDF) {
1184 ri.r_extern = 1;
1185 ri.r_symbolnum = symbolP->sy_number;
1186 } else {
1187 ri.r_extern = 0;
1188 ri.r_symbolnum = symbolP->sy_type & N_TYPE;
1189 }
1190 if (symbolP && symbolP->sy_frag) {
1191 ri.r_addend = symbolP->sy_frag->fr_address;
1192 }
1193 ri.r_type = fixP->fx_r_type;
1194 if (fixP->fx_pcrel) {
1195 /* ri.r_addend -= fixP->fx_where; */
1196 ri.r_addend -= ri.r_address;
1197 } else {
1198 ri.r_addend = fixP->fx_addnumber;
1199 }
1200
1201 /* md_ri_to_chars ((char *) &ri, ri); */
1202 append (&next_object_file_charP, (char *)& ri, sizeof (ri));
1203 }
1204 }
1205 return;
1206 }
1207
1208 static void
1209 s_bss()
1210 {
1211 char *name;
1212 char c;
1213 char *p;
1214 int temp, bss_align = 1;
1215 symbolS *symbolP;
1216 extern const char is_end_of_line [256];
1217
1218 name = input_line_pointer;
1219 c = get_symbol_end();
1220 p = input_line_pointer;
1221 *p = c;
1222 SKIP_WHITESPACE();
1223 if ( * input_line_pointer != ',' )
1224 {
1225 as_warn("Expected comma after name");
1226 ignore_rest_of_line();
1227 return;
1228 }
1229 input_line_pointer ++;
1230 if ((temp = get_absolute_expression()) < 0)
1231 {
1232 as_warn("BSS length (%d.) <0! Ignored.", temp);
1233 ignore_rest_of_line();
1234 return;
1235 }
1236 *p = 0;
1237 symbolP = symbol_find_or_make(name);
1238 *p = c;
1239 if (*input_line_pointer == ',')
1240 {
1241 input_line_pointer++;
1242 bss_align = get_absolute_expression();
1243 while (local_bss_counter % bss_align != 0)
1244 local_bss_counter++;
1245 }
1246
1247 if (symbolP->sy_other == 0
1248 && symbolP->sy_desc == 0
1249 && ((symbolP->sy_type == N_BSS
1250 && symbolP->sy_value == local_bss_counter)
1251 || ((symbolP->sy_type & N_TYPE) == N_UNDF
1252 && symbolP->sy_value == 0)))
1253 {
1254 symbolP->sy_value = local_bss_counter;
1255 symbolP->sy_type = N_BSS;
1256 symbolP->sy_frag = & bss_address_frag;
1257 local_bss_counter += temp;
1258 }
1259 else
1260 {
1261 as_warn( "Ignoring attempt to re-define symbol from %d. to %d.",
1262 symbolP->sy_value, local_bss_counter );
1263 }
1264 while (!is_end_of_line[*input_line_pointer])
1265 {
1266 input_line_pointer++;
1267 }
1268
1269 return;
1270 }
This page took 0.054853 seconds and 4 git commands to generate.