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