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