source: trunk/binutils/gas/config/tc-m88k.c@ 2562

Last change on this file since 2562 was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

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