More v9 fixes.
[deliverable/binutils-gdb.git] / gas / config / tc-sparc.c
CommitLineData
fecd2382
RP
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
6321e9ea 8 the Free Software Foundation; either version 2, or (at your option)
fecd2382
RP
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
30void md_begin();
31void md_end();
32void md_number_to_chars();
33void md_assemble();
34char *md_atof();
35void md_convert_frag();
36void md_create_short_jump();
37void md_create_long_jump();
38int md_estimate_size_before_relax();
39void md_ri_to_chars();
40symbolS *md_undefined_symbol();
41static void sparc_ip();
42
839df5c3
RP
43static enum sparc_architecture current_architecture = v6;
44static int architecture_requested = 0;
45static int warn_on_bump = 1;
46
fecd2382
RP
47const relax_typeS md_relax_table[] = {
48 0 };
49
50/* handle of the OPCODE hash table */
51static struct hash_control *op_hash = NULL;
52
53static void s_seg(), s_proc(), s_data1(), s_reserve(), s_common();
54extern void s_globl(), s_long(), s_short(), s_space(), cons();
55extern void s_align_bytes(), s_ignore();
56
57const 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
839df5c3
RP
71const int md_short_jump_size = 4;
72const int md_long_jump_size = 4;
73const int md_reloc_size = 12; /* Size of relocation record */
fecd2382
RP
74
75/* This array holds the chars that always start a comment. If the
76 pre-processor is disabled, these aren't very useful */
839df5c3 77const char comment_chars[] = "!"; /* JF removed '|' from comment_chars */
fecd2382
RP
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. */
839df5c3
RP
85/* Also note that comments started like this one will always
86 work if '/' isn't otherwise defined. */
87const char line_comment_chars[] = "#";
fecd2382
RP
88
89/* Chars that can be used to separate mant from exp in floating point nums */
839df5c3 90const char EXP_CHARS[] = "eE";
fecd2382
RP
91
92/* Chars that mean this number is a floating point constant */
93/* As in 0f12.456 */
94/* or 0d1.2345e12 */
839df5c3 95const char FLT_CHARS[] = "rRsSfFdDxXpP";
fecd2382
RP
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
102static unsigned char octal[256];
103#define isoctal(c) octal[c]
104static unsigned char toHex[256];
105
fecd2382
RP
106struct 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
117static void print_insn(struct sparc_it *insn);
118#endif
119static int getExpression(char *str);
120#else
121#if 0
122static void print_insn();
123#endif
124static int getExpression();
125#endif
126static char *expr_end;
127static 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 */
140static 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
188static 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
246static 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
276static void s_data1() {
277 subseg_new(SEG_DATA, 1);
278 demand_empty_rest_of_line();
279 return;
280} /* s_data1() */
281
282static 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. */
294void 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
336void md_end() {
337 return;
338} /* md_end() */
339
340void md_assemble(str)
341char *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
421static void sparc_ip(str)
422char *str;
423{
839df5c3 424 char *error_message = "";
fecd2382
RP
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;
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
839df5c3
RP
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
6321e9ea 503 /* start-sanitize-v9 */
839df5c3 504#ifndef NO_V9
6321e9ea
RP
505 case 'I':
506 the_insn.reloc = RELOC_11;
507 goto immediate;
508
839df5c3 509 case 'k':
6321e9ea 510 the_insn.reloc = RELOC_WDISP2_14;
839df5c3
RP
511 the_insn.pcrel = 1;
512 goto immediate;
513
6321e9ea
RP
514 case 'G':
515 the_insn.reloc = RELOC_WDISP19;
839df5c3
RP
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;
6321e9ea
RP
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;
839df5c3 620#endif /* NO_V9 */
6321e9ea 621 /* end-sanitize-v9 */
839df5c3 622
fecd2382
RP
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
6321e9ea
RP
787 /* start-sanitize-v9 */
788#ifndef NO_V9
789 case 'j':
790#endif /* NO_V9 */
791 /* end-sanitize-v9 */
792 case 'e': /* next operand is a floating point register */
fecd2382
RP
793 case 'f':
794 case 'g':
795 if (*s++ == '%' && *s++ == 'f' && isdigit(*s)) {
796 mask = *s++;
797 if (isdigit(*s)) {
798 mask = 10 * (mask - '0') + (*s++ - '0');
799 if (mask >= 32) {
800 break;
801 }
802 } else {
803 mask -= '0';
804 }
805 switch (*args) {
806
807 case 'e':
6321e9ea 808 opcode |= RS1(mask);
fecd2382
RP
809 continue;
810
811 case 'f':
6321e9ea 812 opcode |= RS2(mask);
fecd2382
RP
813 continue;
814
815 case 'g':
6321e9ea
RP
816 opcode |= RD(mask);
817 continue;
818 /* start-sanitize-v9 */
819#ifndef NO_V9
820 case 'j':
821 opcode |= (mask & 0x1f) << 9;
fecd2382 822 continue;
6321e9ea
RP
823#endif /* NO_V9 */
824 /* end-sanitize-v9 */
fecd2382
RP
825 }
826 }
827 break;
828
829 case 'F':
830 if (strncmp(s, "%fsr", 4) == 0) {
831 s += 4;
832 continue;
833 }
834 break;
835
6321e9ea 836 case 'h': /* high 22 bits */
fecd2382
RP
837 the_insn.reloc = RELOC_HI22;
838 goto immediate;
839
6321e9ea 840 case 'l': /* 22 bit PC relative immediate */
fecd2382
RP
841 the_insn.reloc = RELOC_WDISP22;
842 the_insn.pcrel = 1;
843 goto immediate;
844
6321e9ea 845 case 'L': /* 30 bit immediate */
fecd2382
RP
846 the_insn.reloc = RELOC_WDISP30;
847 the_insn.pcrel = 1;
848 goto immediate;
849
850 case 'i': /* 13 bit immediate */
851 the_insn.reloc = RELOC_BASE13;
852
853 /*FALLTHROUGH */
854
855 immediate:
856 if(*s==' ')
857 s++;
858 if (*s == '%') {
859 if ((c = s[1]) == 'h' && s[2] == 'i') {
860 the_insn.reloc = RELOC_HI22;
861 s+=3;
862 } else if (c == 'l' && s[2] == 'o') {
863 the_insn.reloc = RELOC_LO10;
864 s+=3;
865 } else
866 break;
867 }
868 /* Note that if the getExpression() fails, we will still have
869 created U entries in the symbol table for the 'symbols'
870 in the input string. Try not to create U symbols for
871 registers, etc. */
872 {
873 /* This stuff checks to see if the expression ends
874 in +%reg If it does, it removes the register from
875 the expression, and re-sets 's' to point to the
876 right place */
877
878 char *s1;
879
880 for(s1=s;*s1 && *s1!=','&& *s1!=']';s1++)
881 ;
882
883 if(s1!=s && isdigit(s1[-1])) {
884 if(s1[-2]=='%' && s1[-3]=='+') {
885 s1-=3;
886 *s1='\0';
887 (void)getExpression(s);
888 *s1='+';
889 s=s1;
890 continue;
891 } else if(strchr("goli0123456789",s1[-2]) && s1[-3]=='%' && s1[-4]=='+') {
892 s1-=4;
893 *s1='\0';
894 (void)getExpression(s);
895 *s1='+';
896 s=s1;
897 continue;
898 }
899 }
900 }
901 (void)getExpression(s);
902 s = expr_end;
903 continue;
904
905 case 'a':
906 if (*s++ == 'a') {
907 opcode |= ANNUL;
908 continue;
909 }
910 break;
911
912 case 'A': /* alternate space */
913 if (isdigit(*s)) {
914 long num;
915
916 num=0;
917 while (isdigit(*s)) {
918 num= num*10 + *s-'0';
919 ++s;
920 }
921 opcode |= num<<5;
922 continue;
923 }
924 break;
925 /* abort(); */
926
927 case 'p':
928 if (strncmp(s, "%psr", 4) == 0) {
929 s += 4;
930 continue;
931 }
932 break;
933
934 case 'q': /* floating point queue */
935 if (strncmp(s, "%fq", 3) == 0) {
936 s += 3;
937 continue;
938 }
939 break;
940
941 case 'Q': /* coprocessor queue */
942 if (strncmp(s, "%cq", 3) == 0) {
943 s += 3;
944 continue;
945 }
946 break;
947
948 case 'S':
949 if (strcmp(str, "set") == 0) {
950 special_case = SPECIAL_CASE_SET;
951 continue;
952 } else if (strncmp(str, "fdiv", 4) == 0) {
953 special_case = SPECIAL_CASE_FDIV;
954 continue;
955 }
956 break;
957
958 case 't':
959 if (strncmp(s, "%tbr", 4) != 0)
960 break;
961 s += 4;
962 continue;
963
964 case 'w':
965 if (strncmp(s, "%wim", 4) != 0)
966 break;
967 s += 4;
968 continue;
969
970 case 'y':
971 if (strncmp(s, "%y", 2) != 0)
972 break;
973 s += 2;
974 continue;
975
976 default:
977 abort();
8fb36078 978 } /* switch on arg code */
fecd2382 979 break;
8fb36078 980 } /* for each arg that we expect */
fecd2382
RP
981 error:
982 if (match == 0) {
983 /* Args don't match. */
984 if (((unsigned) (&insn[1] - sparc_opcodes)) < NUMOPCODES
985 && !strcmp(insn->name, insn[1].name)) {
986 ++insn;
987 s = argsStart;
988 continue;
839df5c3
RP
989 } else {
990 as_bad("Illegal operands%s", error_message);
991 return;
fecd2382 992 }
839df5c3
RP
993 } else {
994 if (insn->architecture > current_architecture) {
995 if (current_architecture != cypress
996 && (!architecture_requested || warn_on_bump)) {
997
998 if (warn_on_bump) {
999 as_warn("architecture bumped from \"%s\" to \"%s\" on \"%s\"",
1000 architecture_pname[current_architecture],
1001 architecture_pname[insn->architecture],
1002 str);
1003 } /* if warning */
1004
1005 current_architecture = insn->architecture;
1006 } else {
1007 as_bad("architecture mismatch on \"%s\" (\"%s\"). current architecture is \"%s\"",
1008 str,
1009 architecture_pname[insn->architecture],
1010 architecture_pname[current_architecture]);
1011 return;
1012 } /* if bump ok else error */
1013 } /* if architecture higher */
1014 } /* if no match */
1015
fecd2382 1016 break;
839df5c3
RP
1017 } /* forever looking for a match */
1018
fecd2382
RP
1019 the_insn.opcode = opcode;
1020 return;
1021} /* sparc_ip() */
1022
1023static int getExpression(str)
1024char *str;
1025{
1026 char *save_in;
1027 segT seg;
1028
1029 save_in = input_line_pointer;
1030 input_line_pointer = str;
1031 switch (seg = expression(&the_insn.exp)) {
1032
1033 case SEG_ABSOLUTE:
1034 case SEG_TEXT:
1035 case SEG_DATA:
1036 case SEG_BSS:
1037 case SEG_UNKNOWN:
1038 case SEG_DIFFERENCE:
1039 case SEG_BIG:
1040 case SEG_ABSENT:
1041 break;
1042
1043 default:
1044 the_insn.error = "bad segment";
1045 expr_end = input_line_pointer;
1046 input_line_pointer=save_in;
1047 return 1;
1048 }
1049 expr_end = input_line_pointer;
1050 input_line_pointer = save_in;
1051 return 0;
1052} /* getExpression() */
1053
1054
1055/*
1056 This is identical to the md_atof in m68k.c. I think this is right,
1057 but I'm not sure.
1058
1059 Turn a string in input_line_pointer into a floating point constant of type
1060 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
1061 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
1062 */
1063
1064/* Equal to MAX_PRECISION in atof-ieee.c */
1065#define MAX_LITTLENUMS 6
1066
1067char *md_atof(type,litP,sizeP)
1068char type;
1069char *litP;
1070int *sizeP;
1071{
1072 int prec;
1073 LITTLENUM_TYPE words[MAX_LITTLENUMS];
1074 LITTLENUM_TYPE *wordP;
1075 char *t;
1076 char *atof_ieee();
1077
1078 switch(type) {
1079
1080 case 'f':
1081 case 'F':
1082 case 's':
1083 case 'S':
1084 prec = 2;
1085 break;
1086
1087 case 'd':
1088 case 'D':
1089 case 'r':
1090 case 'R':
1091 prec = 4;
1092 break;
1093
1094 case 'x':
1095 case 'X':
1096 prec = 6;
1097 break;
1098
1099 case 'p':
1100 case 'P':
1101 prec = 6;
1102 break;
1103
1104 default:
1105 *sizeP=0;
1106 return "Bad call to MD_ATOF()";
1107 }
1108 t=atof_ieee(input_line_pointer,type,words);
1109 if(t)
1110 input_line_pointer=t;
1111 *sizeP=prec * sizeof(LITTLENUM_TYPE);
1112 for(wordP=words;prec--;) {
1113 md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE));
1114 litP+=sizeof(LITTLENUM_TYPE);
1115 }
1116 return ""; /* Someone should teach Dean about null pointers */
1117} /* md_atof() */
1118
1119/*
1120 * Write out big-endian.
1121 */
1122void md_number_to_chars(buf,val,n)
1123char *buf;
1124long val;
1125int n;
1126{
1127
1128 switch(n) {
1129
1130 case 4:
1131 *buf++ = val >> 24;
1132 *buf++ = val >> 16;
1133 case 2:
1134 *buf++ = val >> 8;
1135 case 1:
1136 *buf = val;
1137 break;
1138
1139 default:
1140 abort();
1141 }
1142 return;
1143} /* md_number_to_chars() */
1144
1145/* Apply a fixS to the frags, now that we know the value it ought to
1146 hold. */
1147
1148void md_apply_fix(fixP, val)
1149fixS *fixP;
1150long val;
1151{
1152 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
1153
1154 assert(fixP->fx_size == 4);
1155 assert(fixP->fx_r_type < NO_RELOC);
1156
1157 fixP->fx_addnumber = val; /* Remember value for emit_reloc */
1158
1159 /*
1160 * This is a hack. There should be a better way to
1161 * handle this.
1162 */
1163 if (fixP->fx_r_type == RELOC_WDISP30 && fixP->fx_addsy) {
1164 val += fixP->fx_where + fixP->fx_frag->fr_address;
1165 }
1166
1167 switch (fixP->fx_r_type) {
1168
1169 case RELOC_32:
1170 buf[0] = 0; /* val >> 24; */
1171 buf[1] = 0; /* val >> 16; */
1172 buf[2] = 0; /* val >> 8; */
1173 buf[3] = 0; /* val; */
1174 break;
1175
1176#if 0
1177 case RELOC_8: /* These don't seem to ever be needed. */
1178 case RELOC_16:
1179 case RELOC_DISP8:
1180 case RELOC_DISP16:
1181 case RELOC_DISP32:
1182#endif
1183 case RELOC_WDISP30:
1184 val = (val >>= 2) + 1;
1185 buf[0] |= (val >> 24) & 0x3f;
1186 buf[1]= (val >> 16);
1187 buf[2] = val >> 8;
1188 buf[3] = val;
1189 break;
839df5c3 1190
6321e9ea 1191 /* start-sanitize-v9 */
839df5c3 1192#ifndef NO_V9
6321e9ea
RP
1193 case RELOC_11:
1194 if (val & 0x7ff) {
1195 as_bad("relocation overflow");
1196 } /* on overflow */
1197
1198 buf[2] = (val >> 8) & 0x7;
1199 buf[3] = val & 0xff;
1200 break;
1201
1202 case RELOC_WDISP2_14:
1203 if (val & ~0xffff) {
1204 as_bad("relocation overflow.");
1205 } /* on overflow */
1206
839df5c3 1207 val = (val >>= 2) + 1;
6321e9ea 1208 buf[1] |= ((val >> 14) & 0x3) << 3;
839df5c3 1209 buf[2] |= (val >> 8) & 0x3f ;
6321e9ea 1210 buf[3] = val & 0xff;
839df5c3
RP
1211 break;
1212
6321e9ea
RP
1213 case RELOC_WDISP19:
1214 if (val & ~0x7ffff) {
1215 as_bad("relocation overflow.");
1216 } /* on overflow */
1217
839df5c3 1218 val = (val >>= 2) + 1;
6321e9ea
RP
1219 buf[1] |= (val >> 16) & 0x7;
1220 buf[2] = (val >> 8) & 0xff;
1221 buf[3] = val & 0xff;
839df5c3
RP
1222 break;
1223#endif /* NO_V9 */
6321e9ea 1224 /* end-sanitize-v9 */
839df5c3 1225
fecd2382
RP
1226 case RELOC_HI22:
1227 if(!fixP->fx_addsy) {
1228 buf[1] |= (val >> 26) & 0x3f;
1229 buf[2] = val >> 18;
1230 buf[3] = val >> 10;
1231 } else {
1232 buf[2]=0;
1233 buf[3]=0;
1234 }
1235 break;
1236#if 0
1237 case RELOC_22:
1238 case RELOC_13:
1239#endif
1240 case RELOC_LO10:
1241 if(!fixP->fx_addsy) {
1242 buf[2] |= (val >> 8) & 0x03;
1243 buf[3] = val;
1244 } else
1245 buf[3]=0;
1246 break;
1247#if 0
1248 case RELOC_SFA_BASE:
1249 case RELOC_SFA_OFF13:
1250 case RELOC_BASE10:
1251#endif
1252 case RELOC_BASE13:
1253 buf[2] |= (val >> 8) & 0x1f;
1254 buf[3] = val;
1255 break;
1256
1257 case RELOC_WDISP22:
1258 val = (val >>= 2) + 1;
1259 /* FALLTHROUGH */
1260 case RELOC_BASE22:
1261 buf[1] |= (val >> 16) & 0x3f;
1262 buf[2] = val >> 8;
1263 buf[3] = val;
1264 break;
1265
1266#if 0
1267 case RELOC_PC10:
1268 case RELOC_PC22:
1269 case RELOC_JMP_TBL:
1270 case RELOC_SEGOFF16:
1271 case RELOC_GLOB_DAT:
1272 case RELOC_JMP_SLOT:
1273 case RELOC_RELATIVE:
1274#endif
1275
1276 case NO_RELOC:
1277 default:
1278 as_bad("bad relocation type: 0x%02x", fixP->fx_r_type);
1279 break;
1280 }
1281} /* md_apply_fix() */
1282
1283/* should never be called for sparc */
1284void md_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol)
1285char *ptr;
1286long from_addr;
1287long to_addr;
1288fragS *frag;
1289symbolS *to_symbol;
1290{
1291 fprintf(stderr, "sparc_create_short_jmp\n");
1292 abort();
1293} /* md_create_short_jump() */
1294
1295/* Translate internal representation of relocation info to target format.
1296
1297 On sparc: first 4 bytes are normal unsigned long address, next three
1298 bytes are index, most sig. byte first. Byte 7 is broken up with
1299 bit 7 as external, bits 6 & 5 unused, and the lower
1300 five bits as relocation type. Next 4 bytes are long addend. */
1301/* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */
1302void md_ri_to_chars(the_bytes, ri)
1303char *the_bytes;
1304struct reloc_info_generic *ri;
1305{
1306 /* this is easy */
1307 md_number_to_chars(the_bytes, ri->r_address, 4);
1308 /* now the fun stuff */
1309 the_bytes[4] = (ri->r_index >> 16) & 0x0ff;
1310 the_bytes[5] = (ri->r_index >> 8) & 0x0ff;
1311 the_bytes[6] = ri->r_index & 0x0ff;
1312 the_bytes[7] = ((ri->r_extern << 7) & 0x80) | (0 & 0x60) | (ri->r_type & 0x1F);
1313 /* Also easy */
1314 md_number_to_chars(&the_bytes[8], ri->r_addend, 4);
1315} /* md_ri_to_chars() */
1316
1317/* should never be called for sparc */
1318void md_convert_frag(fragP)
1319register fragS *fragP;
1320{
1321 fprintf(stderr, "sparc_convert_frag\n");
1322 abort();
1323} /* md_convert_frag() */
1324
1325/* should never be called for sparc */
1326void md_create_long_jump(ptr, from_addr, to_addr, frag, to_symbol)
1327char *ptr;
1328long from_addr, to_addr;
1329fragS *frag;
1330symbolS *to_symbol;
1331{
1332 fprintf(stderr, "sparc_create_long_jump\n");
1333 abort();
1334} /* md_create_long_jump() */
1335
1336/* should never be called for sparc */
1337int md_estimate_size_before_relax(fragP, segtype)
1338fragS *fragP;
1339segT segtype;
1340{
1341 fprintf(stderr, "sparc_estimate_size_before_relax\n");
1342 abort();
1343 return 0;
1344} /* md_estimate_size_before_relax() */
1345
1346#if 0
1347/* for debugging only */
1348static void print_insn(insn)
1349struct sparc_it *insn;
1350{
1351 char *Reloc[] = {
1352 "RELOC_8",
1353 "RELOC_16",
1354 "RELOC_32",
1355 "RELOC_DISP8",
1356 "RELOC_DISP16",
1357 "RELOC_DISP32",
1358 "RELOC_WDISP30",
1359 "RELOC_WDISP22",
1360 "RELOC_HI22",
1361 "RELOC_22",
1362 "RELOC_13",
1363 "RELOC_LO10",
1364 "RELOC_SFA_BASE",
1365 "RELOC_SFA_OFF13",
1366 "RELOC_BASE10",
1367 "RELOC_BASE13",
1368 "RELOC_BASE22",
1369 "RELOC_PC10",
1370 "RELOC_PC22",
1371 "RELOC_JMP_TBL",
1372 "RELOC_SEGOFF16",
1373 "RELOC_GLOB_DAT",
1374 "RELOC_JMP_SLOT",
1375 "RELOC_RELATIVE",
1376 "NO_RELOC"
1377 };
1378
1379 if (insn->error) {
1380 fprintf(stderr, "ERROR: %s\n");
1381 }
1382 fprintf(stderr, "opcode=0x%08x\n", insn->opcode);
1383 fprintf(stderr, "reloc = %s\n", Reloc[insn->reloc]);
1384 fprintf(stderr, "exp = {
1385\n");
1386 fprintf(stderr, "\t\tX_add_symbol = %s\n",
1387 ((insn->exp.X_add_symbol != NULL)
1388 ? ((S_GET_NAME(insn->exp.X_add_symbol) != NULL)
1389 ? S_GET_NAME(insn->exp.X_add_symbol)
1390 : "???")
1391 : "0"));
1392 fprintf(stderr, "\t\tX_sub_symbol = %s\n",
1393 ((insn->exp.X_subtract_symbol != NULL)
1394 ? (S_GET_NAME(insn->exp.X_subtract_symbol)
1395 ? S_GET_NAME(insn->exp.X_subtract_symbol)
1396 : "???")
1397 : "0"));
1398 fprintf(stderr, "\t\tX_add_number = %d\n",
1399 insn->exp.X_add_number);
1400 fprintf(stderr, "}\n");
1401 return;
1402} /* print_insn() */
1403#endif
1404
1405/* Set the hook... */
1406
1407void emit_sparc_reloc();
1408void (*md_emit_relocations)() = emit_sparc_reloc;
1409
1410/*
1411 * Sparc/AM29K relocations are completely different, so it needs
1412 * this machine dependent routine to emit them.
1413 */
1414#if defined(OBJ_AOUT) || defined(OBJ_BOUT)
1415void emit_sparc_reloc(fixP, segment_address_in_file)
1416register fixS *fixP;
1417relax_addressT segment_address_in_file;
1418{
1419 struct reloc_info_generic ri;
1420 register symbolS *symbolP;
1421 extern char *next_object_file_charP;
1422 /* long add_number; */
1423
1424 bzero((char *) &ri, sizeof(ri));
1425 for (; fixP; fixP = fixP->fx_next) {
1426
1427 if (fixP->fx_r_type >= NO_RELOC) {
1428 fprintf(stderr, "fixP->fx_r_type = %d\n", fixP->fx_r_type);
1429 abort();
1430 }
1431
1432 if ((symbolP = fixP->fx_addsy) != NULL) {
1433 ri.r_address = fixP->fx_frag->fr_address +
1434 fixP->fx_where - segment_address_in_file;
1435 if ((S_GET_TYPE(symbolP)) == N_UNDF) {
1436 ri.r_extern = 1;
1437 ri.r_index = symbolP->sy_number;
1438 } else {
1439 ri.r_extern = 0;
1440 ri.r_index = S_GET_TYPE(symbolP);
1441 }
1442 if (symbolP && symbolP->sy_frag) {
1443 ri.r_addend = symbolP->sy_frag->fr_address;
1444 }
1445 ri.r_type = fixP->fx_r_type;
1446 if (fixP->fx_pcrel) {
1447 /* ri.r_addend -= fixP->fx_where; */
1448 ri.r_addend -= ri.r_address;
1449 } else {
1450 ri.r_addend = fixP->fx_addnumber;
1451 }
1452
1453 md_ri_to_chars(next_object_file_charP, &ri);
1454 next_object_file_charP += md_reloc_size;
1455 }
1456 }
1457 return;
1458} /* emit_sparc_reloc() */
1459#endif /* aout or bout */
1460
839df5c3
RP
1461/*
1462 * md_parse_option
1463 * Invocation line includes a switch not recognized by the base assembler.
1464 * See if it's a processor-specific option. These are:
1465 *
1466 * -bump
1467 * Warn on architecture bumps. See also -A.
1468 *
1469 * -Av6, -Av7, -Acypress, -Av8
839df5c3
RP
1470 * Select the architecture. Instructions or features not
1471 * supported by the selected architecture cause fatal errors.
1472 *
1473 * The default is to start at v6, and bump the architecture up
1474 * whenever an instruction is seen at a higher level.
1475 *
1476 * If -bump is specified, a warning is printing when bumping to
1477 * higher levels.
1478 *
1479 * If an architecture is specified, all instructions must match
1480 * that architecture. Any higher level instructions are flagged
1481 * as errors.
1482 *
1483 * if both an architecture and -bump are specified, the
1484 * architecture starts at the specified level, but bumps are
1485 * warnings.
1486 *
1487 * Note that where cypress specific instructions conflict with
1488 * other instructions, the other instruction is assumed. Nothing
1489 * is upward compatible with cypress. Thus, to get the cypress
1490 * instruction set you MUST -Acypress.
1491 *
1492 */
6321e9ea 1493 /* start-sanitize-v9 */
afe3b668 1494 /* There is also a -Av9 architecture option. xoxorich. */
6321e9ea 1495 /* end-sanitize-v9 */
839df5c3 1496int md_parse_option(argP, cntP, vecP)
fecd2382
RP
1497char **argP;
1498int *cntP;
1499char ***vecP;
1500{
839df5c3
RP
1501 char *p;
1502 const char **arch;
1503
1504 if (!strcmp(*argP,"bump")){
1505 warn_on_bump = 1;
1506
1507 } else if (**argP == 'A'){
1508 p = (*argP) + 1;
1509
1510 for (arch = architecture_pname; *arch != NULL; ++arch){
1511 if (strcmp(p, *arch) == 0){
1512 break;
1513 } /* found a match */
1514 } /* walk the pname table */
1515
1516 if (*arch == NULL){
1517 as_bad("unknown architecture: %s", p);
1518 } else {
1519 current_architecture = (enum sparc_architecture) (arch - architecture_pname);
1520 architecture_requested = 1;
1521 }
1522 } else {
1523 /* Unknown option */
1524 (*argP)++;
1525 return 0;
1526 }
1527 **argP = '\0'; /* Done parsing this switch */
fecd2382
RP
1528 return 1;
1529} /* md_parse_option() */
1530
1531/* We have no need to default values of symbols. */
1532
1533/* ARGSUSED */
1534symbolS *md_undefined_symbol(name)
1535char *name;
1536{
1537 return 0;
1538} /* md_undefined_symbol() */
1539
1540/* Parse an operand that is machine-specific.
1541 We just return without modifying the expression if we have nothing
1542 to do. */
1543
1544/* ARGSUSED */
1545void md_operand(expressionP)
1546expressionS *expressionP;
1547{
1548} /* md_operand() */
1549
1550/* Round up a section size to the appropriate boundary. */
1551long md_section_align (segment, size)
1552segT segment;
1553long size;
1554{
1555 return (size + 7) & ~7; /* Round all sects to multiple of 8 */
1556} /* md_section_align() */
1557
1558/* Exactly what point is a PC-relative offset relative TO?
1559 On the sparc, they're relative to the address of the offset, plus
1560 its size. This gets us to the following instruction.
1561 (??? Is this right? FIXME-SOON) */
1562long md_pcrel_from(fixP)
1563fixS *fixP;
1564{
1565 return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
1566} /* md_pcrel_from() */
1567
1568/*
1569 * Local Variables:
1570 * comment-column: 0
1571 * fill-column: 131
1572 * End:
1573 */
1574
1575/* end of tp-sparc.c */
This page took 0.084769 seconds and 4 git commands to generate.