Update to SPARC Version 9 Draft 1.0.4.
[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 /* start-sanitize-v9 */
347 #ifndef NO_V9
348 struct priv_reg_entry { char *name; int regnum; };
349 struct priv_reg_entry priv_reg_table[] =
350 {
351 { "tpc", 0 },
352 { "tnpc", 1 },
353 { "tstate", 2 },
354 { "tt", 3 },
355 { "tick", 4 },
356 { "tba", 5 },
357 { "pstate", 6 },
358 { "tl", 7 },
359 { "pil", 8 },
360 { "cwp", 9 },
361 { "cansave", 10 },
362 { "canrestore", 11 },
363 { "cleanwin", 12 },
364 { "otherwin", 13 },
365 { "wstate", 14},
366 { "fpq", 15},
367 { "ver", 31 },
368 { "", -1 }, /* end marker */
369 };
370
371 static int cmp_reg_entry (p, q)
372 struct priv_reg_entry *p, *q;
373 {
374 return strcmp (q->name, p->name);
375 }
376 #endif
377 /* end-sanitize-v9 */
378
379 /* This function is called once, at assembler startup time. It should
380 set up all the tables, etc. that the MD part of the assembler will need. */
381 void md_begin() {
382 register char *retval = NULL;
383 int lose = 0;
384 register unsigned int i = 0;
385
386 op_hash = hash_new();
387 if (op_hash == NULL)
388 as_fatal("Virtual memory exhausted");
389
390 while (i < NUMOPCODES) {
391 const char *name = sparc_opcodes[i].name;
392 retval = hash_insert(op_hash, name, &sparc_opcodes[i]);
393 if(retval != NULL && *retval != '\0') {
394 fprintf (stderr, "internal error: can't hash `%s': %s\n",
395 sparc_opcodes[i].name, retval);
396 lose = 1;
397 }
398 do
399 {
400 if (sparc_opcodes[i].match & sparc_opcodes[i].lose) {
401 fprintf (stderr, "internal error: losing opcode: `%s' \"%s\"\n",
402 sparc_opcodes[i].name, sparc_opcodes[i].args);
403 lose = 1;
404 }
405 ++i;
406 } while (i < NUMOPCODES
407 && !strcmp(sparc_opcodes[i].name, name));
408 }
409
410 if (lose)
411 as_fatal("Broken assembler. No assembly attempted.");
412
413 for (i = '0'; i < '8'; ++i)
414 octal[i] = 1;
415 for (i = '0'; i <= '9'; ++i)
416 toHex[i] = i - '0';
417 for (i = 'a'; i <= 'f'; ++i)
418 toHex[i] = i + 10 - 'a';
419 for (i = 'A'; i <= 'F'; ++i)
420 toHex[i] = i + 10 - 'A';
421
422 /* start-sanitize-v9 */
423 #ifndef NO_V9
424 qsort (priv_reg_table, sizeof (priv_reg_table) / sizeof (priv_reg_table[0]),
425 sizeof (priv_reg_table[0]), cmp_reg_entry);
426 #endif
427 /* end-sanitize-v9 */
428 } /* md_begin() */
429
430 void md_end() {
431 return;
432 } /* md_end() */
433
434 void md_assemble(str)
435 char *str;
436 {
437 char *toP;
438 int rsd;
439
440 know(str);
441 sparc_ip(str);
442
443 /* See if "set" operand is absolute and small; skip sethi if so. */
444 if (special_case == SPECIAL_CASE_SET && the_insn.exp.X_seg == SEG_ABSOLUTE) {
445 if (the_insn.exp.X_add_number >= -(1<<12)
446 && the_insn.exp.X_add_number < (1<<12)) {
447 the_insn.opcode = 0x80102000 /* or %g0,imm,... */
448 | (the_insn.opcode & 0x3E000000) /* dest reg */
449 | (the_insn.exp.X_add_number & 0x1FFF); /* imm */
450 special_case = 0; /* No longer special */
451 the_insn.reloc = NO_RELOC; /* No longer relocated */
452 }
453 }
454
455 toP = frag_more(4);
456 /* put out the opcode */
457 md_number_to_chars(toP, the_insn.opcode, 4);
458
459 /* put out the symbol-dependent stuff */
460 if (the_insn.reloc != NO_RELOC) {
461 fix_new(frag_now, /* which frag */
462 (toP - frag_now->fr_literal), /* where */
463 4, /* size */
464 the_insn.exp.X_add_symbol,
465 the_insn.exp.X_subtract_symbol,
466 the_insn.exp.X_add_number,
467 the_insn.pcrel,
468 the_insn.reloc);
469 }
470 switch (special_case) {
471
472 case SPECIAL_CASE_SET:
473 special_case = 0;
474 assert(the_insn.reloc == RELOC_HI22);
475 /* See if "set" operand has no low-order bits; skip OR if so. */
476 if (the_insn.exp.X_seg == SEG_ABSOLUTE
477 && ((the_insn.exp.X_add_number & 0x3FF) == 0))
478 return;
479 toP = frag_more(4);
480 rsd = (the_insn.opcode >> 25) & 0x1f;
481 the_insn.opcode = 0x80102000 | (rsd << 25) | (rsd << 14);
482 md_number_to_chars(toP, the_insn.opcode, 4);
483 fix_new(frag_now, /* which frag */
484 (toP - frag_now->fr_literal), /* where */
485 4, /* size */
486 the_insn.exp.X_add_symbol,
487 the_insn.exp.X_subtract_symbol,
488 the_insn.exp.X_add_number,
489 the_insn.pcrel,
490 RELOC_LO10);
491 return;
492
493 case SPECIAL_CASE_FDIV:
494 /* According to information leaked from Sun, the "fdiv" instructions
495 on early SPARC machines would produce incorrect results sometimes.
496 The workaround is to add an fmovs of the destination register to
497 itself just after the instruction. This was true on machines
498 with Weitek 1165 float chips, such as the Sun-4/260 and /280. */
499 special_case = 0;
500 assert(the_insn.reloc == NO_RELOC);
501 toP = frag_more(4);
502 rsd = (the_insn.opcode >> 25) & 0x1f;
503 the_insn.opcode = 0x81A00020 | (rsd << 25) | rsd; /* fmovs dest,dest */
504 md_number_to_chars(toP, the_insn.opcode, 4);
505 return;
506
507 case 0:
508 return;
509
510 default:
511 as_fatal("failed sanity check.");
512 }
513 } /* md_assemble() */
514
515 static void sparc_ip(str)
516 char *str;
517 {
518 char *error_message = "";
519 char *s;
520 const char *args;
521 char c;
522 struct sparc_opcode *insn;
523 char *argsStart;
524 unsigned long opcode;
525 unsigned int mask = 0;
526 int match = 0;
527 int comma = 0;
528
529 for (s = str; islower(*s) || (*s >= '0' && *s <= '3'); ++s)
530 ;
531 switch (*s) {
532
533 case '\0':
534 break;
535
536 case ',':
537 comma = 1;
538
539 /*FALLTHROUGH */
540
541 case ' ':
542 *s++ = '\0';
543 break;
544
545 default:
546 as_bad("Unknown opcode: `%s'", str);
547 exit(1);
548 }
549 if ((insn = (struct sparc_opcode *) hash_find(op_hash, str)) == NULL) {
550 as_bad("Unknown opcode: `%s'", str);
551 return;
552 }
553 if (comma) {
554 *--s = ',';
555 }
556 argsStart = s;
557 for (;;) {
558 opcode = insn->match;
559 memset(&the_insn, '\0', sizeof(the_insn));
560 the_insn.reloc = NO_RELOC;
561
562 /*
563 * Build the opcode, checking as we go to make
564 * sure that the operands match
565 */
566 for (args = insn->args; ; ++args) {
567 switch (*args) {
568
569 /* start-sanitize-v9 */
570 #ifndef NO_V9
571 case 'K':
572 {
573 /* Load is 0; Store is 1.
574 We compute the mask based on the values
575 we find in S. OK is set set
576 if we see something we don't like. */
577 int ok = 1;
578 int mask = 0;
579 while (ok == 1)
580 {
581 int lo = 0, hi = 0;
582 if (*s == '#')
583 {
584 s += 1;
585 if (! (lo = (s[0] == 'S')))
586 ok = (s[0] == 'L');
587 if (! (hi = (s[1] == 'S')))
588 ok = (s[1] == 'L');
589 mask |= (1 << ((hi<<1) | lo));
590 s += 2;
591 }
592 else
593 {
594 /* Parse a number, somehow. */
595 ok = 0;
596 }
597 if (s[2] != '|')
598 break;
599 }
600 if (! ok)
601 {
602 error_message = "unrecognizable mmask";
603 goto error;
604 }
605 opcode |= SIMM13(mask);
606 continue;
607 }
608
609 case '*':
610 /* Parse a prefetch function. */
611 if (*s == '#')
612 {
613 int prefetch_fcn = 0;
614
615 s += 1;
616 if (! strncmp (s, "n_reads", 7))
617 prefetch_fcn = 0, s += 7;
618 else if (! strncmp (s, "one_read", 8))
619 prefetch_fcn = 1, s += 8;
620 else if (! strncmp (s, "n_writes", 8))
621 prefetch_fcn = 2, s += 8;
622 else if (! strncmp (s, "one_write", 9))
623 prefetch_fcn = 3, s += 9;
624 else if (! strncmp (s, "page", 4))
625 prefetch_fcn = 4, s += 4;
626 else
627 {
628 error_message = "unrecognizable prefetch fucntion";
629 goto error;
630 }
631 }
632 else
633 {
634 /* Parse a number, somehow. */
635 error_message = "unrecognizable prefetch fucntion";
636 goto error;
637 }
638 continue;
639
640 case '!':
641 case '?':
642 /* Parse a privileged register. */
643 if (*s == '%')
644 {
645 struct priv_reg_entry *p = priv_reg_table;
646 int len;
647
648 s += 1;
649 while (p->name[0] > s[0])
650 p++;
651 while (p->name[0] == s[0])
652 {
653 len = strlen (p->name);
654 if (strncmp (p->name, s, len) == 0)
655 break;
656 p++;
657 }
658 if (p->name[0] != s[0])
659 {
660 error_message = "unrecognizable privileged register";
661 goto error;
662 }
663 if (*args == '?')
664 opcode |= (p->regnum << 14);
665 else
666 opcode |= (p->regnum << 25);
667 s += len;
668 continue;
669 }
670 else
671 {
672 error_message = "unrecognizable privileged register";
673 goto error;
674 }
675 #endif
676 /* end-sanitize-v9 */
677
678 case 'M':
679 case 'm':
680 if (strncmp(s, "%asr", 4) == 0) {
681 s += 4;
682
683 if (isdigit(*s)) {
684 long num = 0;
685
686 while (isdigit(*s)) {
687 num = num*10 + *s-'0';
688 ++s;
689 }
690
691 if (num < 16 || 31 < num) {
692 error_message = ": asr number must be between 15 and 31";
693 goto error;
694 } /* out of range */
695
696 opcode |= (*args == 'M' ? RS1(num) : RD(num));
697 continue;
698 } else {
699 error_message = ": expecting %asrN";
700 goto error;
701 } /* if %asr followed by a number. */
702
703 } /* if %asr */
704 break;
705
706 /* start-sanitize-v9 */
707 #ifndef NO_V9
708 case 'I':
709 the_insn.reloc = RELOC_11;
710 goto immediate;
711
712 case 'j':
713 the_insn.reloc = RELOC_10;
714 goto immediate;
715
716 case 'k':
717 the_insn.reloc = RELOC_WDISP2_14;
718 the_insn.pcrel = 1;
719 goto immediate;
720
721 case 'G':
722 the_insn.reloc = RELOC_WDISP19;
723 the_insn.pcrel = 1;
724 goto immediate;
725
726 case 'N':
727 if (*s == 'p' && s[1] == 'n') {
728 s += 2;
729 continue;
730 }
731 break;
732
733 case 'T':
734 if (*s == 'p' && s[1] == 't') {
735 s += 2;
736 continue;
737 }
738 break;
739
740 case 'z':
741 if (*s == ' ') {
742 ++s;
743 }
744 if (strncmp(s, "icc", 3) == 0) {
745 s += 3;
746 continue;
747 }
748 break;
749
750 case 'Z':
751 if (*s == ' ') {
752 ++s;
753 }
754 if (strncmp(s, "xcc", 3) == 0) {
755 s += 3;
756 continue;
757 }
758 break;
759
760 case '6':
761 if (*s == ' ') {
762 ++s;
763 }
764 if (strncmp(s, "fcc0", 4) == 0) {
765 s += 4;
766 continue;
767 }
768 break;
769
770 case '7':
771 if (*s == ' ') {
772 ++s;
773 }
774 if (strncmp(s, "fcc1", 4) == 0) {
775 s += 4;
776 continue;
777 }
778 break;
779
780 case '8':
781 if (*s == ' ') {
782 ++s;
783 }
784 if (strncmp(s, "fcc2", 4) == 0) {
785 s += 4;
786 continue;
787 }
788 break;
789
790 case '9':
791 if (*s == ' ') {
792 ++s;
793 }
794 if (strncmp(s, "fcc3", 4) == 0) {
795 s += 4;
796 continue;
797 }
798 break;
799
800 case 'P':
801 if (strncmp(s, "%pc", 3) == 0) {
802 s += 3;
803 continue;
804 }
805 break;
806
807 case 'W':
808 if (strncmp(s, "%tick", 5) == 0) {
809 s += 5;
810 continue;
811 }
812 break;
813 #endif /* NO_V9 */
814 /* end-sanitize-v9 */
815
816 case '\0': /* end of args */
817 if (*s == '\0') {
818 match = 1;
819 }
820 break;
821
822 case '+':
823 if (*s == '+') {
824 ++s;
825 continue;
826 }
827 if (*s == '-') {
828 continue;
829 }
830 break;
831
832 case '[': /* these must match exactly */
833 case ']':
834 case ',':
835 case ' ':
836 if (*s++ == *args)
837 continue;
838 break;
839
840 case '#': /* must be at least one digit */
841 if (isdigit(*s++)) {
842 while (isdigit(*s)) {
843 ++s;
844 }
845 continue;
846 }
847 break;
848
849 case 'C': /* coprocessor state register */
850 if (strncmp(s, "%csr", 4) == 0) {
851 s += 4;
852 continue;
853 }
854 break;
855
856 case 'b': /* next operand is a coprocessor register */
857 case 'c':
858 case 'D':
859 if (*s++ == '%' && *s++ == 'c' && isdigit(*s)) {
860 mask = *s++;
861 if (isdigit(*s)) {
862 mask = 10 * (mask - '0') + (*s++ - '0');
863 if (mask >= 32) {
864 break;
865 }
866 } else {
867 mask -= '0';
868 }
869 switch (*args) {
870
871 case 'b':
872 opcode |= mask << 14;
873 continue;
874
875 case 'c':
876 opcode |= mask;
877 continue;
878
879 case 'D':
880 opcode |= mask << 25;
881 continue;
882 }
883 }
884 break;
885
886 case 'r': /* next operand must be a register */
887 case '1':
888 case '2':
889 case 'd':
890 if (*s++ == '%') {
891 switch (c = *s++) {
892
893 case 'f': /* frame pointer */
894 if (*s++ == 'p') {
895 mask = 0x1e;
896 break;
897 }
898 goto error;
899
900 case 'g': /* global register */
901 if (isoctal(c = *s++)) {
902 mask = c - '0';
903 break;
904 }
905 goto error;
906
907 case 'i': /* in register */
908 if (isoctal(c = *s++)) {
909 mask = c - '0' + 24;
910 break;
911 }
912 goto error;
913
914 case 'l': /* local register */
915 if (isoctal(c = *s++)) {
916 mask= (c - '0' + 16) ;
917 break;
918 }
919 goto error;
920
921 case 'o': /* out register */
922 if (isoctal(c = *s++)) {
923 mask= (c - '0' + 8) ;
924 break;
925 }
926 goto error;
927
928 case 's': /* stack pointer */
929 if (*s++ == 'p') {
930 mask= 0xe;
931 break;
932 }
933 goto error;
934
935 case 'r': /* any register */
936 if (!isdigit(c = *s++)) {
937 goto error;
938 }
939 /* FALLTHROUGH */
940 case '0': case '1': case '2': case '3': case '4':
941 case '5': case '6': case '7': case '8': case '9':
942 if (isdigit(*s)) {
943 if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32) {
944 goto error;
945 }
946 } else {
947 c -= '0';
948 }
949 mask= c;
950 break;
951
952 default:
953 goto error;
954 }
955 /*
956 * Got the register, now figure out where
957 * it goes in the opcode.
958 */
959 switch (*args) {
960
961 case '1':
962 opcode |= mask << 14;
963 continue;
964
965 case '2':
966 opcode |= mask;
967 continue;
968
969 case 'd':
970 opcode |= mask << 25;
971 continue;
972
973 case 'r':
974 opcode |= (mask << 25) | (mask << 14);
975 continue;
976 }
977 }
978 break;
979
980 case 'e': /* next operand is a floating point register */
981 case 'v':
982 case 'V':
983
984 case 'f':
985 case 'B':
986 case 'R':
987
988 case 'g':
989 case 'H':
990 case 'J': {
991 char format;
992
993 if (*s++ == '%'
994
995 /* start-sanitize-v9 */
996 #ifndef NO_V9
997 && ((format = *s) == 'f'
998 || *s == 'd'
999 || *s == 'q')
1000 #else
1001 /* end-sanitize-v9 */
1002 && ((format = *s) == 'f')
1003
1004 /* start-sanitize-v9 */
1005 #endif /* NO_V9 */
1006 /* end-sanitize-v9 */
1007 && isdigit(*++s)) {
1008
1009
1010
1011 for (mask = 0; isdigit(*s); ++s) {
1012 mask = 10 * mask + (*s - '0');
1013 } /* read the number */
1014
1015 if ((*args == 'v'
1016 || *args == 'B'
1017 || *args == 'H')
1018 && (mask & 1)) {
1019 break;
1020 } /* register must be even numbered */
1021
1022 if ((*args == 'V'
1023 || *args == 'R'
1024 || *args == 'J')
1025 && (mask & 3)) {
1026 break;
1027 } /* register must be multiple of 4 */
1028
1029 if (format == 'f') {
1030 if (mask >= 32) {
1031 error_message = ": There are only 32 f registers; [0-31]";
1032 goto error;
1033 } /* on error */
1034 /* start-sanitize-v9 */
1035 #ifndef NO_V9
1036 } else {
1037 if (format == 'd') {
1038 if (mask >= 64) {
1039 error_message = ": There are only 32 d registers [0, 2, ... 62].";
1040 goto error;
1041 } else if (mask & 1) {
1042 error_message = ": Only even numbered d registers exist.";
1043 goto error;
1044 } /* on error */
1045
1046 } else if (format == 'q') {
1047 if (mask >= 64) {
1048 error_message =
1049 ": There are only 16 q registers [0, 4, ... 60].";
1050 goto error;
1051 } else if (mask & 3) {
1052 error_message =
1053 ": Only q registers evenly divisible by four exist.";
1054 goto error;
1055 } /* on error */
1056 } else {
1057 know(0);
1058 } /* depending on format */
1059
1060 if (mask >= 32) {
1061 mask -= 31;
1062 } /* wrap high bit */
1063 #endif /* NO_V9 */
1064 /* end-sanitize-v9 */
1065 } /* if not an 'f' register. */
1066 } /* on error */
1067
1068 switch (*args) {
1069
1070 case 'v':
1071 case 'V':
1072 case 'e':
1073 opcode |= RS1(mask);
1074 continue;
1075
1076
1077 case 'f':
1078 case 'B':
1079 case 'R':
1080 opcode |= RS2(mask);
1081 continue;
1082
1083 case 'g':
1084 case 'H':
1085 case 'J':
1086 opcode |= RD(mask);
1087 continue;
1088 } /* pack it in. */
1089
1090 know(0);
1091 break;
1092 } /* float arg */
1093
1094 case 'F':
1095 if (strncmp(s, "%fsr", 4) == 0) {
1096 s += 4;
1097 continue;
1098 }
1099 break;
1100
1101 case 'h': /* high 22 bits */
1102 the_insn.reloc = RELOC_HI22;
1103 goto immediate;
1104
1105 case 'l': /* 22 bit PC relative immediate */
1106 the_insn.reloc = RELOC_WDISP22;
1107 the_insn.pcrel = 1;
1108 goto immediate;
1109
1110 case 'L': /* 30 bit immediate */
1111 the_insn.reloc = RELOC_WDISP30;
1112 the_insn.pcrel = 1;
1113 goto immediate;
1114
1115 case 'n': /* 22 bit immediate */
1116 the_insn.reloc = RELOC_22;
1117 goto immediate;
1118
1119 case 'i': /* 13 bit immediate */
1120 the_insn.reloc = RELOC_BASE13;
1121
1122 /*FALLTHROUGH */
1123
1124 immediate:
1125 if(*s==' ')
1126 s++;
1127 if (*s == '%') {
1128 if ((c = s[1]) == 'h' && s[2] == 'i') {
1129 the_insn.reloc = RELOC_HI22;
1130 s+=3;
1131 } else if (c == 'l' && s[2] == 'o') {
1132 the_insn.reloc = RELOC_LO10;
1133 s+=3;
1134 /* start-sanitize-v9 */
1135 #ifndef NO_V9
1136 } else if (c == 'h'
1137 && s[2] == 'h'
1138 && s[3] == 'i') {
1139 the_insn.reloc = RELOC_HHI22;
1140 s += 4;
1141
1142 } else if (c == 'h'
1143 && s[2] == 'l'
1144 && s[3] == 'o') {
1145 the_insn.reloc = RELOC_HLO10;
1146 s += 4;
1147 #endif /* NO_V9 */
1148 /* end-sanitize-v9 */
1149 } else
1150 break;
1151 }
1152 /* Note that if the getExpression() fails, we
1153 will still have created U entries in the
1154 symbol table for the 'symbols' in the input
1155 string. Try not to create U symbols for
1156 registers, etc. */
1157 {
1158 /* This stuff checks to see if the
1159 expression ends in +%reg If it does,
1160 it removes the register from the
1161 expression, and re-sets 's' to point
1162 to the right place */
1163
1164 char *s1;
1165
1166 for (s1 = s; *s1 && *s1 != ',' && *s1 != ']'; s1++) ;;
1167
1168 if (s1 != s && isdigit(s1[-1])) {
1169 if(s1[-2] == '%' && s1[-3] == '+') {
1170 s1 -= 3;
1171 *s1 = '\0';
1172 (void) getExpression(s);
1173 *s1 = '+';
1174 s = s1;
1175 continue;
1176 } else if (strchr("goli0123456789", s1[-2]) && s1[-3] == '%' && s1[-4] == '+') {
1177 s1 -= 4;
1178 *s1 = '\0';
1179 (void) getExpression(s);
1180 *s1 = '+';
1181 s = s1;
1182 continue;
1183 }
1184 }
1185 }
1186 (void)getExpression(s);
1187 s = expr_end;
1188 continue;
1189
1190 case 'a':
1191 if (*s++ == 'a') {
1192 opcode |= ANNUL;
1193 continue;
1194 }
1195 break;
1196
1197 case 'A': {
1198 char *push = input_line_pointer;
1199 expressionS e;
1200
1201 input_line_pointer = s;
1202
1203 if (expression(&e) == SEG_ABSOLUTE) {
1204 opcode |= e.X_add_number << 5;
1205 s = input_line_pointer;
1206 input_line_pointer = push;
1207 continue;
1208 } /* if absolute */
1209
1210 break;
1211 } /* alternate space */
1212
1213 case 'p':
1214 if (strncmp(s, "%psr", 4) == 0) {
1215 s += 4;
1216 continue;
1217 }
1218 break;
1219
1220 case 'q': /* floating point queue */
1221 if (strncmp(s, "%fq", 3) == 0) {
1222 s += 3;
1223 continue;
1224 }
1225 break;
1226
1227 case 'Q': /* coprocessor queue */
1228 if (strncmp(s, "%cq", 3) == 0) {
1229 s += 3;
1230 continue;
1231 }
1232 break;
1233
1234 case 'S':
1235 if (strcmp(str, "set") == 0) {
1236 special_case = SPECIAL_CASE_SET;
1237 continue;
1238 } else if (strncmp(str, "fdiv", 4) == 0) {
1239 special_case = SPECIAL_CASE_FDIV;
1240 continue;
1241 }
1242 break;
1243
1244 /* start-sanitize-v9 */
1245 #ifndef NO_V9
1246 case 'o':
1247 if (strncmp (s, "%asi", 4) != 0)
1248 break;
1249 s += 4;
1250 continue;
1251
1252 case 's':
1253 if (strncmp (s, "%fprs", 5) != 0)
1254 break;
1255 s+= 5;
1256 continue;
1257
1258 case 'E':
1259 if (strncmp (s, "%ccr", 4) != 0)
1260 break;
1261 s+= 4;
1262 continue;
1263 #endif /* NO_V9 */
1264 /* end-sanitize-v9 */
1265
1266 case 't':
1267 if (strncmp(s, "%tbr", 4) != 0)
1268 break;
1269 s += 4;
1270 continue;
1271
1272 case 'w':
1273 if (strncmp(s, "%wim", 4) != 0)
1274 break;
1275 s += 4;
1276 continue;
1277
1278 case 'y':
1279 if (strncmp(s, "%y", 2) != 0)
1280 break;
1281 s += 2;
1282 continue;
1283
1284 default:
1285 as_fatal("failed sanity check.");
1286 } /* switch on arg code */
1287 break;
1288 } /* for each arg that we expect */
1289 error:
1290 if (match == 0) {
1291 /* Args don't match. */
1292 if (((unsigned) (&insn[1] - sparc_opcodes)) < NUMOPCODES
1293 && !strcmp(insn->name, insn[1].name)) {
1294 ++insn;
1295 s = argsStart;
1296 continue;
1297 } else {
1298 as_bad("Illegal operands%s", error_message);
1299 return;
1300 }
1301 } else {
1302 if (insn->architecture > current_architecture) {
1303 if ((!architecture_requested || warn_on_bump)
1304 &&
1305 /* start-sanitize-v9 */
1306 #ifndef NO_V9
1307 ! ARCHITECTURES_CONFLICT_P (current_architecture,
1308 insn->architecture)
1309 #else
1310 /* end-sanitize-v9 */
1311 1
1312 /* start-sanitize-v9 */
1313 #endif
1314 /* end-sanitize-v9 */
1315 ) {
1316 if (warn_on_bump) {
1317 as_warn("architecture bumped from \"%s\" to \"%s\" on \"%s\"",
1318 architecture_pname[current_architecture],
1319 architecture_pname[insn->architecture],
1320 str);
1321 } /* if warning */
1322
1323 current_architecture = insn->architecture;
1324 } else {
1325 as_bad("architecture mismatch on \"%s\" (\"%s\"). current architecture is \"%s\"",
1326 str,
1327 architecture_pname[insn->architecture],
1328 architecture_pname[current_architecture]);
1329 return;
1330 } /* if bump ok else error */
1331 } /* if architecture higher */
1332 } /* if no match */
1333
1334 break;
1335 } /* forever looking for a match */
1336
1337 the_insn.opcode = opcode;
1338 return;
1339 } /* sparc_ip() */
1340
1341 static int getExpression(str)
1342 char *str;
1343 {
1344 char *save_in;
1345 segT seg;
1346
1347 save_in = input_line_pointer;
1348 input_line_pointer = str;
1349 switch (seg = expression(&the_insn.exp)) {
1350
1351 case SEG_ABSOLUTE:
1352 case SEG_TEXT:
1353 case SEG_DATA:
1354 case SEG_BSS:
1355 case SEG_UNKNOWN:
1356 case SEG_DIFFERENCE:
1357 case SEG_BIG:
1358 case SEG_ABSENT:
1359 break;
1360
1361 default:
1362 the_insn.error = "bad segment";
1363 expr_end = input_line_pointer;
1364 input_line_pointer=save_in;
1365 return 1;
1366 }
1367 expr_end = input_line_pointer;
1368 input_line_pointer = save_in;
1369 return 0;
1370 } /* getExpression() */
1371
1372
1373 /*
1374 This is identical to the md_atof in m68k.c. I think this is right,
1375 but I'm not sure.
1376
1377 Turn a string in input_line_pointer into a floating point constant of type
1378 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
1379 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
1380 */
1381
1382 /* Equal to MAX_PRECISION in atof-ieee.c */
1383 #define MAX_LITTLENUMS 6
1384
1385 char *md_atof(type,litP,sizeP)
1386 char type;
1387 char *litP;
1388 int *sizeP;
1389 {
1390 int prec;
1391 LITTLENUM_TYPE words[MAX_LITTLENUMS];
1392 LITTLENUM_TYPE *wordP;
1393 char *t;
1394 char *atof_ieee();
1395
1396 switch(type) {
1397
1398 case 'f':
1399 case 'F':
1400 case 's':
1401 case 'S':
1402 prec = 2;
1403 break;
1404
1405 case 'd':
1406 case 'D':
1407 case 'r':
1408 case 'R':
1409 prec = 4;
1410 break;
1411
1412 case 'x':
1413 case 'X':
1414 prec = 6;
1415 break;
1416
1417 case 'p':
1418 case 'P':
1419 prec = 6;
1420 break;
1421
1422 default:
1423 *sizeP=0;
1424 return "Bad call to MD_ATOF()";
1425 }
1426 t=atof_ieee(input_line_pointer,type,words);
1427 if(t)
1428 input_line_pointer=t;
1429 *sizeP=prec * sizeof(LITTLENUM_TYPE);
1430 for(wordP=words;prec--;) {
1431 md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE));
1432 litP+=sizeof(LITTLENUM_TYPE);
1433 }
1434 return ""; /* Someone should teach Dean about null pointers */
1435 } /* md_atof() */
1436
1437 /*
1438 * Write out big-endian.
1439 */
1440 void md_number_to_chars(buf,val,n)
1441 char *buf;
1442 long val;
1443 int n;
1444 {
1445
1446 switch(n) {
1447
1448 case 4:
1449 *buf++ = val >> 24;
1450 *buf++ = val >> 16;
1451 case 2:
1452 *buf++ = val >> 8;
1453 case 1:
1454 *buf = val;
1455 break;
1456
1457 default:
1458 as_fatal("failed sanity check.");
1459 }
1460 return;
1461 } /* md_number_to_chars() */
1462
1463 /* Apply a fixS to the frags, now that we know the value it ought to
1464 hold. */
1465
1466 void md_apply_fix(fixP, val)
1467 fixS *fixP;
1468 long val;
1469 {
1470 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
1471
1472 assert(fixP->fx_size == 4);
1473 assert(fixP->fx_r_type < NO_RELOC);
1474
1475 fixP->fx_addnumber = val; /* Remember value for emit_reloc */
1476
1477 /*
1478 * This is a hack. There should be a better way to
1479 * handle this.
1480 */
1481 if (fixP->fx_r_type == RELOC_WDISP30 && fixP->fx_addsy) {
1482 val += fixP->fx_where + fixP->fx_frag->fr_address;
1483 }
1484
1485 switch (fixP->fx_r_type) {
1486
1487 case RELOC_32:
1488 buf[0] = 0; /* val >> 24; */
1489 buf[1] = 0; /* val >> 16; */
1490 buf[2] = 0; /* val >> 8; */
1491 buf[3] = 0; /* val; */
1492 break;
1493
1494 #if 0
1495 case RELOC_8: /* These don't seem to ever be needed. */
1496 case RELOC_16:
1497 case RELOC_DISP8:
1498 case RELOC_DISP16:
1499 case RELOC_DISP32:
1500 #endif
1501 case RELOC_WDISP30:
1502 val = (val >>= 2) + 1;
1503 buf[0] |= (val >> 24) & 0x3f;
1504 buf[1]= (val >> 16);
1505 buf[2] = val >> 8;
1506 buf[3] = val;
1507 break;
1508
1509 /* start-sanitize-v9 */
1510 #ifndef NO_V9
1511 case RELOC_11:
1512 if (((val > 0) && (val & ~0x7ff))
1513 || ((val < 0) && (~(val - 1) & ~0x7ff))) {
1514 as_bad("relocation overflow.");
1515 } /* on overflow */
1516
1517 buf[2] = (val >> 8) & 0x7;
1518 buf[3] = val & 0xff;
1519 break;
1520
1521 case RELOC_10:
1522 if (((val > 0) && (val & ~0x3ff))
1523 || ((val < 0) && (~(val - 1) & ~0x3ff))) {
1524 as_bad("relocation overflow.");
1525 } /* on overflow */
1526
1527 buf[2] = (val >> 8) & 0x3;
1528 buf[3] = val & 0xff;
1529 break;
1530
1531 case RELOC_WDISP2_14:
1532 if (((val > 0) && (val & ~0x3fffc))
1533 || ((val < 0) && (~(val - 1) & ~0x3fffc))) {
1534 as_bad("relocation overflow.");
1535 } /* on overflow */
1536
1537 val = (val >>= 2) + 1;
1538 buf[1] |= ((val >> 14) & 0x3) << 3;
1539 buf[2] |= (val >> 8) & 0x3f ;
1540 buf[3] = val & 0xff;
1541 break;
1542
1543 case RELOC_WDISP19:
1544 if (((val > 0) && (val & ~0x1ffffc))
1545 || ((val < 0) && (~(val - 1) & ~0x1ffffc))) {
1546 as_bad("relocation overflow.");
1547 } /* on overflow */
1548
1549 val = (val >>= 2) + 1;
1550 buf[1] |= (val >> 16) & 0x7;
1551 buf[2] = (val >> 8) & 0xff;
1552 buf[3] = val & 0xff;
1553 break;
1554
1555 case RELOC_HHI22:
1556 val >>= 32;
1557 /* intentional fallthrough */
1558 #endif /* NO_V9 */
1559 /* end-sanitize-v9 */
1560
1561 case RELOC_HI22:
1562 if(!fixP->fx_addsy) {
1563 buf[1] |= (val >> 26) & 0x3f;
1564 buf[2] = val >> 18;
1565 buf[3] = val >> 10;
1566 } else {
1567 buf[2]=0;
1568 buf[3]=0;
1569 }
1570 break;
1571
1572 case RELOC_22:
1573 if (val & ~0x003fffff) {
1574 as_bad("relocation overflow");
1575 } /* on overflow */
1576 buf[1] |= (val >> 16) & 0x3f;
1577 buf[2] = val >> 8;
1578 buf[3] = val & 0xff;
1579 break;
1580
1581 case RELOC_13:
1582 if (val & ~0x00001fff) {
1583 as_bad("relocation overflow");
1584 } /* on overflow */
1585 buf[2] = (val >> 8) & 0x1f;
1586 buf[3] = val & 0xff;
1587 break;
1588
1589 /* start-sanitize-v9 */
1590 #ifndef NO_V9
1591 case RELOC_HLO10:
1592 val >>= 32;
1593 /* intentional fallthrough */
1594 #endif /* NO_V9 */
1595 /* end-sanitize-v9 */
1596
1597 case RELOC_LO10:
1598 if(!fixP->fx_addsy) {
1599 buf[2] |= (val >> 8) & 0x03;
1600 buf[3] = val;
1601 } else
1602 buf[3]=0;
1603 break;
1604 #if 0
1605 case RELOC_SFA_BASE:
1606 case RELOC_SFA_OFF13:
1607 case RELOC_BASE10:
1608 #endif
1609 case RELOC_BASE13:
1610 buf[2] |= (val >> 8) & 0x1f;
1611 buf[3] = val;
1612 break;
1613
1614 case RELOC_WDISP22:
1615 val = (val >>= 2) + 1;
1616 /* FALLTHROUGH */
1617 case RELOC_BASE22:
1618 buf[1] |= (val >> 16) & 0x3f;
1619 buf[2] = val >> 8;
1620 buf[3] = val;
1621 break;
1622
1623 #if 0
1624 case RELOC_PC10:
1625 case RELOC_PC22:
1626 case RELOC_JMP_TBL:
1627 case RELOC_SEGOFF16:
1628 case RELOC_GLOB_DAT:
1629 case RELOC_JMP_SLOT:
1630 case RELOC_RELATIVE:
1631 #endif
1632
1633 case NO_RELOC:
1634 default:
1635 as_bad("bad relocation type: 0x%02x", fixP->fx_r_type);
1636 break;
1637 }
1638 } /* md_apply_fix() */
1639
1640 /* should never be called for sparc */
1641 void md_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol)
1642 char *ptr;
1643 long from_addr;
1644 long to_addr;
1645 fragS *frag;
1646 symbolS *to_symbol;
1647 {
1648 as_fatal("sparc_create_short_jmp\n");
1649 } /* md_create_short_jump() */
1650
1651 /* Translate internal representation of relocation info to target format.
1652
1653 On sparc: first 4 bytes are normal unsigned long address, next three
1654 bytes are index, most sig. byte first. Byte 7 is broken up with
1655 bit 7 as external, bits 6 & 5 unused, and the lower
1656 five bits as relocation type. Next 4 bytes are long addend. */
1657 /* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */
1658 void
1659 tc_aout_fix_to_chars(where, fixP, segment_address_in_file)
1660 char *where;
1661 fixS *fixP;
1662 relax_addressT segment_address_in_file;
1663 {
1664 long r_index;
1665 long r_extern;
1666 long r_addend = 0;
1667 long r_address;
1668
1669 know(fixP->fx_addsy);
1670
1671 if (!S_IS_DEFINED(fixP->fx_addsy)) {
1672 r_extern = 1;
1673 r_index = fixP->fx_addsy->sy_number;
1674 } else {
1675 r_extern = 0;
1676 r_index = S_GET_TYPE(fixP->fx_addsy);
1677 }
1678
1679 /* this is easy */
1680 md_number_to_chars(where,
1681 r_address = fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
1682 4);
1683
1684 /* now the fun stuff */
1685 where[4] = (r_index >> 16) & 0x0ff;
1686 where[5] = (r_index >> 8) & 0x0ff;
1687 where[6] = r_index & 0x0ff;
1688 where[7] = ((r_extern << 7) & 0x80) | (0 & 0x60) | (fixP->fx_r_type & 0x1F);
1689
1690 /* Also easy */
1691 if (fixP->fx_addsy->sy_frag) {
1692 r_addend = fixP->fx_addsy->sy_frag->fr_address;
1693 }
1694
1695 if (fixP->fx_pcrel) {
1696 r_addend += fixP->fx_offset - r_address;
1697 } else {
1698 r_addend = fixP->fx_addnumber;
1699 }
1700
1701 md_number_to_chars(&where[8], r_addend, 4);
1702
1703 return;
1704 } /* tc_aout_fix_to_chars() */
1705
1706 /* should never be called for sparc */
1707 void md_convert_frag(headers, fragP)
1708 object_headers *headers;
1709 register fragS *fragP;
1710 {
1711 as_fatal("sparc_convert_frag\n");
1712 } /* md_convert_frag() */
1713
1714 /* should never be called for sparc */
1715 void md_create_long_jump(ptr, from_addr, to_addr, frag, to_symbol)
1716 char *ptr;
1717 long from_addr, to_addr;
1718 fragS *frag;
1719 symbolS *to_symbol;
1720 {
1721 as_fatal("sparc_create_long_jump\n");
1722 } /* md_create_long_jump() */
1723
1724 /* should never be called for sparc */
1725 int md_estimate_size_before_relax(fragP, segtype)
1726 fragS *fragP;
1727 segT segtype;
1728 {
1729 as_fatal("sparc_estimate_size_before_relax\n");
1730 return(1);
1731 } /* md_estimate_size_before_relax() */
1732
1733 #if 0
1734 /* for debugging only */
1735 static void print_insn(insn)
1736 struct sparc_it *insn;
1737 {
1738 char *Reloc[] = {
1739 "RELOC_8",
1740 "RELOC_16",
1741 "RELOC_32",
1742 "RELOC_DISP8",
1743 "RELOC_DISP16",
1744 "RELOC_DISP32",
1745 "RELOC_WDISP30",
1746 "RELOC_WDISP22",
1747 "RELOC_HI22",
1748 "RELOC_22",
1749 "RELOC_13",
1750 "RELOC_LO10",
1751 "RELOC_SFA_BASE",
1752 "RELOC_SFA_OFF13",
1753 "RELOC_BASE10",
1754 "RELOC_BASE13",
1755 "RELOC_BASE22",
1756 "RELOC_PC10",
1757 "RELOC_PC22",
1758 "RELOC_JMP_TBL",
1759 "RELOC_SEGOFF16",
1760 "RELOC_GLOB_DAT",
1761 "RELOC_JMP_SLOT",
1762 "RELOC_RELATIVE",
1763 "NO_RELOC"
1764 };
1765
1766 if (insn->error) {
1767 fprintf(stderr, "ERROR: %s\n");
1768 }
1769 fprintf(stderr, "opcode=0x%08x\n", insn->opcode);
1770 fprintf(stderr, "reloc = %s\n", Reloc[insn->reloc]);
1771 fprintf(stderr, "exp = {
1772 \n");
1773 fprintf(stderr, "\t\tX_add_symbol = %s\n",
1774 ((insn->exp.X_add_symbol != NULL)
1775 ? ((S_GET_NAME(insn->exp.X_add_symbol) != NULL)
1776 ? S_GET_NAME(insn->exp.X_add_symbol)
1777 : "???")
1778 : "0"));
1779 fprintf(stderr, "\t\tX_sub_symbol = %s\n",
1780 ((insn->exp.X_subtract_symbol != NULL)
1781 ? (S_GET_NAME(insn->exp.X_subtract_symbol)
1782 ? S_GET_NAME(insn->exp.X_subtract_symbol)
1783 : "???")
1784 : "0"));
1785 fprintf(stderr, "\t\tX_add_number = %d\n",
1786 insn->exp.X_add_number);
1787 fprintf(stderr, "}\n");
1788 return;
1789 } /* print_insn() */
1790 #endif
1791
1792 /* Set the hook... */
1793
1794 /* void emit_sparc_reloc();
1795 void (*md_emit_relocations)() = emit_sparc_reloc; */
1796
1797 #ifdef comment
1798
1799 /*
1800 * Sparc/AM29K relocations are completely different, so it needs
1801 * this machine dependent routine to emit them.
1802 */
1803 #if defined(OBJ_AOUT) || defined(OBJ_BOUT)
1804 void emit_sparc_reloc(fixP, segment_address_in_file)
1805 register fixS *fixP;
1806 relax_addressT segment_address_in_file;
1807 {
1808 struct reloc_info_generic ri;
1809 register symbolS *symbolP;
1810 extern char *next_object_file_charP;
1811 /* long add_number; */
1812
1813 memset((char *) &ri, '\0', sizeof(ri));
1814 for (; fixP; fixP = fixP->fx_next) {
1815
1816 if (fixP->fx_r_type >= NO_RELOC) {
1817 as_fatal("fixP->fx_r_type = %d\n", fixP->fx_r_type);
1818 }
1819
1820 if ((symbolP = fixP->fx_addsy) != NULL) {
1821 ri.r_address = fixP->fx_frag->fr_address +
1822 fixP->fx_where - segment_address_in_file;
1823 if ((S_GET_TYPE(symbolP)) == N_UNDF) {
1824 ri.r_extern = 1;
1825 ri.r_index = symbolP->sy_number;
1826 } else {
1827 ri.r_extern = 0;
1828 ri.r_index = S_GET_TYPE(symbolP);
1829 }
1830 if (symbolP && symbolP->sy_frag) {
1831 ri.r_addend = symbolP->sy_frag->fr_address;
1832 }
1833 ri.r_type = fixP->fx_r_type;
1834 if (fixP->fx_pcrel) {
1835 /* ri.r_addend -= fixP->fx_where; */
1836 ri.r_addend -= ri.r_address;
1837 } else {
1838 ri.r_addend = fixP->fx_addnumber;
1839 }
1840
1841 md_ri_to_chars(next_object_file_charP, &ri);
1842 next_object_file_charP += md_reloc_size;
1843 }
1844 }
1845 return;
1846 } /* emit_sparc_reloc() */
1847 #endif /* aout or bout */
1848 #endif /* comment */
1849
1850 /*
1851 * md_parse_option
1852 * Invocation line includes a switch not recognized by the base assembler.
1853 * See if it's a processor-specific option. These are:
1854 *
1855 * -bump
1856 * Warn on architecture bumps. See also -A.
1857 *
1858 * -Av6, -Av7, -Av8, -Asparclite
1859 * Select the architecture. Instructions or features not
1860 * supported by the selected architecture cause fatal errors.
1861 *
1862 * The default is to start at v6, and bump the architecture up
1863 * whenever an instruction is seen at a higher level.
1864 *
1865 * If -bump is specified, a warning is printing when bumping to
1866 * higher levels.
1867 *
1868 * If an architecture is specified, all instructions must match
1869 * that architecture. Any higher level instructions are flagged
1870 * as errors.
1871 *
1872 * if both an architecture and -bump are specified, the
1873 * architecture starts at the specified level, but bumps are
1874 * warnings.
1875 *
1876 * start-sanitize-v9
1877 * Bumping between incompatible architectures is always an
1878 * error. For example, from sparclite to v9.
1879 * end-sanitize-v9
1880 */
1881 /* start-sanitize-v9 */
1882 /* There is also a -Av9 architecture option. xoxorich. */
1883 /* end-sanitize-v9 */
1884 int md_parse_option(argP, cntP, vecP)
1885 char **argP;
1886 int *cntP;
1887 char ***vecP;
1888 {
1889 char *p;
1890 const char **arch;
1891
1892 if (!strcmp(*argP,"bump")){
1893 warn_on_bump = 1;
1894
1895 } else if (**argP == 'A'){
1896 p = (*argP) + 1;
1897
1898 for (arch = architecture_pname; *arch != NULL; ++arch){
1899 if (strcmp(p, *arch) == 0){
1900 break;
1901 } /* found a match */
1902 } /* walk the pname table */
1903
1904 if (*arch == NULL){
1905 as_bad("unknown architecture: %s", p);
1906 } else {
1907 current_architecture = (enum sparc_architecture) (arch - architecture_pname);
1908 architecture_requested = 1;
1909 }
1910 } else {
1911 /* Unknown option */
1912 (*argP)++;
1913 return 0;
1914 }
1915 **argP = '\0'; /* Done parsing this switch */
1916 return 1;
1917 } /* md_parse_option() */
1918
1919 /* We have no need to default values of symbols. */
1920
1921 /* ARGSUSED */
1922 symbolS *md_undefined_symbol(name)
1923 char *name;
1924 {
1925 return 0;
1926 } /* md_undefined_symbol() */
1927
1928 /* Parse an operand that is machine-specific.
1929 We just return without modifying the expression if we have nothing
1930 to do. */
1931
1932 /* ARGSUSED */
1933 void md_operand(expressionP)
1934 expressionS *expressionP;
1935 {
1936 } /* md_operand() */
1937
1938 /* Round up a section size to the appropriate boundary. */
1939 long md_section_align (segment, size)
1940 segT segment;
1941 long size;
1942 {
1943 return (size + 7) & ~7; /* Round all sects to multiple of 8 */
1944 } /* md_section_align() */
1945
1946 /* Exactly what point is a PC-relative offset relative TO?
1947 On the sparc, they're relative to the address of the offset, plus
1948 its size. This gets us to the following instruction.
1949 (??? Is this right? FIXME-SOON) */
1950 long md_pcrel_from(fixP)
1951 fixS *fixP;
1952 {
1953 return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
1954 } /* md_pcrel_from() */
1955
1956 void tc_aout_pre_write_hook(headers)
1957 object_headers *headers;
1958 {
1959 H_SET_VERSION(headers, 1);
1960 return;
1961 } /* tc_aout_pre_write_hook() */
1962
1963 /*
1964 * Local Variables:
1965 * comment-column: 0
1966 * fill-column: 131
1967 * End:
1968 */
1969
1970 /* end of tc-sparc.c */
This page took 0.123624 seconds and 5 git commands to generate.