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