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