* gas/all/gas.exp: Remove a29k and m88k support.
[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 4 Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1999,
ea1562b3 5 2000, 2001, 2002, 2003, 2005
252b5132
RH
6 Free Software Foundation, Inc.
7
ea1562b3 8 This file is part of GAS, the GNU Assembler.
252b5132 9
ea1562b3
NC
10 GAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
252b5132 14
ea1562b3
NC
15 GAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
252b5132 19
ea1562b3
NC
20 You should have received a copy of the GNU General Public License
21 along with GAS; see the file COPYING. If not, write to the Free
4b4da160
NC
22 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
23 02110-1301, USA. */
252b5132 24
252b5132 25#include "as.h"
3882b010 26#include "safe-ctype.h"
252b5132
RH
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{
ea1562b3 83/* Integer Floating point. */
252b5132
RH
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
252b5132
RH
125extern char *myname;
126static struct hash_control *op_hash = NULL;
127
ea1562b3 128/* These bits should be turned off in the first address of every segment. */
252b5132
RH
129int md_seg_align = 7;
130
131/* These chars start a comment anywhere in a source file (except inside
453520d7 132 another comment. */
252b5132
RH
133const char comment_chars[] = ";";
134
82efde3a 135/* These chars only start a comment at the beginning of a line. */
252b5132
RH
136const char line_comment_chars[] = "#";
137
138const char line_separator_chars[] = "";
139
ea1562b3 140/* Chars that can be used to separate mant from exp in floating point nums. */
252b5132
RH
141const char EXP_CHARS[] = "eE";
142
ea1562b3
NC
143/* Chars that mean this number is a floating point constant.
144 as in 0f123.456
145 or 0H1.234E-12 (see exp chars above). */
252b5132
RH
146const char FLT_CHARS[] = "dDfF";
147
252b5132 148void
ea1562b3 149md_begin (void)
252b5132
RH
150{
151 const char *retval = NULL;
152 unsigned int i = 0;
153
453520d7 154 /* Initialize hash table. */
252b5132
RH
155 op_hash = hash_new ();
156
252b5132
RH
157 while (*m88k_opcodes[i].name)
158 {
159 char *name = m88k_opcodes[i].name;
160
453520d7 161 /* Hash each mnemonic and record its position. */
252b5132
RH
162 retval = hash_insert (op_hash, name, &m88k_opcodes[i]);
163
164 if (retval != NULL)
165 as_fatal (_("Can't hash instruction '%s':%s"),
166 m88k_opcodes[i].name, retval);
167
453520d7 168 /* Skip to next unique mnemonic or end of list. */
252b5132
RH
169 for (i++; !strcmp (m88k_opcodes[i].name, name); i++)
170 ;
171 }
172}
173\f
5a38dc70 174const char *md_shortopts = "";
ea1562b3
NC
175struct option md_longopts[] =
176{
252b5132
RH
177 {NULL, no_argument, NULL, 0}
178};
bc805888 179size_t md_longopts_size = sizeof (md_longopts);
252b5132
RH
180
181int
ea1562b3 182md_parse_option (int c ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED)
252b5132
RH
183{
184 return 0;
185}
186
187void
ea1562b3 188md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
252b5132
RH
189{
190}
191\f
ea1562b3
NC
192static char *
193get_o6 (char *param, unsigned *valp)
252b5132 194{
ea1562b3
NC
195 unsigned val;
196 char *save_ptr;
252b5132 197
ea1562b3
NC
198 save_ptr = input_line_pointer;
199 input_line_pointer = param;
200 val = get_absolute_expression ();
201 param = input_line_pointer;
202 input_line_pointer = save_ptr;
252b5132 203
ea1562b3
NC
204 if (val & 0x3)
205 as_warn (_("Removed lower 2 bits of expression"));
252b5132 206
ea1562b3
NC
207 *valp = val;
208
209 return (param);
210}
211
212static char *
213get_vec9 (char *param, unsigned *valp)
214{
215 unsigned val;
216 char *save_ptr;
217
218 save_ptr = input_line_pointer;
219 input_line_pointer = param;
220 val = get_absolute_expression ();
221 param = input_line_pointer;
222 input_line_pointer = save_ptr;
223
224 if (val >= 1 << 9)
225 as_warn (_("Expression truncated to 9 bits"));
226
227 *valp = val % (1 << 9);
228
229 return param;
230}
231
232static char *
233get_bf2 (char *param, int bc)
234{
235 int depth = 0;
236 int c;
237
238 for (;;)
252b5132 239 {
ea1562b3
NC
240 c = *param;
241 if (c == 0)
242 return param;
243 else if (c == '(')
244 depth++;
245 else if (c == ')')
246 depth--;
247 else if (c == bc && depth <= 0)
248 return param;
249 param++;
252b5132 250 }
ea1562b3 251}
252b5132 252
ea1562b3
NC
253static char *
254match_name (char *param,
255 struct field_val_assoc *assoc_tab,
256 unsigned *valp)
257{
258 int i;
259 char *name;
260 int name_len;
252b5132 261
ea1562b3 262 for (i = 0;; i++)
252b5132 263 {
ea1562b3
NC
264 name = assoc_tab[i].name;
265 if (name == NULL)
266 return NULL;
267 name_len = strlen (name);
268 if (!strncmp (param, name, name_len))
252b5132 269 {
ea1562b3
NC
270 *valp = assoc_tab[i].val;
271 return param + name_len;
252b5132
RH
272 }
273 }
ea1562b3 274}
252b5132 275
ea1562b3
NC
276static char *
277get_bf_offset_expression (char *param, unsigned *offsetp)
278{
279 unsigned offset;
252b5132 280
ea1562b3 281 if (ISALPHA (param[0]))
252b5132 282 {
ea1562b3
NC
283 param[0] = TOLOWER (param[0]);
284 param[1] = TOLOWER (param[1]);
252b5132 285
ea1562b3 286 param = match_name (param, cmpslot, offsetp);
252b5132 287
ea1562b3 288 return param;
252b5132 289 }
ea1562b3
NC
290 else
291 {
292 input_line_pointer = param;
293 offset = get_absolute_expression ();
294 param = input_line_pointer;
295 }
296
297 *offsetp = offset;
298 return param;
252b5132
RH
299}
300
ea1562b3
NC
301static char *
302get_bf (char *param, unsigned *valp)
252b5132 303{
ea1562b3
NC
304 unsigned offset = 0;
305 unsigned width = 0;
306 char *xp;
307 char *save_ptr;
252b5132 308
ea1562b3 309 xp = get_bf2 (param, '<');
252b5132 310
ea1562b3
NC
311 save_ptr = input_line_pointer;
312 input_line_pointer = param;
313 if (*xp == 0)
252b5132 314 {
ea1562b3
NC
315 /* We did not find '<'. We have an offset (width implicitly 32). */
316 param = get_bf_offset_expression (param, &offset);
317 input_line_pointer = save_ptr;
318 if (param == NULL)
319 return NULL;
320 }
321 else
322 {
323 *xp++ = 0; /* Overwrite the '<'. */
324 param = get_bf2 (xp, '>');
325 if (*param == 0)
326 return NULL;
327 *param++ = 0; /* Overwrite the '>'. */
252b5132 328
ea1562b3
NC
329 width = get_absolute_expression ();
330 xp = get_bf_offset_expression (xp, &offset);
331 input_line_pointer = save_ptr;
252b5132 332
ea1562b3
NC
333 if (xp + 1 != param)
334 return NULL;
335 }
252b5132 336
ea1562b3 337 *valp = ((width % 32) << 5) | (offset % 32);
252b5132 338
ea1562b3
NC
339 return param;
340}
252b5132 341
ea1562b3
NC
342static char *
343get_cr (char *param, unsigned *regnop)
344{
345 unsigned regno;
346 unsigned c;
252b5132 347
ea1562b3
NC
348 if (!strncmp (param, "cr", 2))
349 {
350 param += 2;
252b5132 351
ea1562b3
NC
352 regno = *param++ - '0';
353 if (regno < 10)
354 {
355 if (regno == 0)
356 {
357 *regnop = 0;
358 return param;
359 }
360 c = *param - '0';
361 if (c < 10)
362 {
363 regno = regno * 10 + c;
364 if (c < 64)
365 {
366 *regnop = regno;
367 return param + 1;
368 }
369 }
370 else
371 {
372 *regnop = regno;
373 return param;
374 }
375 }
376 return NULL;
377 }
252b5132 378
ea1562b3 379 param = match_name (param, cr_regs, regnop);
252b5132 380
ea1562b3
NC
381 return param;
382}
252b5132 383
ea1562b3
NC
384static char *
385get_fcr (char *param, unsigned *regnop)
386{
387 unsigned regno;
388 unsigned c;
252b5132 389
ea1562b3
NC
390 if (!strncmp (param, "fcr", 3))
391 {
392 param += 3;
252b5132 393
ea1562b3
NC
394 regno = *param++ - '0';
395 if (regno < 10)
396 {
397 if (regno == 0)
398 {
399 *regnop = 0;
400 return param;
401 }
402 c = *param - '0';
403 if (c < 10)
404 {
405 regno = regno * 10 + c;
406 if (c < 64)
407 {
408 *regnop = regno;
409 return param + 1;
410 }
411 }
412 else
413 {
414 *regnop = regno;
415 return param;
416 }
417 }
418 return NULL;
419 }
252b5132 420
ea1562b3 421 param = match_name (param, fcr_regs, regnop);
252b5132 422
ea1562b3
NC
423 return param;
424}
252b5132 425
ea1562b3
NC
426#define hexval(z) \
427 (ISDIGIT (z) ? (z) - '0' : \
428 ISLOWER (z) ? (z) - 'a' + 10 : \
429 ISUPPER (z) ? (z) - 'A' + 10 : (unsigned) -1)
252b5132 430
ea1562b3
NC
431static char *
432getval (char *param, unsigned int *valp)
433{
434 unsigned int val = 0;
435 unsigned int c;
252b5132 436
ea1562b3
NC
437 c = *param++;
438 if (c == '0')
439 {
440 c = *param++;
441 if (c == 'x' || c == 'X')
442 {
443 c = *param++;
444 c = hexval (c);
445 while (c < 16)
446 {
447 val = val * 16 + c;
448 c = *param++;
449 c = hexval (c);
450 }
451 }
452 else
453 {
454 c -= '0';
455 while (c < 8)
456 {
457 val = val * 8 + c;
458 c = *param++ - '0';
459 }
460 }
461 }
462 else
463 {
464 c -= '0';
465 while (c < 10)
466 {
467 val = val * 10 + c;
468 c = *param++ - '0';
252b5132
RH
469 }
470 }
ea1562b3
NC
471
472 *valp = val;
473 return param - 1;
252b5132
RH
474}
475
476static char *
ea1562b3 477get_cnd (char *param, unsigned *valp)
252b5132 478{
ea1562b3 479 unsigned int val;
252b5132 480
ea1562b3 481 if (ISDIGIT (*param))
252b5132 482 {
ea1562b3
NC
483 param = getval (param, &val);
484
485 if (val >= 32)
252b5132 486 {
ea1562b3
NC
487 as_warn (_("Expression truncated to 5 bits"));
488 val %= 32;
252b5132
RH
489 }
490 }
ea1562b3
NC
491 else
492 {
493 param[0] = TOLOWER (param[0]);
494 param[1] = TOLOWER (param[1]);
495
496 param = match_name (param, cndmsk, valp);
497
498 if (param == NULL)
499 return NULL;
500
501 val = *valp;
502 }
503
504 *valp = val << 21;
505 return param;
252b5132
RH
506}
507
508static char *
ea1562b3 509get_reg (char *param, unsigned *regnop, unsigned int reg_prefix)
252b5132 510{
bd59b34f 511 unsigned c;
252b5132
RH
512 unsigned regno;
513
514 c = *param++;
515 if (c == reg_prefix)
516 {
517 regno = *param++ - '0';
518 if (regno < 10)
519 {
520 if (regno == 0)
521 {
522 *regnop = 0;
523 return param;
524 }
525 c = *param - '0';
526 if (c < 10)
527 {
528 regno = regno * 10 + c;
529 if (c < 32)
530 {
531 *regnop = regno;
532 return param + 1;
533 }
534 }
535 else
536 {
537 *regnop = regno;
538 return param;
539 }
540 }
541 return NULL;
542 }
543 else if (c == 's' && param[0] == 'p')
544 {
545 *regnop = 31;
546 return param + 1;
547 }
548
549 return 0;
550}
551
552static char *
ea1562b3 553get_imm16 (char *param, struct m88k_insn *insn)
252b5132
RH
554{
555 enum reloc_type reloc = NO_RELOC;
556 unsigned int val;
557 char *save_ptr;
558
3882b010 559 if (!strncmp (param, "hi16", 4) && !ISALNUM (param[4]))
252b5132
RH
560 {
561 reloc = RELOC_HI16;
562 param += 4;
563 }
3882b010 564 else if (!strncmp (param, "lo16", 4) && !ISALNUM (param[4]))
252b5132
RH
565 {
566 reloc = RELOC_LO16;
567 param += 4;
568 }
3882b010 569 else if (!strncmp (param, "iw16", 4) && !ISALNUM (param[4]))
252b5132
RH
570 {
571 reloc = RELOC_IW16;
572 param += 4;
573 }
574
575 save_ptr = input_line_pointer;
576 input_line_pointer = param;
577 expression (&insn->exp);
578 param = input_line_pointer;
579 input_line_pointer = save_ptr;
580
581 val = insn->exp.X_add_number;
582
583 if (insn->exp.X_op == O_constant)
584 {
585 /* Insert the value now, and reset reloc to NO_RELOC. */
586 if (reloc == NO_RELOC)
587 {
588 /* Warn about too big expressions if not surrounded by xx16. */
589 if (val > 0xffff)
590 as_warn (_("Expression truncated to 16 bits"));
591 }
592
593 if (reloc == RELOC_HI16)
594 val >>= 16;
595
596 insn->opcode |= val & 0xffff;
597 reloc = NO_RELOC;
598 }
599 else if (reloc == NO_RELOC)
600 /* We accept a symbol even without lo16, hi16, etc, and assume
601 lo16 was intended. */
602 reloc = RELOC_LO16;
603
604 insn->reloc = reloc;
605
606 return param;
607}
608
609static char *
ea1562b3 610get_pcr (char *param, struct m88k_insn *insn, enum reloc_type reloc)
252b5132
RH
611{
612 char *saveptr, *saveparam;
613
614 saveptr = input_line_pointer;
615 input_line_pointer = param;
616
617 expression (&insn->exp);
618
619 saveparam = input_line_pointer;
620 input_line_pointer = saveptr;
621
622 /* Botch: We should relocate now if O_constant. */
623 insn->reloc = reloc;
624
625 return saveparam;
626}
627
628static char *
ea1562b3 629get_cmp (char *param, unsigned *valp)
252b5132
RH
630{
631 unsigned int val;
632 char *save_ptr;
633
634 save_ptr = param;
635
636 param = match_name (param, cmpslot, valp);
637 val = *valp;
638
639 if (param == NULL)
640 {
641 param = save_ptr;
642
643 save_ptr = input_line_pointer;
644 input_line_pointer = param;
645 val = get_absolute_expression ();
646 param = input_line_pointer;
647 input_line_pointer = save_ptr;
648
649 if (val >= 32)
650 {
651 as_warn (_("Expression truncated to 5 bits"));
652 val %= 32;
653 }
654 }
655
656 *valp = val << 21;
657 return param;
658}
659
ea1562b3
NC
660static int
661calcop (struct m88k_opcode *format,
662 char *param,
663 struct m88k_insn *insn)
252b5132 664{
ea1562b3
NC
665 char *fmt = format->op_spec;
666 int f;
667 unsigned val;
668 unsigned opcode;
669 unsigned int reg_prefix = 'r';
252b5132 670
ea1562b3
NC
671 insn->opcode = format->opcode;
672 opcode = 0;
252b5132
RH
673
674 for (;;)
675 {
ea1562b3
NC
676 if (param == 0)
677 return 0;
678 f = *fmt++;
679 switch (f)
680 {
681 case 0:
682 insn->opcode |= opcode;
683 return (*param == 0 || *param == '\n');
252b5132 684
ea1562b3
NC
685 default:
686 if (f != *param++)
687 return 0;
688 break;
252b5132 689
ea1562b3
NC
690 case 'd':
691 param = get_reg (param, &val, reg_prefix);
692 reg_prefix = 'r';
693 opcode |= val << 21;
694 break;
252b5132 695
ea1562b3
NC
696 case 'o':
697 param = get_o6 (param, &val);
698 opcode |= ((val >> 2) << 7);
699 break;
252b5132 700
ea1562b3
NC
701 case 'x':
702 reg_prefix = 'x';
703 break;
252b5132 704
ea1562b3
NC
705 case '1':
706 param = get_reg (param, &val, reg_prefix);
707 reg_prefix = 'r';
708 opcode |= val << 16;
709 break;
252b5132 710
ea1562b3
NC
711 case '2':
712 param = get_reg (param, &val, reg_prefix);
713 reg_prefix = 'r';
714 opcode |= val;
715 break;
252b5132 716
ea1562b3
NC
717 case '3':
718 param = get_reg (param, &val, 'r');
719 opcode |= (val << 16) | val;
720 break;
252b5132 721
ea1562b3
NC
722 case 'I':
723 param = get_imm16 (param, insn);
724 break;
252b5132 725
ea1562b3
NC
726 case 'b':
727 param = get_bf (param, &val);
728 opcode |= val;
729 break;
252b5132 730
ea1562b3
NC
731 case 'p':
732 param = get_pcr (param, insn, RELOC_PC16);
733 break;
252b5132 734
ea1562b3
NC
735 case 'P':
736 param = get_pcr (param, insn, RELOC_PC26);
737 break;
252b5132 738
ea1562b3
NC
739 case 'B':
740 param = get_cmp (param, &val);
741 opcode |= val;
742 break;
252b5132 743
ea1562b3
NC
744 case 'M':
745 param = get_cnd (param, &val);
746 opcode |= val;
747 break;
252b5132 748
ea1562b3
NC
749 case 'c':
750 param = get_cr (param, &val);
751 opcode |= val << 5;
752 break;
252b5132 753
ea1562b3
NC
754 case 'f':
755 param = get_fcr (param, &val);
756 opcode |= val << 5;
757 break;
252b5132 758
ea1562b3
NC
759 case 'V':
760 param = get_vec9 (param, &val);
761 opcode |= val;
762 break;
763
764 case '?':
765 /* Having this here repeats the warning somtimes.
766 But can't we stand that? */
767 as_warn (_("Use of obsolete instruction"));
768 break;
769 }
770 }
252b5132
RH
771}
772
ea1562b3
NC
773void
774md_assemble (char *op)
252b5132 775{
ea1562b3
NC
776 char *param, *thisfrag;
777 char c;
778 struct m88k_opcode *format;
779 struct m88k_insn insn;
252b5132 780
ea1562b3 781 assert (op);
252b5132 782
ea1562b3
NC
783 /* Skip over instruction to find parameters. */
784 for (param = op; *param != 0 && !ISSPACE (*param); param++)
785 ;
786 c = *param;
787 *param++ = '\0';
252b5132 788
ea1562b3
NC
789 /* Try to find the instruction in the hash table. */
790 if ((format = (struct m88k_opcode *) hash_find (op_hash, op)) == NULL)
791 {
792 as_bad (_("Invalid mnemonic '%s'"), op);
793 return;
794 }
252b5132 795
ea1562b3
NC
796 /* Try parsing this instruction into insn. */
797 insn.exp.X_add_symbol = 0;
798 insn.exp.X_op_symbol = 0;
799 insn.exp.X_add_number = 0;
800 insn.exp.X_op = O_illegal;
801 insn.reloc = NO_RELOC;
252b5132 802
ea1562b3 803 while (!calcop (format, param, &insn))
252b5132 804 {
ea1562b3
NC
805 /* If it doesn't parse try the next instruction. */
806 if (!strcmp (format[0].name, format[1].name))
807 format++;
252b5132
RH
808 else
809 {
ea1562b3
NC
810 as_fatal (_("Parameter syntax error"));
811 return;
252b5132
RH
812 }
813 }
ea1562b3
NC
814
815 /* Grow the current frag and plop in the opcode. */
816 thisfrag = frag_more (4);
817 md_number_to_chars (thisfrag, insn.opcode, 4);
818
819 /* If this instruction requires labels mark it for later. */
820 switch (insn.reloc)
252b5132 821 {
ea1562b3
NC
822 case NO_RELOC:
823 break;
252b5132 824
ea1562b3
NC
825 case RELOC_LO16:
826 case RELOC_HI16:
827 fix_new_exp (frag_now,
828 thisfrag - frag_now->fr_literal + 2,
829 2,
830 &insn.exp,
831 0,
832 insn.reloc);
833 break;
834
835 case RELOC_IW16:
836 fix_new_exp (frag_now,
837 thisfrag - frag_now->fr_literal,
838 4,
839 &insn.exp,
840 0,
841 insn.reloc);
842 break;
843
844 case RELOC_PC16:
845 fix_new_exp (frag_now,
846 thisfrag - frag_now->fr_literal + 2,
847 2,
848 &insn.exp,
849 1,
850 insn.reloc);
851 break;
852
853 case RELOC_PC26:
854 fix_new_exp (frag_now,
855 thisfrag - frag_now->fr_literal,
856 4,
857 &insn.exp,
858 1,
859 insn.reloc);
860 break;
861
862 default:
863 as_fatal (_("Unknown relocation type"));
864 break;
865 }
252b5132
RH
866}
867
868void
ea1562b3 869md_number_to_chars (char *buf, valueT val, int nbytes)
252b5132
RH
870{
871 number_to_chars_bigendian (buf, val, nbytes);
872}
873
252b5132
RH
874#define MAX_LITTLENUMS 6
875
876/* Turn a string in input_line_pointer into a floating point constant of type
877 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
ea1562b3
NC
878 emitted is stored in *sizeP . An error message is returned, or NULL on OK. */
879
252b5132 880char *
ea1562b3 881md_atof (int type, char *litP, int *sizeP)
252b5132
RH
882{
883 int prec;
884 LITTLENUM_TYPE words[MAX_LITTLENUMS];
885 LITTLENUM_TYPE *wordP;
886 char *t;
887
888 switch (type)
889 {
890 case 'f':
891 case 'F':
892 case 's':
893 case 'S':
894 prec = 2;
895 break;
896
897 case 'd':
898 case 'D':
899 case 'r':
900 case 'R':
901 prec = 4;
902 break;
903
904 case 'x':
905 case 'X':
906 prec = 6;
907 break;
908
909 case 'p':
910 case 'P':
911 prec = 6;
912 break;
913
914 default:
915 *sizeP = 0;
916 return _("Bad call to MD_ATOF()");
917 }
918 t = atof_ieee (input_line_pointer, type, words);
919 if (t)
920 input_line_pointer = t;
921
922 *sizeP = prec * sizeof (LITTLENUM_TYPE);
923 for (wordP = words; prec--;)
924 {
925 md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
926 litP += sizeof (LITTLENUM_TYPE);
927 }
928 return 0;
929}
930
931int md_short_jump_size = 4;
932
933void
ea1562b3
NC
934md_create_short_jump (char *ptr,
935 addressT from_addr ATTRIBUTE_UNUSED,
936 addressT to_addr ATTRIBUTE_UNUSED,
937 fragS *frag,
938 symbolS *to_symbol)
252b5132
RH
939{
940 ptr[0] = (char) 0xc0;
941 ptr[1] = 0x00;
942 ptr[2] = 0x00;
943 ptr[3] = 0x00;
944 fix_new (frag,
945 ptr - frag->fr_literal,
946 4,
947 to_symbol,
948 (offsetT) 0,
949 0,
950 RELOC_PC26); /* Botch: Shouldn't this be RELOC_PC16? */
951}
952
953int md_long_jump_size = 4;
954
955void
ea1562b3
NC
956md_create_long_jump (char *ptr,
957 addressT from_addr ATTRIBUTE_UNUSED,
958 addressT to_addr ATTRIBUTE_UNUSED,
959 fragS *frag,
960 symbolS *to_symbol)
252b5132
RH
961{
962 ptr[0] = (char) 0xc0;
963 ptr[1] = 0x00;
964 ptr[2] = 0x00;
965 ptr[3] = 0x00;
966 fix_new (frag,
967 ptr - frag->fr_literal,
968 4,
969 to_symbol,
970 (offsetT) 0,
971 0,
972 RELOC_PC26);
973}
974
975int
ea1562b3
NC
976md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
977 segT segment_type ATTRIBUTE_UNUSED)
252b5132
RH
978{
979 as_fatal (_("Relaxation should never occur"));
ea1562b3 980 return -1;
252b5132
RH
981}
982
252b5132
RH
983#ifdef M88KCOFF
984
985/* These functions are needed if we are linking with obj-coffbfd.c.
986 That file may be replaced by a more BFD oriented version at some
67c1ffbe 987 point. If that happens, these functions should be reexamined.
252b5132
RH
988
989 Ian Lance Taylor, Cygnus Support, 13 July 1993. */
990
991/* Given a fixS structure (created by a call to fix_new, above),
992 return the BFD relocation type to use for it. */
993
994short
ea1562b3 995tc_coff_fix2rtype (fixS *fixp)
252b5132
RH
996{
997 switch (fixp->fx_r_type)
998 {
999 case RELOC_LO16:
1000 return R_LVRT16;
1001 case RELOC_HI16:
1002 return R_HVRT16;
1003 case RELOC_PC16:
1004 return R_PCR16L;
1005 case RELOC_PC26:
1006 return R_PCR26L;
1007 case RELOC_32:
1008 return R_VRT32;
1009 case RELOC_IW16:
1010 return R_VRT16;
1011 default:
1012 abort ();
1013 }
1014}
1015
1016/* Apply a fixS to the object file. Since COFF does not use addends
1017 in relocs, the addend is actually stored directly in the object
1018 file itself. */
1019
1020void
55cf6793 1021md_apply_fix (fixS *fixP, valueT * valP, segT seg ATTRIBUTE_UNUSED)
252b5132 1022{
f021c2a7 1023 long val = * (long *) valP;
252b5132
RH
1024 char *buf;
1025
94f592af
NC
1026 buf = fixP->fx_frag->fr_literal + fixP->fx_where;
1027 fixP->fx_offset = 0;
252b5132 1028
94f592af 1029 switch (fixP->fx_r_type)
252b5132
RH
1030 {
1031 case RELOC_IW16:
94f592af 1032 fixP->fx_offset = val >> 16;
252b5132
RH
1033 buf[2] = val >> 8;
1034 buf[3] = val;
1035 break;
1036
1037 case RELOC_LO16:
94f592af 1038 fixP->fx_offset = val >> 16;
252b5132
RH
1039 buf[0] = val >> 8;
1040 buf[1] = val;
1041 break;
1042
1043 case RELOC_HI16:
94f592af 1044 fixP->fx_offset = val >> 16;
252b5132
RH
1045 buf[0] = val >> 8;
1046 buf[1] = val;
1047 break;
1048
1049 case RELOC_PC16:
1050 buf[0] = val >> 10;
1051 buf[1] = val >> 2;
1052 break;
1053
1054 case RELOC_PC26:
1055 buf[0] |= (val >> 26) & 0x03;
1056 buf[1] = val >> 18;
1057 buf[2] = val >> 10;
1058 buf[3] = val >> 2;
1059 break;
1060
1061 case RELOC_32:
1062 buf[0] = val >> 24;
1063 buf[1] = val >> 16;
1064 buf[2] = val >> 8;
1065 buf[3] = val;
1066 break;
1067
1068 default:
1069 abort ();
1070 }
94f592af
NC
1071
1072 if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
1073 fixP->fx_done = 1;
252b5132
RH
1074}
1075
1076/* Where a PC relative offset is calculated from. On the m88k they
1077 are calculated from just after the instruction. */
1078
1079long
ea1562b3 1080md_pcrel_from (fixS *fixp)
252b5132
RH
1081{
1082 switch (fixp->fx_r_type)
1083 {
1084 case RELOC_PC16:
1085 return fixp->fx_frag->fr_address + fixp->fx_where - 2;
1086 case RELOC_PC26:
1087 return fixp->fx_frag->fr_address + fixp->fx_where;
1088 default:
1089 abort ();
1090 }
252b5132
RH
1091}
1092
0a9ef439 1093/* Fill in rs_align_code fragments. */
252b5132 1094
0a9ef439 1095void
ea1562b3 1096m88k_handle_align (fragS *fragp)
252b5132 1097{
0a9ef439
RH
1098 static const unsigned char nop_pattern[] = { 0xf4, 0x00, 0x58, 0x00 };
1099
1100 int bytes;
1101 char *p;
1102
1103 if (fragp->fr_type != rs_align_code)
1104 return;
1105
1106 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
1107 p = fragp->fr_literal + fragp->fr_fix;
1108
1109 if (bytes & 3)
252b5132 1110 {
0a9ef439
RH
1111 int fix = bytes & 3;
1112 memset (p, 0, fix);
1113 p += fix;
1114 bytes -= fix;
1115 fragp->fr_fix += fix;
252b5132 1116 }
0a9ef439
RH
1117
1118 memcpy (p, nop_pattern, 4);
1119 fragp->fr_var = 4;
252b5132
RH
1120}
1121
1122#endif /* M88KCOFF */
ea1562b3
NC
1123
1124const pseudo_typeS md_pseudo_table[] =
1125{
1126 {"align", s_align_bytes, 4},
1127 {"def", s_set, 0},
1128 {"dfloat", float_cons, 'd'},
1129 {"ffloat", float_cons, 'f'},
1130 {"half", cons, 2},
1131 {"bss", s_lcomm, 1},
1132 {"string", stringer, 0},
1133 {"word", cons, 4},
1134 /* Force set to be treated as an instruction. */
1135 {"set", NULL, 0},
1136 {".set", s_set, 0},
1137 {NULL, NULL, 0}
1138};
This page took 0.368373 seconds and 4 git commands to generate.