2001-07-01 Ben Elliston <bje@redhat.com>
[deliverable/binutils-gdb.git] / gas / config / tc-m88k.c
CommitLineData
252b5132
RH
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.
f7e42eb4
NC
4 Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1999,
5 2000
252b5132
RH
6 Free Software Foundation, Inc.
7
8This file is part of GAS, the GNU Assembler.
9
10GAS is free software; you can redistribute it and/or modify
11it under the terms of the GNU General Public License as published by
12the Free Software Foundation; either version 2, or (at your option)
13any later version.
14
15GAS is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with GAS; see the file COPYING. If not, write to the Free
22Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2302111-1307, USA. */
24
25#include <ctype.h>
26#include "as.h"
27#include "subsegs.h"
28#include "m88k-opcode.h"
29
30struct field_val_assoc
31{
32 char *name;
33 unsigned val;
34};
35
36struct field_val_assoc cr_regs[] =
37{
38 {"PID", 0},
39 {"PSR", 1},
40 {"EPSR", 2},
41 {"SSBR", 3},
42 {"SXIP", 4},
43 {"SNIP", 5},
44 {"SFIP", 6},
45 {"VBR", 7},
46 {"DMT0", 8},
47 {"DMD0", 9},
48 {"DMA0", 10},
49 {"DMT1", 11},
50 {"DMD1", 12},
51 {"DMA1", 13},
52 {"DMT2", 14},
53 {"DMD2", 15},
54 {"DMA2", 16},
55 {"SR0", 17},
56 {"SR1", 18},
57 {"SR2", 19},
58 {"SR3", 20},
59
60 {NULL, 0},
61};
62
63struct field_val_assoc fcr_regs[] =
64{
65 {"FPECR", 0},
66 {"FPHS1", 1},
67 {"FPLS1", 2},
68 {"FPHS2", 3},
69 {"FPLS2", 4},
70 {"FPPT", 5},
71 {"FPRH", 6},
72 {"FPRL", 7},
73 {"FPIT", 8},
74
75 {"FPSR", 62},
76 {"FPCR", 63},
77
78 {NULL, 0},
79};
80
81struct field_val_assoc cmpslot[] =
82{
83/* Integer Floating point */
84 {"nc", 0},
85 {"cp", 1},
86 {"eq", 2},
87 {"ne", 3},
88 {"gt", 4},
89 {"le", 5},
90 {"lt", 6},
91 {"ge", 7},
92 {"hi", 8}, {"ou", 8},
93 {"ls", 9}, {"ib", 9},
94 {"lo", 10}, {"in", 10},
95 {"hs", 11}, {"ob", 11},
96 {"be", 12}, {"ue", 12},
97 {"nb", 13}, {"lg", 13},
98 {"he", 14}, {"ug", 14},
99 {"nh", 15}, {"ule", 15},
100 {"ul", 16},
101 {"uge", 17},
102
103 {NULL, 0},
104};
105
106struct field_val_assoc cndmsk[] =
107{
108 {"gt0", 1},
109 {"eq0", 2},
110 {"ge0", 3},
111 {"lt0", 12},
112 {"ne0", 13},
113 {"le0", 14},
114
115 {NULL, 0},
116};
117
118struct m88k_insn
119{
120 unsigned long opcode;
121 expressionS exp;
122 enum reloc_type reloc;
123};
124
125static char *get_bf PARAMS ((char *param, unsigned *valp));
126static char *get_cmp PARAMS ((char *param, unsigned *valp));
127static char *get_cnd PARAMS ((char *param, unsigned *valp));
128static char *get_cr PARAMS ((char *param, unsigned *regnop));
129static char *get_fcr PARAMS ((char *param, unsigned *regnop));
130static char *get_imm16 PARAMS ((char *param, struct m88k_insn *insn));
131static char *get_o6 PARAMS ((char *param, unsigned *valp));
bd59b34f 132static char *get_reg PARAMS ((char *param, unsigned *regnop, int reg_prefix));
252b5132
RH
133static char *get_vec9 PARAMS ((char *param, unsigned *valp));
134static char *getval PARAMS ((char *param, unsigned int *valp));
135
136static char *get_pcr PARAMS ((char *param, struct m88k_insn *insn,
137 enum reloc_type reloc));
138
139static int calcop PARAMS ((struct m88k_opcode *format,
140 char *param, struct m88k_insn *insn));
141
252b5132
RH
142extern char *myname;
143static struct hash_control *op_hash = NULL;
144
145/* These bits should be turned off in the first address of every segment */
146int md_seg_align = 7;
147
148/* These chars start a comment anywhere in a source file (except inside
453520d7 149 another comment. */
252b5132
RH
150const char comment_chars[] = ";";
151
82efde3a 152/* These chars only start a comment at the beginning of a line. */
252b5132
RH
153const char line_comment_chars[] = "#";
154
155const char line_separator_chars[] = "";
156
157/* Chars that can be used to separate mant from exp in floating point nums */
158const char EXP_CHARS[] = "eE";
159
160/* Chars that mean this number is a floating point constant */
161/* as in 0f123.456 */
162/* or 0H1.234E-12 (see exp chars above) */
163const char FLT_CHARS[] = "dDfF";
164
165extern void float_cons (), cons (), s_globl (), s_space (),
166 s_set (), s_lcomm ();
167
168const pseudo_typeS md_pseudo_table[] =
169{
170 {"align", s_align_bytes, 4},
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_lcomm, 1},
177 {"string", stringer, 0},
178 {"word", cons, 4},
179 /* Force set to be treated as an instruction. */
180 {"set", NULL, 0},
181 {".set", s_set, 0},
a181d81e 182 {NULL, NULL, 0}
252b5132
RH
183};
184
185void
186md_begin ()
187{
188 const char *retval = NULL;
189 unsigned int i = 0;
190
453520d7 191 /* Initialize hash table. */
252b5132
RH
192 op_hash = hash_new ();
193
252b5132
RH
194 while (*m88k_opcodes[i].name)
195 {
196 char *name = m88k_opcodes[i].name;
197
453520d7 198 /* Hash each mnemonic and record its position. */
252b5132
RH
199 retval = hash_insert (op_hash, name, &m88k_opcodes[i]);
200
201 if (retval != NULL)
202 as_fatal (_("Can't hash instruction '%s':%s"),
203 m88k_opcodes[i].name, retval);
204
453520d7 205 /* Skip to next unique mnemonic or end of list. */
252b5132
RH
206 for (i++; !strcmp (m88k_opcodes[i].name, name); i++)
207 ;
208 }
209}
210\f
211CONST char *md_shortopts = "";
212struct option md_longopts[] = {
213 {NULL, no_argument, NULL, 0}
214};
bc805888 215size_t md_longopts_size = sizeof (md_longopts);
252b5132
RH
216
217int
218md_parse_option (c, arg)
e21e484e
BE
219 int c ATTRIBUTE_UNUSED;
220 char *arg ATTRIBUTE_UNUSED;
252b5132
RH
221{
222 return 0;
223}
224
225void
226md_show_usage (stream)
e21e484e 227 FILE *stream ATTRIBUTE_UNUSED;
252b5132
RH
228{
229}
230\f
231void
232md_assemble (op)
233 char *op;
234{
235 char *param, *thisfrag;
236 char c;
237 struct m88k_opcode *format;
238 struct m88k_insn insn;
239
240 assert (op);
241
453520d7 242 /* Skip over instruction to find parameters. */
252b5132
RH
243 for (param = op; *param != 0 && !isspace (*param); param++)
244 ;
245 c = *param;
246 *param++ = '\0';
247
453520d7 248 /* Try to find the instruction in the hash table. */
252b5132
RH
249 if ((format = (struct m88k_opcode *) hash_find (op_hash, op)) == NULL)
250 {
251 as_bad (_("Invalid mnemonic '%s'"), op);
252 return;
253 }
254
453520d7 255 /* Try parsing this instruction into insn. */
252b5132
RH
256 insn.exp.X_add_symbol = 0;
257 insn.exp.X_op_symbol = 0;
258 insn.exp.X_add_number = 0;
259 insn.exp.X_op = O_illegal;
260 insn.reloc = NO_RELOC;
261
262 while (!calcop (format, param, &insn))
263 {
453520d7 264 /* If it doesn't parse try the next instruction. */
252b5132
RH
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
453520d7 274 /* Grow the current frag and plop in the opcode. */
252b5132
RH
275 thisfrag = frag_more (4);
276 md_number_to_chars (thisfrag, insn.opcode, 4);
277
453520d7 278 /* If this instruction requires labels mark it for later. */
252b5132
RH
279 switch (insn.reloc)
280 {
281 case NO_RELOC:
282 break;
283
284 case RELOC_LO16:
285 case RELOC_HI16:
286 fix_new_exp (frag_now,
287 thisfrag - frag_now->fr_literal + 2,
288 2,
289 &insn.exp,
290 0,
291 insn.reloc);
292 break;
293
294 case RELOC_IW16:
295 fix_new_exp (frag_now,
296 thisfrag - frag_now->fr_literal,
297 4,
298 &insn.exp,
299 0,
300 insn.reloc);
301 break;
302
303 case RELOC_PC16:
304 fix_new_exp (frag_now,
305 thisfrag - frag_now->fr_literal + 2,
306 2,
307 &insn.exp,
308 1,
309 insn.reloc);
310 break;
311
312 case RELOC_PC26:
313 fix_new_exp (frag_now,
314 thisfrag - frag_now->fr_literal,
315 4,
316 &insn.exp,
317 1,
318 insn.reloc);
319 break;
320
321 default:
322 as_fatal (_("Unknown relocation type"));
323 break;
324 }
325}
326
327static int
328calcop (format, param, insn)
329 struct m88k_opcode *format;
330 char *param;
331 struct m88k_insn *insn;
332{
333 char *fmt = format->op_spec;
334 int f;
335 unsigned val;
336 unsigned opcode;
bd59b34f 337 int reg_prefix = 'r';
252b5132
RH
338
339 insn->opcode = format->opcode;
340 opcode = 0;
341
342 for (;;)
343 {
344 if (param == 0)
345 return 0;
346 f = *fmt++;
347 switch (f)
348 {
349 case 0:
350 insn->opcode |= opcode;
351 return (*param == 0 || *param == '\n');
352
353 default:
354 if (f != *param++)
355 return 0;
356 break;
357
358 case 'd':
359 param = get_reg (param, &val, reg_prefix);
360 reg_prefix = 'r';
361 opcode |= val << 21;
362 break;
363
364 case 'o':
365 param = get_o6 (param, &val);
366 opcode |= ((val >> 2) << 7);
367 break;
368
369 case 'x':
370 reg_prefix = 'x';
371 break;
372
373 case '1':
374 param = get_reg (param, &val, reg_prefix);
375 reg_prefix = 'r';
376 opcode |= val << 16;
377 break;
378
379 case '2':
380 param = get_reg (param, &val, reg_prefix);
381 reg_prefix = 'r';
382 opcode |= val;
383 break;
384
385 case '3':
386 param = get_reg (param, &val, 'r');
387 opcode |= (val << 16) | val;
388 break;
389
390 case 'I':
391 param = get_imm16 (param, insn);
392 break;
393
394 case 'b':
395 param = get_bf (param, &val);
396 opcode |= val;
397 break;
398
399 case 'p':
400 param = get_pcr (param, insn, RELOC_PC16);
401 break;
402
403 case 'P':
404 param = get_pcr (param, insn, RELOC_PC26);
405 break;
406
407 case 'B':
408 param = get_cmp (param, &val);
409 opcode |= val;
410 break;
411
412 case 'M':
413 param = get_cnd (param, &val);
414 opcode |= val;
415 break;
416
417 case 'c':
418 param = get_cr (param, &val);
419 opcode |= val << 5;
420 break;
421
422 case 'f':
423 param = get_fcr (param, &val);
424 opcode |= val << 5;
425 break;
426
427 case 'V':
428 param = get_vec9 (param, &val);
429 opcode |= val;
430 break;
431
432 case '?':
433 /* Having this here repeats the warning somtimes.
434 But can't we stand that? */
435 as_warn (_("Use of obsolete instruction"));
436 break;
437 }
438 }
439}
440
441static char *
442match_name (param, assoc_tab, valp)
443 char *param;
444 struct field_val_assoc *assoc_tab;
445 unsigned *valp;
446{
447 int i;
448 char *name;
449 int name_len;
450
451 for (i = 0;; i++)
452 {
453 name = assoc_tab[i].name;
454 if (name == NULL)
455 return NULL;
456 name_len = strlen (name);
457 if (!strncmp (param, name, name_len))
458 {
459 *valp = assoc_tab[i].val;
460 return param + name_len;
461 }
462 }
463}
464
465static char *
466get_reg (param, regnop, reg_prefix)
467 char *param;
468 unsigned *regnop;
bd59b34f 469 int reg_prefix;
252b5132 470{
bd59b34f 471 unsigned c;
252b5132
RH
472 unsigned regno;
473
474 c = *param++;
475 if (c == reg_prefix)
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
512static char *
513get_imm16 (param, insn)
514 char *param;
515 struct m88k_insn *insn;
516{
517 enum reloc_type reloc = NO_RELOC;
518 unsigned int val;
519 char *save_ptr;
520
521 if (!strncmp (param, "hi16", 4) && !isalnum (param[4]))
522 {
523 reloc = RELOC_HI16;
524 param += 4;
525 }
526 else if (!strncmp (param, "lo16", 4) && !isalnum (param[4]))
527 {
528 reloc = RELOC_LO16;
529 param += 4;
530 }
531 else if (!strncmp (param, "iw16", 4) && !isalnum (param[4]))
532 {
533 reloc = RELOC_IW16;
534 param += 4;
535 }
536
537 save_ptr = input_line_pointer;
538 input_line_pointer = param;
539 expression (&insn->exp);
540 param = input_line_pointer;
541 input_line_pointer = save_ptr;
542
543 val = insn->exp.X_add_number;
544
545 if (insn->exp.X_op == O_constant)
546 {
547 /* Insert the value now, and reset reloc to NO_RELOC. */
548 if (reloc == NO_RELOC)
549 {
550 /* Warn about too big expressions if not surrounded by xx16. */
551 if (val > 0xffff)
552 as_warn (_("Expression truncated to 16 bits"));
553 }
554
555 if (reloc == RELOC_HI16)
556 val >>= 16;
557
558 insn->opcode |= val & 0xffff;
559 reloc = NO_RELOC;
560 }
561 else if (reloc == NO_RELOC)
562 /* We accept a symbol even without lo16, hi16, etc, and assume
563 lo16 was intended. */
564 reloc = RELOC_LO16;
565
566 insn->reloc = reloc;
567
568 return param;
569}
570
571static char *
572get_pcr (param, insn, reloc)
573 char *param;
574 struct m88k_insn *insn;
575 enum reloc_type reloc;
576{
577 char *saveptr, *saveparam;
578
579 saveptr = input_line_pointer;
580 input_line_pointer = param;
581
582 expression (&insn->exp);
583
584 saveparam = input_line_pointer;
585 input_line_pointer = saveptr;
586
587 /* Botch: We should relocate now if O_constant. */
588 insn->reloc = reloc;
589
590 return saveparam;
591}
592
593static char *
594get_cmp (param, valp)
595 char *param;
596 unsigned *valp;
597{
598 unsigned int val;
599 char *save_ptr;
600
601 save_ptr = param;
602
603 param = match_name (param, cmpslot, valp);
604 val = *valp;
605
606 if (param == NULL)
607 {
608 param = save_ptr;
609
610 save_ptr = input_line_pointer;
611 input_line_pointer = param;
612 val = get_absolute_expression ();
613 param = input_line_pointer;
614 input_line_pointer = save_ptr;
615
616 if (val >= 32)
617 {
618 as_warn (_("Expression truncated to 5 bits"));
619 val %= 32;
620 }
621 }
622
623 *valp = val << 21;
624 return param;
625}
626
627static char *
628get_cnd (param, valp)
629 char *param;
630 unsigned *valp;
631{
632 unsigned int val;
633
634 if (isdigit (*param))
635 {
636 param = getval (param, &val);
637
638 if (val >= 32)
639 {
640 as_warn (_("Expression truncated to 5 bits"));
641 val %= 32;
642 }
643 }
644 else
645 {
646 if (isupper (*param))
647 *param = tolower (*param);
648
649 if (isupper (param[1]))
650 param[1] = tolower (param[1]);
651
652 param = match_name (param, cndmsk, valp);
653
654 if (param == NULL)
655 return NULL;
656
657 val = *valp;
658 }
659
660 *valp = val << 21;
661 return param;
662}
663
664static char *
665get_bf2 (param, bc)
666 char *param;
667 int bc;
668{
669 int depth = 0;
670 int c;
671
672 for (;;)
673 {
674 c = *param;
675 if (c == 0)
676 return param;
677 else if (c == '(')
678 depth++;
679 else if (c == ')')
680 depth--;
681 else if (c == bc && depth <= 0)
682 return param;
683 param++;
684 }
685}
686
687static char *
688get_bf_offset_expression (param, offsetp)
689 char *param;
690 unsigned *offsetp;
691{
692 unsigned offset;
693
694 if (isalpha (param[0]))
695 {
696 if (isupper (param[0]))
697 param[0] = tolower (param[0]);
698 if (isupper (param[1]))
699 param[1] = tolower (param[1]);
700
701 param = match_name (param, cmpslot, offsetp);
702
703 return param;
704 }
705 else
706 {
707 input_line_pointer = param;
708 offset = get_absolute_expression ();
709 param = input_line_pointer;
710 }
711
712 *offsetp = offset;
713 return param;
714}
715
716static char *
717get_bf (param, valp)
718 char *param;
719 unsigned *valp;
720{
721 unsigned offset = 0;
722 unsigned width = 0;
723 char *xp;
724 char *save_ptr;
725
726 xp = get_bf2 (param, '<');
727
728 save_ptr = input_line_pointer;
729 input_line_pointer = param;
730 if (*xp == 0)
731 {
732 /* We did not find '<'. We have an offset (width implicitly 32). */
733 param = get_bf_offset_expression (param, &offset);
734 input_line_pointer = save_ptr;
735 if (param == NULL)
736 return NULL;
737 }
738 else
739 {
740 *xp++ = 0; /* Overwrite the '<' */
741 param = get_bf2 (xp, '>');
742 if (*param == 0)
743 return NULL;
744 *param++ = 0; /* Overwrite the '>' */
745
746 width = get_absolute_expression ();
747 xp = get_bf_offset_expression (xp, &offset);
748 input_line_pointer = save_ptr;
749
750 if (xp + 1 != param)
751 return NULL;
752 }
753
754 *valp = ((width % 32) << 5) | (offset % 32);
755
756 return param;
757}
758
759static char *
760get_cr (param, regnop)
761 char *param;
762 unsigned *regnop;
763{
764 unsigned regno;
765 unsigned c;
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
803static char *
804get_fcr (param, regnop)
805 char *param;
806 unsigned *regnop;
807{
808 unsigned regno;
809 unsigned c;
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
847static char *
848get_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
869static char *
870get_o6 (param, valp)
871 char *param;
872 unsigned *valp;
873{
874 unsigned val;
875 char *save_ptr;
876
877 save_ptr = input_line_pointer;
878 input_line_pointer = param;
879 val = get_absolute_expression ();
880 param = input_line_pointer;
881 input_line_pointer = save_ptr;
882
883 if (val & 0x3)
884 as_warn (_("Removed lower 2 bits of expression"));
885
886 *valp = val;
887
888 return(param);
889}
890
891#define hexval(z) \
892 (isdigit (z) ? (z) - '0' : \
893 islower (z) ? (z) - 'a' + 10 : \
894 isupper (z) ? (z) - 'A' + 10 : -1)
895
896static char *
897getval (param, valp)
898 char *param;
899 unsigned int *valp;
900{
901 unsigned int val = 0;
bd59b34f 902 unsigned int c;
252b5132
RH
903
904 c = *param++;
905 if (c == '0')
906 {
907 c = *param++;
908 if (c == 'x' || c == 'X')
909 {
910 c = *param++;
911 c = hexval (c);
912 while (c < 16)
913 {
914 val = val * 16 + c;
915 c = *param++;
916 c = hexval (c);
917 }
918 }
919 else
920 {
921 c -= '0';
922 while (c < 8)
923 {
924 val = val * 8 + c;
925 c = *param++ - '0';
926 }
927 }
928 }
929 else
930 {
931 c -= '0';
932 while (c < 10)
933 {
934 val = val * 10 + c;
935 c = *param++ - '0';
936 }
937 }
938
939 *valp = val;
940 return param - 1;
941}
942
943void
944md_number_to_chars (buf, val, nbytes)
945 char *buf;
946 valueT val;
947 int nbytes;
948{
949 number_to_chars_bigendian (buf, val, nbytes);
950}
951
252b5132
RH
952void
953md_number_to_disp (buf, val, nbytes)
954 char *buf;
955 int val;
956 int nbytes;
957{
958 as_fatal (_("md_number_to_disp not defined"));
959 md_number_to_chars (buf, val, nbytes);
960}
961
962void
963md_number_to_field (buf, val, nbytes)
964 char *buf;
965 int val;
966 int nbytes;
967{
968 as_fatal (_("md_number_to_field not defined"));
969 md_number_to_chars (buf, val, nbytes);
970}
971
972#define MAX_LITTLENUMS 6
973
974/* Turn a string in input_line_pointer into a floating point constant of type
975 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
976 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
977 */
978char *
979md_atof (type, litP, sizeP)
980 char type;
981 char *litP;
982 int *sizeP;
983{
984 int prec;
985 LITTLENUM_TYPE words[MAX_LITTLENUMS];
986 LITTLENUM_TYPE *wordP;
987 char *t;
988
989 switch (type)
990 {
991 case 'f':
992 case 'F':
993 case 's':
994 case 'S':
995 prec = 2;
996 break;
997
998 case 'd':
999 case 'D':
1000 case 'r':
1001 case 'R':
1002 prec = 4;
1003 break;
1004
1005 case 'x':
1006 case 'X':
1007 prec = 6;
1008 break;
1009
1010 case 'p':
1011 case 'P':
1012 prec = 6;
1013 break;
1014
1015 default:
1016 *sizeP = 0;
1017 return _("Bad call to MD_ATOF()");
1018 }
1019 t = atof_ieee (input_line_pointer, type, words);
1020 if (t)
1021 input_line_pointer = t;
1022
1023 *sizeP = prec * sizeof (LITTLENUM_TYPE);
1024 for (wordP = words; prec--;)
1025 {
1026 md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
1027 litP += sizeof (LITTLENUM_TYPE);
1028 }
1029 return 0;
1030}
1031
1032int md_short_jump_size = 4;
1033
1034void
1035md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
1036 char *ptr;
e21e484e
BE
1037 addressT from_addr ATTRIBUTE_UNUSED;
1038 addressT to_addr ATTRIBUTE_UNUSED;
252b5132
RH
1039 fragS *frag;
1040 symbolS *to_symbol;
1041{
1042 ptr[0] = (char) 0xc0;
1043 ptr[1] = 0x00;
1044 ptr[2] = 0x00;
1045 ptr[3] = 0x00;
1046 fix_new (frag,
1047 ptr - frag->fr_literal,
1048 4,
1049 to_symbol,
1050 (offsetT) 0,
1051 0,
1052 RELOC_PC26); /* Botch: Shouldn't this be RELOC_PC16? */
1053}
1054
1055int md_long_jump_size = 4;
1056
1057void
1058md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
1059 char *ptr;
e21e484e
BE
1060 addressT from_addr ATTRIBUTE_UNUSED;
1061 addressT to_addr ATTRIBUTE_UNUSED;
252b5132
RH
1062 fragS *frag;
1063 symbolS *to_symbol;
1064{
1065 ptr[0] = (char) 0xc0;
1066 ptr[1] = 0x00;
1067 ptr[2] = 0x00;
1068 ptr[3] = 0x00;
1069 fix_new (frag,
1070 ptr - frag->fr_literal,
1071 4,
1072 to_symbol,
1073 (offsetT) 0,
1074 0,
1075 RELOC_PC26);
1076}
1077
1078int
1079md_estimate_size_before_relax (fragP, segment_type)
e21e484e
BE
1080 fragS *fragP ATTRIBUTE_UNUSED;
1081 segT segment_type ATTRIBUTE_UNUSED;
252b5132
RH
1082{
1083 as_fatal (_("Relaxation should never occur"));
1084 return (-1);
1085}
1086
252b5132
RH
1087#ifdef M88KCOFF
1088
1089/* These functions are needed if we are linking with obj-coffbfd.c.
1090 That file may be replaced by a more BFD oriented version at some
1091 point. If that happens, these functions should be rexamined.
1092
1093 Ian Lance Taylor, Cygnus Support, 13 July 1993. */
1094
1095/* Given a fixS structure (created by a call to fix_new, above),
1096 return the BFD relocation type to use for it. */
1097
1098short
1099tc_coff_fix2rtype (fixp)
1100 fixS *fixp;
1101{
1102 switch (fixp->fx_r_type)
1103 {
1104 case RELOC_LO16:
1105 return R_LVRT16;
1106 case RELOC_HI16:
1107 return R_HVRT16;
1108 case RELOC_PC16:
1109 return R_PCR16L;
1110 case RELOC_PC26:
1111 return R_PCR26L;
1112 case RELOC_32:
1113 return R_VRT32;
1114 case RELOC_IW16:
1115 return R_VRT16;
1116 default:
1117 abort ();
1118 }
1119}
1120
1121/* Apply a fixS to the object file. Since COFF does not use addends
1122 in relocs, the addend is actually stored directly in the object
1123 file itself. */
1124
1125void
1126md_apply_fix (fixp, val)
1127 fixS *fixp;
1128 long val;
1129{
1130 char *buf;
1131
1132 buf = fixp->fx_frag->fr_literal + fixp->fx_where;
1133 fixp->fx_offset = 0;
1134
1135 switch (fixp->fx_r_type)
1136 {
1137 case RELOC_IW16:
1138 fixp->fx_offset = val >> 16;
1139 buf[2] = val >> 8;
1140 buf[3] = val;
1141 break;
1142
1143 case RELOC_LO16:
1144 fixp->fx_offset = val >> 16;
1145 buf[0] = val >> 8;
1146 buf[1] = val;
1147 break;
1148
1149 case RELOC_HI16:
1150 fixp->fx_offset = val >> 16;
1151 buf[0] = val >> 8;
1152 buf[1] = val;
1153 break;
1154
1155 case RELOC_PC16:
1156 buf[0] = val >> 10;
1157 buf[1] = val >> 2;
1158 break;
1159
1160 case RELOC_PC26:
1161 buf[0] |= (val >> 26) & 0x03;
1162 buf[1] = val >> 18;
1163 buf[2] = val >> 10;
1164 buf[3] = val >> 2;
1165 break;
1166
1167 case RELOC_32:
1168 buf[0] = val >> 24;
1169 buf[1] = val >> 16;
1170 buf[2] = val >> 8;
1171 buf[3] = val;
1172 break;
1173
1174 default:
1175 abort ();
1176 }
1177}
1178
1179/* Where a PC relative offset is calculated from. On the m88k they
1180 are calculated from just after the instruction. */
1181
1182long
1183md_pcrel_from (fixp)
1184 fixS *fixp;
1185{
1186 switch (fixp->fx_r_type)
1187 {
1188 case RELOC_PC16:
1189 return fixp->fx_frag->fr_address + fixp->fx_where - 2;
1190 case RELOC_PC26:
1191 return fixp->fx_frag->fr_address + fixp->fx_where;
1192 default:
1193 abort ();
1194 }
1195 /*NOTREACHED*/
1196}
1197
0a9ef439 1198/* Fill in rs_align_code fragments. */
252b5132 1199
0a9ef439
RH
1200void
1201m88k_handle_align (fragp)
1202 fragS *fragp;
252b5132 1203{
0a9ef439
RH
1204 static const unsigned char nop_pattern[] = { 0xf4, 0x00, 0x58, 0x00 };
1205
1206 int bytes;
1207 char *p;
1208
1209 if (fragp->fr_type != rs_align_code)
1210 return;
1211
1212 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
1213 p = fragp->fr_literal + fragp->fr_fix;
1214
1215 if (bytes & 3)
252b5132 1216 {
0a9ef439
RH
1217 int fix = bytes & 3;
1218 memset (p, 0, fix);
1219 p += fix;
1220 bytes -= fix;
1221 fragp->fr_fix += fix;
252b5132 1222 }
0a9ef439
RH
1223
1224 memcpy (p, nop_pattern, 4);
1225 fragp->fr_var = 4;
252b5132
RH
1226}
1227
1228#endif /* M88KCOFF */
This page took 0.126468 seconds and 4 git commands to generate.