* no more relocation_info structures. We now squirt directly from
[deliverable/binutils-gdb.git] / gas / config / tc-sparc.c
1 /* tc-sparc.c -- Assemble for the SPARC
2 Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
3
4 This file is part of GAS, the GNU Assembler.
5
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 /* static const char rcsid[] = "$Id$"; */
21
22 #include <stdio.h>
23 #include <ctype.h>
24
25 #include "as.h"
26
27 /* careful, this file includes data *declarations* */
28 #include "sparc-opcode.h"
29
30 void md_begin();
31 void md_end();
32 void md_number_to_chars();
33 void md_assemble();
34 char *md_atof();
35 void md_convert_frag();
36 void md_create_short_jump();
37 void md_create_long_jump();
38 int md_estimate_size_before_relax();
39 void md_ri_to_chars();
40 symbolS *md_undefined_symbol();
41 static void sparc_ip();
42
43 static enum sparc_architecture current_architecture = v6;
44 static int architecture_requested = 0;
45 static int warn_on_bump = 0;
46
47 const relax_typeS md_relax_table[] = {
48 0 };
49
50 /* handle of the OPCODE hash table */
51 static struct hash_control *op_hash = NULL;
52
53 static void s_seg(), s_proc(), s_data1(), s_reserve(), s_common();
54 extern void s_globl(), s_long(), s_short(), s_space(), cons();
55 extern void s_align_bytes(), s_ignore();
56
57 const pseudo_typeS md_pseudo_table[] = {
58 { "align", s_align_bytes, 0 }, /* Defaulting is invalid (0) */
59 { "common", s_common, 0 },
60 { "global", s_globl, 0 },
61 { "half", cons, 2 },
62 { "optim", s_ignore, 0 },
63 { "proc", s_proc, 0 },
64 { "reserve", s_reserve, 0 },
65 { "seg", s_seg, 0 },
66 { "skip", s_space, 0 },
67 { "word", cons, 4 },
68 { NULL, 0, 0 },
69 };
70
71 const int md_short_jump_size = 4;
72 const int md_long_jump_size = 4;
73 const int md_reloc_size = 12; /* Size of relocation record */
74
75 /* This array holds the chars that always start a comment. If the
76 pre-processor is disabled, these aren't very useful */
77 const char comment_chars[] = "!"; /* JF removed '|' from comment_chars */
78
79 /* This array holds the chars that only start a comment at the beginning of
80 a line. If the line seems to have the form '# 123 filename'
81 .line and .file directives will appear in the pre-processed output */
82 /* Note that input_file.c hand checks for '#' at the beginning of the
83 first line of the input file. This is because the compiler outputs
84 #NO_APP at the beginning of its output. */
85 /* Also note that comments started like this one will always
86 work if '/' isn't otherwise defined. */
87 const char line_comment_chars[] = "#";
88
89 /* Chars that can be used to separate mant from exp in floating point nums */
90 const char EXP_CHARS[] = "eE";
91
92 /* Chars that mean this number is a floating point constant */
93 /* As in 0f12.456 */
94 /* or 0d1.2345e12 */
95 const char FLT_CHARS[] = "rRsSfFdDxXpP";
96
97 /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
98 changed in read.c . Ideally it shouldn't have to know about it at all,
99 but nothing is ideal around here.
100 */
101
102 static unsigned char octal[256];
103 #define isoctal(c) octal[c]
104 static unsigned char toHex[256];
105
106 struct sparc_it {
107 char *error;
108 unsigned long opcode;
109 struct nlist *nlistp;
110 expressionS exp;
111 int pcrel;
112 enum reloc_type reloc;
113 } the_insn, set_insn;
114
115 #ifdef __STDC__
116 #if 0
117 static void print_insn(struct sparc_it *insn);
118 #endif
119 static int getExpression(char *str);
120 #else
121 #if 0
122 static void print_insn();
123 #endif
124 static int getExpression();
125 #endif
126 static char *expr_end;
127 static int special_case;
128
129 /*
130 * Instructions that require wierd handling because they're longer than
131 * 4 bytes.
132 */
133 #define SPECIAL_CASE_SET 1
134 #define SPECIAL_CASE_FDIV 2
135
136 /*
137 * sort of like s_lcomm
138 *
139 */
140 static void s_reserve() {
141 char *name;
142 char c;
143 char *p;
144 int temp;
145 symbolS *symbolP;
146
147 name = input_line_pointer;
148 c = get_symbol_end();
149 p = input_line_pointer;
150 *p = c;
151 SKIP_WHITESPACE();
152 if (* input_line_pointer != ',') {
153 as_bad("Expected comma after name");
154 ignore_rest_of_line();
155 return;
156 }
157 input_line_pointer ++;
158 if ((temp = get_absolute_expression()) < 0) {
159 as_bad("BSS length (%d.) <0! Ignored.", temp);
160 ignore_rest_of_line();
161 return;
162 }
163 *p = 0;
164 symbolP = symbol_find_or_make(name);
165 *p = c;
166 if (strncmp(input_line_pointer, ",\"bss\"", 6) != 0) {
167 as_bad("bad .reserve segment: `%s'", input_line_pointer);
168 return;
169 }
170 input_line_pointer += 6;
171 if (S_GET_OTHER(symbolP) == 0
172 && S_GET_DESC(symbolP) == 0
173 && ((S_GET_TYPE(symbolP) == N_BSS
174 && S_GET_VALUE(symbolP) == local_bss_counter)
175 || !S_IS_DEFINED(symbolP))) {
176 S_SET_VALUE(symbolP, local_bss_counter);
177 S_SET_SEGMENT(symbolP, SEG_BSS);
178 symbolP->sy_frag = & bss_address_frag;
179 local_bss_counter += temp;
180 } else {
181 as_warn("Ignoring attempt to re-define symbol from %d. to %d.",
182 S_GET_VALUE(symbolP), local_bss_counter);
183 }
184 demand_empty_rest_of_line();
185 return;
186 } /* s_reserve() */
187
188 static void s_common() {
189 register char *name;
190 register char c;
191 register char *p;
192 register int temp;
193 register symbolS * symbolP;
194
195 name = input_line_pointer;
196 c = get_symbol_end();
197 /* just after name is now '\0' */
198 p = input_line_pointer;
199 *p = c;
200 SKIP_WHITESPACE();
201 if (* input_line_pointer != ',') {
202 as_bad("Expected comma after symbol-name");
203 ignore_rest_of_line();
204 return;
205 }
206 input_line_pointer ++; /* skip ',' */
207 if ((temp = get_absolute_expression ()) < 0) {
208 as_bad(".COMMon length (%d.) <0! Ignored.", temp);
209 ignore_rest_of_line();
210 return;
211 }
212 *p = 0;
213 symbolP = symbol_find_or_make(name);
214 *p = c;
215 if (S_IS_DEFINED(symbolP)) {
216 as_bad("Ignoring attempt to re-define symbol");
217 ignore_rest_of_line();
218 return;
219 }
220 if (S_GET_VALUE(symbolP) != 0) {
221 if (S_GET_VALUE(symbolP) != temp) {
222 as_warn("Length of .comm \"%s\" is already %d. Not changed to %d.",
223 S_GET_NAME(symbolP), S_GET_VALUE(symbolP), temp);
224 }
225 } else {
226 S_SET_VALUE(symbolP, temp);
227 S_SET_EXTERNAL(symbolP);
228 }
229 know(symbolP->sy_frag == &zero_address_frag);
230 if (strncmp(input_line_pointer, ",\"bss\"", 6) != 0
231 && strncmp(input_line_pointer, ",\"data\"", 7) != 0) {
232 p=input_line_pointer;
233 while(*p && *p!='\n')
234 p++;
235 c= *p;
236 *p='\0';
237 as_bad("bad .common segment: `%s'", input_line_pointer);
238 *p=c;
239 return;
240 }
241 input_line_pointer += 6 + (input_line_pointer[2] == 'd'); /* Skip either */
242 demand_empty_rest_of_line();
243 return;
244 } /* s_common() */
245
246 static void s_seg() {
247
248 if (strncmp(input_line_pointer, "\"text\"", 6) == 0) {
249 input_line_pointer += 6;
250 s_text();
251 return;
252 }
253 if (strncmp(input_line_pointer, "\"data\"", 6) == 0) {
254 input_line_pointer += 6;
255 s_data();
256 return;
257 }
258 if (strncmp(input_line_pointer, "\"data1\"", 7) == 0) {
259 input_line_pointer += 7;
260 s_data1();
261 return;
262 }
263 if (strncmp(input_line_pointer, "\"bss\"", 5) == 0) {
264 input_line_pointer += 5;
265 /* We only support 2 segments -- text and data -- for now, so
266 things in the "bss segment" will have to go into data for now.
267 You can still allocate SEG_BSS stuff with .lcomm or .reserve. */
268 subseg_new(SEG_DATA, 255); /* FIXME-SOMEDAY */
269 return;
270 }
271 as_bad("Unknown segment type");
272 demand_empty_rest_of_line();
273 return;
274 } /* s_seg() */
275
276 static void s_data1() {
277 subseg_new(SEG_DATA, 1);
278 demand_empty_rest_of_line();
279 return;
280 } /* s_data1() */
281
282 static void s_proc() {
283 extern char is_end_of_line[];
284
285 while (!is_end_of_line[*input_line_pointer]) {
286 ++input_line_pointer;
287 }
288 ++input_line_pointer;
289 return;
290 } /* s_proc() */
291
292 /* This function is called once, at assembler startup time. It should
293 set up all the tables, etc. that the MD part of the assembler will need. */
294 void md_begin() {
295 register char *retval = NULL;
296 int lose = 0;
297 register unsigned int i = 0;
298
299 op_hash = hash_new();
300 if (op_hash == NULL)
301 as_fatal("Virtual memory exhausted");
302
303 while (i < NUMOPCODES) {
304 const char *name = sparc_opcodes[i].name;
305 retval = hash_insert(op_hash, name, &sparc_opcodes[i]);
306 if(retval != NULL && *retval != '\0') {
307 fprintf (stderr, "internal error: can't hash `%s': %s\n",
308 sparc_opcodes[i].name, retval);
309 lose = 1;
310 }
311 do
312 {
313 if (sparc_opcodes[i].match & sparc_opcodes[i].lose) {
314 fprintf (stderr, "internal error: losing opcode: `%s' \"%s\"\n",
315 sparc_opcodes[i].name, sparc_opcodes[i].args);
316 lose = 1;
317 }
318 ++i;
319 } while (i < NUMOPCODES
320 && !strcmp(sparc_opcodes[i].name, name));
321 }
322
323 if (lose)
324 as_fatal("Broken assembler. No assembly attempted.");
325
326 for (i = '0'; i < '8'; ++i)
327 octal[i] = 1;
328 for (i = '0'; i <= '9'; ++i)
329 toHex[i] = i - '0';
330 for (i = 'a'; i <= 'f'; ++i)
331 toHex[i] = i + 10 - 'a';
332 for (i = 'A'; i <= 'F'; ++i)
333 toHex[i] = i + 10 - 'A';
334 } /* md_begin() */
335
336 void md_end() {
337 return;
338 } /* md_end() */
339
340 void md_assemble(str)
341 char *str;
342 {
343 char *toP;
344 int rsd;
345
346 know(str);
347 sparc_ip(str);
348
349 /* See if "set" operand is absolute and small; skip sethi if so. */
350 if (special_case == SPECIAL_CASE_SET && the_insn.exp.X_seg == SEG_ABSOLUTE) {
351 if (the_insn.exp.X_add_number >= -(1<<12)
352 && the_insn.exp.X_add_number < (1<<12)) {
353 the_insn.opcode = 0x80102000 /* or %g0,imm,... */
354 | (the_insn.opcode & 0x3E000000) /* dest reg */
355 | (the_insn.exp.X_add_number & 0x1FFF); /* imm */
356 special_case = 0; /* No longer special */
357 the_insn.reloc = NO_RELOC; /* No longer relocated */
358 }
359 }
360
361 toP = frag_more(4);
362 /* put out the opcode */
363 md_number_to_chars(toP, the_insn.opcode, 4);
364
365 /* put out the symbol-dependent stuff */
366 if (the_insn.reloc != NO_RELOC) {
367 fix_new(frag_now, /* which frag */
368 (toP - frag_now->fr_literal), /* where */
369 4, /* size */
370 the_insn.exp.X_add_symbol,
371 the_insn.exp.X_subtract_symbol,
372 the_insn.exp.X_add_number,
373 the_insn.pcrel,
374 the_insn.reloc);
375 }
376 switch (special_case) {
377
378 case SPECIAL_CASE_SET:
379 special_case = 0;
380 assert(the_insn.reloc == RELOC_HI22);
381 /* See if "set" operand has no low-order bits; skip OR if so. */
382 if (the_insn.exp.X_seg == SEG_ABSOLUTE
383 && ((the_insn.exp.X_add_number & 0x3FF) == 0))
384 return;
385 toP = frag_more(4);
386 rsd = (the_insn.opcode >> 25) & 0x1f;
387 the_insn.opcode = 0x80102000 | (rsd << 25) | (rsd << 14);
388 md_number_to_chars(toP, the_insn.opcode, 4);
389 fix_new(frag_now, /* which frag */
390 (toP - frag_now->fr_literal), /* where */
391 4, /* size */
392 the_insn.exp.X_add_symbol,
393 the_insn.exp.X_subtract_symbol,
394 the_insn.exp.X_add_number,
395 the_insn.pcrel,
396 RELOC_LO10);
397 return;
398
399 case SPECIAL_CASE_FDIV:
400 /* According to information leaked from Sun, the "fdiv" instructions
401 on early SPARC machines would produce incorrect results sometimes.
402 The workaround is to add an fmovs of the destination register to
403 itself just after the instruction. This was true on machines
404 with Weitek 1165 float chips, such as the Sun-4/260 and /280. */
405 special_case = 0;
406 assert(the_insn.reloc == NO_RELOC);
407 toP = frag_more(4);
408 rsd = (the_insn.opcode >> 25) & 0x1f;
409 the_insn.opcode = 0x81A00020 | (rsd << 25) | rsd; /* fmovs dest,dest */
410 md_number_to_chars(toP, the_insn.opcode, 4);
411 return;
412
413 case 0:
414 return;
415
416 default:
417 abort();
418 }
419 } /* md_assemble() */
420
421 static void sparc_ip(str)
422 char *str;
423 {
424 char *error_message = "";
425 char *s;
426 const char *args;
427 char c;
428 struct sparc_opcode *insn;
429 char *argsStart;
430 unsigned long opcode;
431 unsigned int mask = 0;
432 int match = 0;
433 int comma = 0;
434
435 for (s = str; islower(*s) || (*s >= '0' && *s <= '3'); ++s)
436 ;
437 switch (*s) {
438
439 case '\0':
440 break;
441
442 case ',':
443 comma = 1;
444
445 /*FALLTHROUGH */
446
447 case ' ':
448 *s++ = '\0';
449 break;
450
451 default:
452 as_bad("Unknown opcode: `%s'", str);
453 exit(1);
454 }
455 if ((insn = (struct sparc_opcode *) hash_find(op_hash, str)) == NULL) {
456 as_bad("Unknown opcode: `%s'", str);
457 return;
458 }
459 if (comma) {
460 *--s = ',';
461 }
462 argsStart = s;
463 for (;;) {
464 opcode = insn->match;
465 bzero(&the_insn, sizeof(the_insn));
466 the_insn.reloc = NO_RELOC;
467
468 /*
469 * Build the opcode, checking as we go to make
470 * sure that the operands match
471 */
472 for (args = insn->args; ; ++args) {
473 switch (*args) {
474
475 case 'M':
476 case 'm':
477 if (strncmp(s, "%asr", 4) == 0) {
478 s += 4;
479
480 if (isdigit(*s)) {
481 long num = 0;
482
483 while (isdigit(*s)) {
484 num = num*10 + *s-'0';
485 ++s;
486 }
487
488 if (num < 16 || 31 < num) {
489 error_message = ": asr number must be between 15 and 31";
490 goto error;
491 } /* out of range */
492
493 opcode |= (*args == 'M' ? RS1(num) : RD(num));
494 continue;
495 } else {
496 error_message = ": expecting %asrN";
497 goto error;
498 } /* if %asr followed by a number. */
499
500 } /* if %asr */
501 break;
502
503 /* start-sanitize-v9 */
504 #ifndef NO_V9
505 case 'I':
506 the_insn.reloc = RELOC_11;
507 goto immediate;
508
509 case 'k':
510 the_insn.reloc = RELOC_WDISP2_14;
511 the_insn.pcrel = 1;
512 goto immediate;
513
514 case 'G':
515 the_insn.reloc = RELOC_WDISP19;
516 the_insn.pcrel = 1;
517 goto immediate;
518
519 case 'N':
520 if (*s == 'p' && s[1] == 'n') {
521 s += 2;
522 continue;
523 }
524 break;
525
526 case 'T':
527 if (*s == 'p' && s[1] == 't') {
528 s += 2;
529 continue;
530 }
531 break;
532
533 case 'Y':
534 if (strncmp(s, "%amr", 4) == 0) {
535 s += 4;
536 continue;
537 }
538 break;
539
540 case 'z':
541 if (*s == ' ') {
542 ++s;
543 }
544 if (strncmp(s, "icc", 3) == 0) {
545 s += 3;
546 continue;
547 }
548 break;
549
550 case 'Z':
551 if (*s == ' ') {
552 ++s;
553 }
554 if (strncmp(s, "xcc", 3) == 0) {
555 s += 3;
556 continue;
557 }
558 break;
559
560 case '6':
561 if (*s == ' ') {
562 ++s;
563 }
564 if (strncmp(s, "fcc0", 4) == 0) {
565 s += 4;
566 continue;
567 }
568 break;
569
570 case '7':
571 if (*s == ' ') {
572 ++s;
573 }
574 if (strncmp(s, "fcc1", 4) == 0) {
575 s += 4;
576 continue;
577 }
578 break;
579
580 case '8':
581 if (*s == ' ') {
582 ++s;
583 }
584 if (strncmp(s, "fcc2", 4) == 0) {
585 s += 4;
586 continue;
587 }
588 break;
589
590 case '9':
591 if (*s == ' ') {
592 ++s;
593 }
594 if (strncmp(s, "fcc3", 4) == 0) {
595 s += 4;
596 continue;
597 }
598 break;
599
600 case 'P':
601 if (strncmp(s, "%pc", 3) == 0) {
602 s += 3;
603 continue;
604 }
605 break;
606
607 case 'E':
608 if (strncmp(s, "%modes", 6) == 0) {
609 s += 6;
610 continue;
611 }
612 break;
613
614 case 'W':
615 if (strncmp(s, "%tick", 5) == 0) {
616 s += 5;
617 continue;
618 }
619 break;
620 #endif /* NO_V9 */
621 /* end-sanitize-v9 */
622
623 case '\0': /* end of args */
624 if (*s == '\0') {
625 match = 1;
626 }
627 break;
628
629 case '+':
630 if (*s == '+') {
631 ++s;
632 continue;
633 }
634 if (*s == '-') {
635 continue;
636 }
637 break;
638
639 case '[': /* these must match exactly */
640 case ']':
641 case ',':
642 case ' ':
643 if (*s++ == *args)
644 continue;
645 break;
646
647 case '#': /* must be at least one digit */
648 if (isdigit(*s++)) {
649 while (isdigit(*s)) {
650 ++s;
651 }
652 continue;
653 }
654 break;
655
656 case 'C': /* coprocessor state register */
657 if (strncmp(s, "%csr", 4) == 0) {
658 s += 4;
659 continue;
660 }
661 break;
662
663 case 'b': /* next operand is a coprocessor register */
664 case 'c':
665 case 'D':
666 if (*s++ == '%' && *s++ == 'c' && isdigit(*s)) {
667 mask = *s++;
668 if (isdigit(*s)) {
669 mask = 10 * (mask - '0') + (*s++ - '0');
670 if (mask >= 32) {
671 break;
672 }
673 } else {
674 mask -= '0';
675 }
676 switch (*args) {
677
678 case 'b':
679 opcode |= mask << 14;
680 continue;
681
682 case 'c':
683 opcode |= mask;
684 continue;
685
686 case 'D':
687 opcode |= mask << 25;
688 continue;
689 }
690 }
691 break;
692
693 case 'r': /* next operand must be a register */
694 case '1':
695 case '2':
696 case 'd':
697 if (*s++ == '%') {
698 switch (c = *s++) {
699
700 case 'f': /* frame pointer */
701 if (*s++ == 'p') {
702 mask = 0x1e;
703 break;
704 }
705 goto error;
706
707 case 'g': /* global register */
708 if (isoctal(c = *s++)) {
709 mask = c - '0';
710 break;
711 }
712 goto error;
713
714 case 'i': /* in register */
715 if (isoctal(c = *s++)) {
716 mask = c - '0' + 24;
717 break;
718 }
719 goto error;
720
721 case 'l': /* local register */
722 if (isoctal(c = *s++)) {
723 mask= (c - '0' + 16) ;
724 break;
725 }
726 goto error;
727
728 case 'o': /* out register */
729 if (isoctal(c = *s++)) {
730 mask= (c - '0' + 8) ;
731 break;
732 }
733 goto error;
734
735 case 's': /* stack pointer */
736 if (*s++ == 'p') {
737 mask= 0xe;
738 break;
739 }
740 goto error;
741
742 case 'r': /* any register */
743 if (!isdigit(c = *s++)) {
744 goto error;
745 }
746 /* FALLTHROUGH */
747 case '0': case '1': case '2': case '3': case '4':
748 case '5': case '6': case '7': case '8': case '9':
749 if (isdigit(*s)) {
750 if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32) {
751 goto error;
752 }
753 } else {
754 c -= '0';
755 }
756 mask= c;
757 break;
758
759 default:
760 goto error;
761 }
762 /*
763 * Got the register, now figure out where
764 * it goes in the opcode.
765 */
766 switch (*args) {
767
768 case '1':
769 opcode |= mask << 14;
770 continue;
771
772 case '2':
773 opcode |= mask;
774 continue;
775
776 case 'd':
777 opcode |= mask << 25;
778 continue;
779
780 case 'r':
781 opcode |= (mask << 25) | (mask << 14);
782 continue;
783 }
784 }
785 break;
786
787 /* start-sanitize-v9 */
788 #ifndef NO_V9
789 case 'j':
790 case 'u':
791 case 'U':
792 #endif /* NO_V9 */
793 /* end-sanitize-v9 */
794 case 'e': /* next operand is a floating point register */
795 case 'v':
796 case 'V':
797
798 case 'f':
799 case 'B':
800 case 'R':
801
802 case 'g':
803 case 'H':
804 case 'J': {
805 char format;
806
807 if (*s++ == '%'
808
809 /* start-sanitize-v9 */
810 #ifndef NO_V9
811 && ((format = *s) == 'f'
812 || *s == 'd'
813 || *s == 'q')
814 #else
815 /* end-sanitize-v9 */
816 && ((format = *s) == 'f')
817
818 /* start-sanitize-v9 */
819 #endif /* NO_V9 */
820 /* end-sanitize-v9 */
821 && isdigit(*++s)) {
822
823
824
825 for (mask = 0; isdigit(*s); ++s) {
826 mask = 10 * mask + (*s - '0');
827 } /* read the number */
828
829 if ((*args == 'u'
830 || *args == 'v'
831 || *args == 'B'
832 || *args == 'H')
833 && (mask & 1)) {
834 break;
835 } /* register must be even numbered */
836
837 if ((*args == 'U'
838 || *args == 'V'
839 || *args == 'R'
840 || *args == 'J')
841 && (mask & 3)) {
842 break;
843 } /* register must be multiple of 4 */
844
845 if (format == 'f') {
846 if (mask >= 32) {
847 error_message = ": There are only 32 f registers; [0-31]";
848 goto error;
849 } /* on error */
850 /* start-sanitize-v9 */
851 #ifndef NO_V9
852 } else {
853 if (format == 'd') {
854 if (mask >= 64) {
855 error_message = ": There are only 32 d registers [0, 2, ... 62].";
856 goto error;
857 } else if (mask & 1) {
858 error_message = ": Only even numbered d registers exist.";
859 goto error;
860 } /* on error */
861
862 } else if (format == 'q') {
863 if (mask >= 64) {
864 error_message =
865 ": There are only 16 q registers [0, 4, ... 60].";
866 goto error;
867 } else if (mask & 3) {
868 error_message =
869 ": Only q registers evenly divisible by four exist.";
870 goto error;
871 } /* on error */
872 } else {
873 know(0);
874 } /* depending on format */
875
876 if (mask >= 32) {
877 mask -= 31;
878 } /* wrap high bit */
879 } /* if not an 'f' register. */
880 #endif /* NO_V9 */
881 /* end-sanitize-v9 */
882 } /* on error */
883
884 switch (*args) {
885 /* start-sanitize-v9 */
886 #ifndef NO_V9
887 case 'j':
888 case 'u':
889 case 'U':
890 opcode |= (mask & 0x1f) << 9;
891 continue;
892 #endif /* NO_V9 */
893 /* end-sanitize-v9 */
894
895 case 'v':
896 case 'V':
897 case 'e':
898 opcode |= RS1(mask);
899 continue;
900
901
902 case 'f':
903 case 'B':
904 case 'R':
905 opcode |= RS2(mask);
906 continue;
907
908 case 'g':
909 case 'H':
910 case 'J':
911 opcode |= RD(mask);
912 continue;
913 } /* pack it in. */
914
915 know(0);
916 break;
917 } /* float arg */
918
919 case 'F':
920 if (strncmp(s, "%fsr", 4) == 0) {
921 s += 4;
922 continue;
923 }
924 break;
925
926 case 'h': /* high 22 bits */
927 the_insn.reloc = RELOC_HI22;
928 goto immediate;
929
930 case 'l': /* 22 bit PC relative immediate */
931 the_insn.reloc = RELOC_WDISP22;
932 the_insn.pcrel = 1;
933 goto immediate;
934
935 case 'L': /* 30 bit immediate */
936 the_insn.reloc = RELOC_WDISP30;
937 the_insn.pcrel = 1;
938 goto immediate;
939
940 case 'i': /* 13 bit immediate */
941 the_insn.reloc = RELOC_BASE13;
942
943 /*FALLTHROUGH */
944
945 immediate:
946 if(*s==' ')
947 s++;
948 if (*s == '%') {
949 if ((c = s[1]) == 'h' && s[2] == 'i') {
950 the_insn.reloc = RELOC_HI22;
951 s+=3;
952 } else if (c == 'l' && s[2] == 'o') {
953 the_insn.reloc = RELOC_LO10;
954 s+=3;
955 /* start-sanitize-v9 */
956 #ifndef NO_V9
957 } else if (c == 'h'
958 && s[2] == 'h'
959 && s[3] == 'i') {
960 the_insn.reloc = RELOC_HHI22;
961 s += 4;
962
963 } else if (c == 'h'
964 && s[2] == 'l'
965 && s[3] == 'o') {
966 the_insn.reloc = RELOC_HLO10;
967 s += 4;
968 #endif /* NO_V9 */
969 /* end-sanitize-v9 */
970 } else
971 break;
972 }
973 /* Note that if the getExpression() fails, we
974 will still have created U entries in the
975 symbol table for the 'symbols' in the input
976 string. Try not to create U symbols for
977 registers, etc. */
978 {
979 /* This stuff checks to see if the
980 expression ends in +%reg If it does,
981 it removes the register from the
982 expression, and re-sets 's' to point
983 to the right place */
984
985 char *s1;
986
987 for(s1=s;*s1 && *s1!=','&& *s1!=']';s1++)
988 ;
989
990 if(s1!=s && isdigit(s1[-1])) {
991 if(s1[-2]=='%' && s1[-3]=='+') {
992 s1-=3;
993 *s1='\0';
994 (void)getExpression(s);
995 *s1='+';
996 s=s1;
997 continue;
998 } else if(strchr("goli0123456789",s1[-2]) && s1[-3]=='%' && s1[-4]=='+') {
999 s1-=4;
1000 *s1='\0';
1001 (void)getExpression(s);
1002 *s1='+';
1003 s=s1;
1004 continue;
1005 }
1006 }
1007 }
1008 (void)getExpression(s);
1009 s = expr_end;
1010 continue;
1011
1012 case 'a':
1013 if (*s++ == 'a') {
1014 opcode |= ANNUL;
1015 continue;
1016 }
1017 break;
1018
1019 case 'A': /* alternate space */
1020 if (isdigit(*s)) {
1021 long num;
1022
1023 num=0;
1024 while (isdigit(*s)) {
1025 num= num*10 + *s-'0';
1026 ++s;
1027 }
1028 opcode |= num<<5;
1029 continue;
1030 }
1031 break;
1032 /* abort(); */
1033
1034 case 'p':
1035 if (strncmp(s, "%psr", 4) == 0) {
1036 s += 4;
1037 continue;
1038 }
1039 break;
1040
1041 case 'q': /* floating point queue */
1042 if (strncmp(s, "%fq", 3) == 0) {
1043 s += 3;
1044 continue;
1045 }
1046 break;
1047
1048 case 'Q': /* coprocessor queue */
1049 if (strncmp(s, "%cq", 3) == 0) {
1050 s += 3;
1051 continue;
1052 }
1053 break;
1054
1055 case 'S':
1056 if (strcmp(str, "set") == 0) {
1057 special_case = SPECIAL_CASE_SET;
1058 continue;
1059 } else if (strncmp(str, "fdiv", 4) == 0) {
1060 special_case = SPECIAL_CASE_FDIV;
1061 continue;
1062 }
1063 break;
1064
1065 case 't':
1066 if (strncmp(s, "%tbr", 4) != 0)
1067 break;
1068 s += 4;
1069 continue;
1070
1071 case 'w':
1072 if (strncmp(s, "%wim", 4) != 0)
1073 break;
1074 s += 4;
1075 continue;
1076
1077 case 'y':
1078 if (strncmp(s, "%y", 2) != 0)
1079 break;
1080 s += 2;
1081 continue;
1082
1083 default:
1084 abort();
1085 } /* switch on arg code */
1086 break;
1087 } /* for each arg that we expect */
1088 error:
1089 if (match == 0) {
1090 /* Args don't match. */
1091 if (((unsigned) (&insn[1] - sparc_opcodes)) < NUMOPCODES
1092 && !strcmp(insn->name, insn[1].name)) {
1093 ++insn;
1094 s = argsStart;
1095 continue;
1096 } else {
1097 as_bad("Illegal operands%s", error_message);
1098 return;
1099 }
1100 } else {
1101 if (insn->architecture > current_architecture) {
1102 if (current_architecture != cypress
1103 && (!architecture_requested || warn_on_bump)) {
1104
1105 if (warn_on_bump) {
1106 as_warn("architecture bumped from \"%s\" to \"%s\" on \"%s\"",
1107 architecture_pname[current_architecture],
1108 architecture_pname[insn->architecture],
1109 str);
1110 } /* if warning */
1111
1112 current_architecture = insn->architecture;
1113 } else {
1114 as_bad("architecture mismatch on \"%s\" (\"%s\"). current architecture is \"%s\"",
1115 str,
1116 architecture_pname[insn->architecture],
1117 architecture_pname[current_architecture]);
1118 return;
1119 } /* if bump ok else error */
1120 } /* if architecture higher */
1121 } /* if no match */
1122
1123 break;
1124 } /* forever looking for a match */
1125
1126 the_insn.opcode = opcode;
1127 return;
1128 } /* sparc_ip() */
1129
1130 static int getExpression(str)
1131 char *str;
1132 {
1133 char *save_in;
1134 segT seg;
1135
1136 save_in = input_line_pointer;
1137 input_line_pointer = str;
1138 switch (seg = expression(&the_insn.exp)) {
1139
1140 case SEG_ABSOLUTE:
1141 case SEG_TEXT:
1142 case SEG_DATA:
1143 case SEG_BSS:
1144 case SEG_UNKNOWN:
1145 case SEG_DIFFERENCE:
1146 case SEG_BIG:
1147 case SEG_ABSENT:
1148 break;
1149
1150 default:
1151 the_insn.error = "bad segment";
1152 expr_end = input_line_pointer;
1153 input_line_pointer=save_in;
1154 return 1;
1155 }
1156 expr_end = input_line_pointer;
1157 input_line_pointer = save_in;
1158 return 0;
1159 } /* getExpression() */
1160
1161
1162 /*
1163 This is identical to the md_atof in m68k.c. I think this is right,
1164 but I'm not sure.
1165
1166 Turn a string in input_line_pointer into a floating point constant of type
1167 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
1168 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
1169 */
1170
1171 /* Equal to MAX_PRECISION in atof-ieee.c */
1172 #define MAX_LITTLENUMS 6
1173
1174 char *md_atof(type,litP,sizeP)
1175 char type;
1176 char *litP;
1177 int *sizeP;
1178 {
1179 int prec;
1180 LITTLENUM_TYPE words[MAX_LITTLENUMS];
1181 LITTLENUM_TYPE *wordP;
1182 char *t;
1183 char *atof_ieee();
1184
1185 switch(type) {
1186
1187 case 'f':
1188 case 'F':
1189 case 's':
1190 case 'S':
1191 prec = 2;
1192 break;
1193
1194 case 'd':
1195 case 'D':
1196 case 'r':
1197 case 'R':
1198 prec = 4;
1199 break;
1200
1201 case 'x':
1202 case 'X':
1203 prec = 6;
1204 break;
1205
1206 case 'p':
1207 case 'P':
1208 prec = 6;
1209 break;
1210
1211 default:
1212 *sizeP=0;
1213 return "Bad call to MD_ATOF()";
1214 }
1215 t=atof_ieee(input_line_pointer,type,words);
1216 if(t)
1217 input_line_pointer=t;
1218 *sizeP=prec * sizeof(LITTLENUM_TYPE);
1219 for(wordP=words;prec--;) {
1220 md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE));
1221 litP+=sizeof(LITTLENUM_TYPE);
1222 }
1223 return ""; /* Someone should teach Dean about null pointers */
1224 } /* md_atof() */
1225
1226 /*
1227 * Write out big-endian.
1228 */
1229 void md_number_to_chars(buf,val,n)
1230 char *buf;
1231 long val;
1232 int n;
1233 {
1234
1235 switch(n) {
1236
1237 case 4:
1238 *buf++ = val >> 24;
1239 *buf++ = val >> 16;
1240 case 2:
1241 *buf++ = val >> 8;
1242 case 1:
1243 *buf = val;
1244 break;
1245
1246 default:
1247 abort();
1248 }
1249 return;
1250 } /* md_number_to_chars() */
1251
1252 /* Apply a fixS to the frags, now that we know the value it ought to
1253 hold. */
1254
1255 void md_apply_fix(fixP, val)
1256 fixS *fixP;
1257 long val;
1258 {
1259 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
1260
1261 assert(fixP->fx_size == 4);
1262 assert(fixP->fx_r_type < NO_RELOC);
1263
1264 fixP->fx_addnumber = val; /* Remember value for emit_reloc */
1265
1266 /*
1267 * This is a hack. There should be a better way to
1268 * handle this.
1269 */
1270 if (fixP->fx_r_type == RELOC_WDISP30 && fixP->fx_addsy) {
1271 val += fixP->fx_where + fixP->fx_frag->fr_address;
1272 }
1273
1274 switch (fixP->fx_r_type) {
1275
1276 case RELOC_32:
1277 buf[0] = 0; /* val >> 24; */
1278 buf[1] = 0; /* val >> 16; */
1279 buf[2] = 0; /* val >> 8; */
1280 buf[3] = 0; /* val; */
1281 break;
1282
1283 #if 0
1284 case RELOC_8: /* These don't seem to ever be needed. */
1285 case RELOC_16:
1286 case RELOC_DISP8:
1287 case RELOC_DISP16:
1288 case RELOC_DISP32:
1289 #endif
1290 case RELOC_WDISP30:
1291 val = (val >>= 2) + 1;
1292 buf[0] |= (val >> 24) & 0x3f;
1293 buf[1]= (val >> 16);
1294 buf[2] = val >> 8;
1295 buf[3] = val;
1296 break;
1297
1298 /* start-sanitize-v9 */
1299 #ifndef NO_V9
1300 case RELOC_11:
1301 if (((val > 0) && (val & ~0x7ff))
1302 || ((val < 0) && (~val & ~0x7ff))) {
1303 as_bad("relocation overflow.");
1304 } /* on overflow */
1305
1306 buf[2] = (val >> 8) & 0x7;
1307 buf[3] = val & 0xff;
1308 break;
1309
1310 case RELOC_WDISP2_14:
1311 if (((val > 0) && (val & ~0x3fffc))
1312 || ((val < 0) && (~val & ~0x3fffc))) {
1313 as_bad("relocation overflow.");
1314 } /* on overflow */
1315
1316 val = (val >>= 2) + 1;
1317 buf[1] |= ((val >> 14) & 0x3) << 3;
1318 buf[2] |= (val >> 8) & 0x3f ;
1319 buf[3] = val & 0xff;
1320 break;
1321
1322 case RELOC_WDISP19:
1323 if (((val > 0) && (val & ~0x1ffffc))
1324 || ((val < 0) && (~val & ~0x1ffffc))) {
1325 as_bad("relocation overflow.");
1326 } /* on overflow */
1327
1328 val = (val >>= 2) + 1;
1329 buf[1] |= (val >> 16) & 0x7;
1330 buf[2] = (val >> 8) & 0xff;
1331 buf[3] = val & 0xff;
1332 break;
1333
1334 case RELOC_HHI22:
1335 val >>= 32;
1336 /* intentional fallthrough */
1337 #endif /* NO_V9 */
1338 /* end-sanitize-v9 */
1339
1340 case RELOC_HI22:
1341 if(!fixP->fx_addsy) {
1342 buf[1] |= (val >> 26) & 0x3f;
1343 buf[2] = val >> 18;
1344 buf[3] = val >> 10;
1345 } else {
1346 buf[2]=0;
1347 buf[3]=0;
1348 }
1349 break;
1350 #if 0
1351 case RELOC_22:
1352 case RELOC_13:
1353 #endif
1354
1355 /* start-sanitize-v9 */
1356 #ifndef NO_V9
1357 case RELOC_HLO10:
1358 val >>= 32;
1359 /* intentional fallthrough */
1360 #endif /* NO_V9 */
1361 /* end-sanitize-v9 */
1362
1363 case RELOC_LO10:
1364 if(!fixP->fx_addsy) {
1365 buf[2] |= (val >> 8) & 0x03;
1366 buf[3] = val;
1367 } else
1368 buf[3]=0;
1369 break;
1370 #if 0
1371 case RELOC_SFA_BASE:
1372 case RELOC_SFA_OFF13:
1373 case RELOC_BASE10:
1374 #endif
1375 case RELOC_BASE13:
1376 buf[2] |= (val >> 8) & 0x1f;
1377 buf[3] = val;
1378 break;
1379
1380 case RELOC_WDISP22:
1381 val = (val >>= 2) + 1;
1382 /* FALLTHROUGH */
1383 case RELOC_BASE22:
1384 buf[1] |= (val >> 16) & 0x3f;
1385 buf[2] = val >> 8;
1386 buf[3] = val;
1387 break;
1388
1389 #if 0
1390 case RELOC_PC10:
1391 case RELOC_PC22:
1392 case RELOC_JMP_TBL:
1393 case RELOC_SEGOFF16:
1394 case RELOC_GLOB_DAT:
1395 case RELOC_JMP_SLOT:
1396 case RELOC_RELATIVE:
1397 #endif
1398
1399 case NO_RELOC:
1400 default:
1401 as_bad("bad relocation type: 0x%02x", fixP->fx_r_type);
1402 break;
1403 }
1404 } /* md_apply_fix() */
1405
1406 /* should never be called for sparc */
1407 void md_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol)
1408 char *ptr;
1409 long from_addr;
1410 long to_addr;
1411 fragS *frag;
1412 symbolS *to_symbol;
1413 {
1414 fprintf(stderr, "sparc_create_short_jmp\n");
1415 abort();
1416 } /* md_create_short_jump() */
1417
1418 /* Translate internal representation of relocation info to target format.
1419
1420 On sparc: first 4 bytes are normal unsigned long address, next three
1421 bytes are index, most sig. byte first. Byte 7 is broken up with
1422 bit 7 as external, bits 6 & 5 unused, and the lower
1423 five bits as relocation type. Next 4 bytes are long addend. */
1424 /* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */
1425 void tc_aout_fix_to_chars(where, fixP, segment_address_in_file)
1426 char *where;
1427 fixS *fixP;
1428 relax_addressT segment_address_in_file;
1429 {
1430 long r_index;
1431 long r_extern;
1432 long r_addend;
1433 long r_address;
1434
1435 know(fixP->fx_addsy);
1436
1437 if ((S_GET_TYPE(fixP->fx_addsy)) == N_UNDF) {
1438 r_extern = 1;
1439 r_index = fixP->fx_addsy->sy_number;
1440 } else {
1441 r_extern = 0;
1442 r_index = S_GET_TYPE(fixP->fx_addsy);
1443 }
1444
1445 /* this is easy */
1446 md_number_to_chars(where,
1447 r_address = fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
1448 4);
1449
1450 /* now the fun stuff */
1451 where[4] = (r_index >> 16) & 0x0ff;
1452 where[5] = (r_index >> 8) & 0x0ff;
1453 where[6] = r_index & 0x0ff;
1454 where[7] = ((r_extern << 7) & 0x80) | (0 & 0x60) | (fixP->fx_r_type & 0x1F);
1455
1456 /* Also easy */
1457 if (fixP->fx_addsy->sy_frag) {
1458 r_addend = fixP->fx_addsy->sy_frag->fr_address;
1459 }
1460
1461 if (fixP->fx_pcrel) {
1462 r_addend -= r_address;
1463 } else {
1464 r_addend = fixP->fx_addnumber;
1465 }
1466
1467 md_number_to_chars(&where[8], r_addend, 4);
1468
1469 return;
1470 } /* tc_aout_fix_to_chars() */
1471
1472 /* should never be called for sparc */
1473 void md_convert_frag(headers, fragP)
1474 object_headers *headers;
1475 register fragS *fragP;
1476 {
1477 fprintf(stderr, "sparc_convert_frag\n");
1478 abort();
1479 } /* md_convert_frag() */
1480
1481 /* should never be called for sparc */
1482 void md_create_long_jump(ptr, from_addr, to_addr, frag, to_symbol)
1483 char *ptr;
1484 long from_addr, to_addr;
1485 fragS *frag;
1486 symbolS *to_symbol;
1487 {
1488 fprintf(stderr, "sparc_create_long_jump\n");
1489 abort();
1490 } /* md_create_long_jump() */
1491
1492 /* should never be called for sparc */
1493 int md_estimate_size_before_relax(fragP, segtype)
1494 fragS *fragP;
1495 segT segtype;
1496 {
1497 fprintf(stderr, "sparc_estimate_size_before_relax\n");
1498 abort();
1499 return 0;
1500 } /* md_estimate_size_before_relax() */
1501
1502 #if 0
1503 /* for debugging only */
1504 static void print_insn(insn)
1505 struct sparc_it *insn;
1506 {
1507 char *Reloc[] = {
1508 "RELOC_8",
1509 "RELOC_16",
1510 "RELOC_32",
1511 "RELOC_DISP8",
1512 "RELOC_DISP16",
1513 "RELOC_DISP32",
1514 "RELOC_WDISP30",
1515 "RELOC_WDISP22",
1516 "RELOC_HI22",
1517 "RELOC_22",
1518 "RELOC_13",
1519 "RELOC_LO10",
1520 "RELOC_SFA_BASE",
1521 "RELOC_SFA_OFF13",
1522 "RELOC_BASE10",
1523 "RELOC_BASE13",
1524 "RELOC_BASE22",
1525 "RELOC_PC10",
1526 "RELOC_PC22",
1527 "RELOC_JMP_TBL",
1528 "RELOC_SEGOFF16",
1529 "RELOC_GLOB_DAT",
1530 "RELOC_JMP_SLOT",
1531 "RELOC_RELATIVE",
1532 "NO_RELOC"
1533 };
1534
1535 if (insn->error) {
1536 fprintf(stderr, "ERROR: %s\n");
1537 }
1538 fprintf(stderr, "opcode=0x%08x\n", insn->opcode);
1539 fprintf(stderr, "reloc = %s\n", Reloc[insn->reloc]);
1540 fprintf(stderr, "exp = {
1541 \n");
1542 fprintf(stderr, "\t\tX_add_symbol = %s\n",
1543 ((insn->exp.X_add_symbol != NULL)
1544 ? ((S_GET_NAME(insn->exp.X_add_symbol) != NULL)
1545 ? S_GET_NAME(insn->exp.X_add_symbol)
1546 : "???")
1547 : "0"));
1548 fprintf(stderr, "\t\tX_sub_symbol = %s\n",
1549 ((insn->exp.X_subtract_symbol != NULL)
1550 ? (S_GET_NAME(insn->exp.X_subtract_symbol)
1551 ? S_GET_NAME(insn->exp.X_subtract_symbol)
1552 : "???")
1553 : "0"));
1554 fprintf(stderr, "\t\tX_add_number = %d\n",
1555 insn->exp.X_add_number);
1556 fprintf(stderr, "}\n");
1557 return;
1558 } /* print_insn() */
1559 #endif
1560
1561 /* Set the hook... */
1562
1563 /* void emit_sparc_reloc();
1564 void (*md_emit_relocations)() = emit_sparc_reloc; */
1565
1566 #ifdef comment
1567
1568 /*
1569 * Sparc/AM29K relocations are completely different, so it needs
1570 * this machine dependent routine to emit them.
1571 */
1572 #if defined(OBJ_AOUT) || defined(OBJ_BOUT)
1573 void emit_sparc_reloc(fixP, segment_address_in_file)
1574 register fixS *fixP;
1575 relax_addressT segment_address_in_file;
1576 {
1577 struct reloc_info_generic ri;
1578 register symbolS *symbolP;
1579 extern char *next_object_file_charP;
1580 /* long add_number; */
1581
1582 bzero((char *) &ri, sizeof(ri));
1583 for (; fixP; fixP = fixP->fx_next) {
1584
1585 if (fixP->fx_r_type >= NO_RELOC) {
1586 fprintf(stderr, "fixP->fx_r_type = %d\n", fixP->fx_r_type);
1587 abort();
1588 }
1589
1590 if ((symbolP = fixP->fx_addsy) != NULL) {
1591 ri.r_address = fixP->fx_frag->fr_address +
1592 fixP->fx_where - segment_address_in_file;
1593 if ((S_GET_TYPE(symbolP)) == N_UNDF) {
1594 ri.r_extern = 1;
1595 ri.r_index = symbolP->sy_number;
1596 } else {
1597 ri.r_extern = 0;
1598 ri.r_index = S_GET_TYPE(symbolP);
1599 }
1600 if (symbolP && symbolP->sy_frag) {
1601 ri.r_addend = symbolP->sy_frag->fr_address;
1602 }
1603 ri.r_type = fixP->fx_r_type;
1604 if (fixP->fx_pcrel) {
1605 /* ri.r_addend -= fixP->fx_where; */
1606 ri.r_addend -= ri.r_address;
1607 } else {
1608 ri.r_addend = fixP->fx_addnumber;
1609 }
1610
1611 md_ri_to_chars(next_object_file_charP, &ri);
1612 next_object_file_charP += md_reloc_size;
1613 }
1614 }
1615 return;
1616 } /* emit_sparc_reloc() */
1617 #endif /* aout or bout */
1618 #endif /* comment */
1619
1620 /*
1621 * md_parse_option
1622 * Invocation line includes a switch not recognized by the base assembler.
1623 * See if it's a processor-specific option. These are:
1624 *
1625 * -bump
1626 * Warn on architecture bumps. See also -A.
1627 *
1628 * -Av6, -Av7, -Acypress, -Av8
1629 * Select the architecture. Instructions or features not
1630 * supported by the selected architecture cause fatal errors.
1631 *
1632 * The default is to start at v6, and bump the architecture up
1633 * whenever an instruction is seen at a higher level.
1634 *
1635 * If -bump is specified, a warning is printing when bumping to
1636 * higher levels.
1637 *
1638 * If an architecture is specified, all instructions must match
1639 * that architecture. Any higher level instructions are flagged
1640 * as errors.
1641 *
1642 * if both an architecture and -bump are specified, the
1643 * architecture starts at the specified level, but bumps are
1644 * warnings.
1645 *
1646 * Note that where cypress specific instructions conflict with
1647 * other instructions, the other instruction is assumed. Nothing
1648 * is upward compatible with cypress. Thus, to get the cypress
1649 * instruction set you MUST -Acypress.
1650 *
1651 */
1652 /* start-sanitize-v9 */
1653 /* There is also a -Av9 architecture option. xoxorich. */
1654 /* end-sanitize-v9 */
1655 int md_parse_option(argP, cntP, vecP)
1656 char **argP;
1657 int *cntP;
1658 char ***vecP;
1659 {
1660 char *p;
1661 const char **arch;
1662
1663 if (!strcmp(*argP,"bump")){
1664 warn_on_bump = 1;
1665
1666 } else if (**argP == 'A'){
1667 p = (*argP) + 1;
1668
1669 for (arch = architecture_pname; *arch != NULL; ++arch){
1670 if (strcmp(p, *arch) == 0){
1671 break;
1672 } /* found a match */
1673 } /* walk the pname table */
1674
1675 if (*arch == NULL){
1676 as_bad("unknown architecture: %s", p);
1677 } else {
1678 current_architecture = (enum sparc_architecture) (arch - architecture_pname);
1679 architecture_requested = 1;
1680 }
1681 } else {
1682 /* Unknown option */
1683 (*argP)++;
1684 return 0;
1685 }
1686 **argP = '\0'; /* Done parsing this switch */
1687 return 1;
1688 } /* md_parse_option() */
1689
1690 /* We have no need to default values of symbols. */
1691
1692 /* ARGSUSED */
1693 symbolS *md_undefined_symbol(name)
1694 char *name;
1695 {
1696 return 0;
1697 } /* md_undefined_symbol() */
1698
1699 /* Parse an operand that is machine-specific.
1700 We just return without modifying the expression if we have nothing
1701 to do. */
1702
1703 /* ARGSUSED */
1704 void md_operand(expressionP)
1705 expressionS *expressionP;
1706 {
1707 } /* md_operand() */
1708
1709 /* Round up a section size to the appropriate boundary. */
1710 long md_section_align (segment, size)
1711 segT segment;
1712 long size;
1713 {
1714 return (size + 7) & ~7; /* Round all sects to multiple of 8 */
1715 } /* md_section_align() */
1716
1717 /* Exactly what point is a PC-relative offset relative TO?
1718 On the sparc, they're relative to the address of the offset, plus
1719 its size. This gets us to the following instruction.
1720 (??? Is this right? FIXME-SOON) */
1721 long md_pcrel_from(fixP)
1722 fixS *fixP;
1723 {
1724 return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
1725 } /* md_pcrel_from() */
1726
1727 /*
1728 * Local Variables:
1729 * comment-column: 0
1730 * fill-column: 131
1731 * End:
1732 */
1733
1734 /* end of tp-sparc.c */
This page took 0.066808 seconds and 5 git commands to generate.