force all files to end in "/* end of filename"
[external/binutils.git] / gas / config / tc-sparc.c
1 #define cypress 1234
2 /* tc-sparc.c -- Assemble for the SPARC
3    Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
4    
5    This file is part of GAS, the GNU Assembler.
6    
7    GAS is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2, or (at your option)
10    any later version.
11    
12    GAS is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with GAS; see the file COPYING.  If not, write to
19    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21 #include <stdio.h>
22 #include <ctype.h>
23
24 #include "as.h"
25
26 /* careful, this file includes data *declarations* */
27 #include "opcode/sparc.h"
28
29 void md_begin();
30 void md_end();
31 void md_number_to_chars();
32 void md_assemble();
33 char *md_atof();
34 void md_convert_frag();
35 void md_create_short_jump();
36 void md_create_long_jump();
37 int md_estimate_size_before_relax();
38 void md_ri_to_chars();
39 symbolS *md_undefined_symbol();
40 static void sparc_ip();
41
42 static enum sparc_architecture current_architecture = v6;
43 static int architecture_requested = 0;
44 static int warn_on_bump = 0;
45
46 const relax_typeS md_relax_table[] = {
47     0 };
48
49 /* handle of the OPCODE hash table */
50 static struct hash_control *op_hash = NULL;
51
52 static void s_seg(), s_proc(), s_data1(), s_reserve(), s_common();
53 extern void s_globl(), s_long(), s_short(), s_space(), cons();
54 extern void s_align_bytes(), s_ignore();
55
56 const pseudo_typeS md_pseudo_table[] = {
57 { "align",      s_align_bytes,  0       },    /* Defaulting is invalid (0) */
58 { "common",     s_common,       0       },
59 { "global",     s_globl,        0       },
60 { "half",       cons,           2       },
61 { "optim",      s_ignore,       0       },
62 { "proc",       s_proc,         0       },
63 { "reserve",    s_reserve,      0       },
64 { "seg",        s_seg,          0       },
65 { "skip",       s_space,        0       },
66 { "word",       cons,           4       },
67 { NULL, 0,              0       },
68 };
69
70 const int md_short_jump_size = 4;
71 const int md_long_jump_size = 4;
72 const int md_reloc_size = 12;                   /* Size of relocation record */
73
74 /* This array holds the chars that always start a comment.  If the
75    pre-processor is disabled, these aren't very useful */
76 const char comment_chars[] = "!";       /* JF removed '|' from comment_chars */
77
78 /* This array holds the chars that only start a comment at the beginning of
79    a line.  If the line seems to have the form '# 123 filename'
80    .line and .file directives will appear in the pre-processed output */
81 /* Note that input_file.c hand checks for '#' at the beginning of the
82    first line of the input file.  This is because the compiler outputs
83    #NO_APP at the beginning of its output. */
84 /* Also note that comments started like this one will always
85    work if '/' isn't otherwise defined. */
86 const char line_comment_chars[] = "#";
87
88 /* Chars that can be used to separate mant from exp in floating point nums */
89 const char EXP_CHARS[] = "eE";
90
91 /* Chars that mean this number is a floating point constant */
92 /* As in 0f12.456 */
93 /* or    0d1.2345e12 */
94 const char FLT_CHARS[] = "rRsSfFdDxXpP";
95
96 /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
97    changed in read.c .  Ideally it shouldn't have to know about it at all,
98    but nothing is ideal around here.
99    */
100
101 static unsigned char octal[256];
102 #define isoctal(c)  octal[c]
103     static unsigned char toHex[256];
104
105 struct sparc_it {
106     char *error;
107 unsigned long opcode;
108 struct nlist *nlistp;
109 expressionS exp;
110 int pcrel;
111 enum reloc_type reloc;
112 } the_insn, set_insn;
113
114 #ifdef __STDC__
115 #if 0
116 static void print_insn(struct sparc_it *insn);
117 #endif
118 static int getExpression(char *str);
119 #else
120 #if 0
121 static void print_insn();
122 #endif
123 static int getExpression();
124 #endif
125 static char *expr_end;
126 static int special_case;
127
128 /*
129  * Instructions that require wierd handling because they're longer than
130  * 4 bytes.
131  */
132 #define SPECIAL_CASE_SET        1
133 #define SPECIAL_CASE_FDIV       2
134
135 /*
136  * sort of like s_lcomm
137  *
138  */
139 static int max_alignment = 15;
140
141 static void s_reserve() {
142         char *name;
143     char *p;
144     char c;
145     int align;
146     int size;
147     int temp;
148     symbolS *symbolP;
149     
150     name = input_line_pointer;
151     c = get_symbol_end();
152     p = input_line_pointer;
153     *p = c;
154     SKIP_WHITESPACE();
155     
156     if (*input_line_pointer != ',') {
157         as_bad("Expected comma after name");
158         ignore_rest_of_line();
159         return;
160     }
161     
162     ++input_line_pointer;
163     
164     if ((size = get_absolute_expression()) < 0) {
165         as_bad("BSS length (%d.) <0! Ignored.", size);
166         ignore_rest_of_line();
167         return;
168     } /* bad length */
169     
170     *p = 0;
171     symbolP = symbol_find_or_make(name);
172     *p = c;
173     
174     if (strncmp(input_line_pointer, ",\"bss\"", 6) != 0) {
175         as_bad("bad .reserve segment: `%s'", input_line_pointer);
176         return;
177     } /* if not bss */
178     
179     input_line_pointer += 6;
180     SKIP_WHITESPACE();
181     
182     if (*input_line_pointer == ',') {
183         ++input_line_pointer;
184         
185         SKIP_WHITESPACE();
186         if (*input_line_pointer == '\n') {
187             as_bad("Missing alignment");
188             return;
189         }
190         
191         align = get_absolute_expression();
192         if (align > max_alignment){
193             align = max_alignment;
194             as_warn("Alignment too large: %d. assumed.", align);
195         } else if (align < 0) {
196             align = 0;
197             as_warn("Alignment negative. 0 assumed.");
198         }
199 #ifdef MANY_SEGMENTS
200 #define SEG_BSS SEG_E2
201         record_alignment(SEG_E2, align);
202 #else
203         record_alignment(SEG_BSS, align);
204 #endif
205         
206         /* convert to a power of 2 alignment */
207         for (temp = 0; (align & 1) == 0; align >>= 1, ++temp) ;;
208         
209         if (align != 1) {
210             as_bad("Alignment not a power of 2");
211             ignore_rest_of_line();
212             return;
213         } /* not a power of two */
214         
215         align = temp;
216         
217         /* Align */
218         align = ~((~0) << align);       /* Convert to a mask */
219         local_bss_counter = (local_bss_counter + align) & (~align);
220     } /* if has optional alignment */
221     
222     if (S_GET_OTHER(symbolP) == 0
223         && S_GET_DESC(symbolP) == 0
224         && ((S_GET_SEGMENT(symbolP) == SEG_BSS
225              && S_GET_VALUE(symbolP) == local_bss_counter)
226             || !S_IS_DEFINED(symbolP))) {
227         S_SET_VALUE(symbolP, local_bss_counter);
228         S_SET_SEGMENT(symbolP, SEG_BSS);
229         symbolP->sy_frag  = &bss_address_frag;
230         local_bss_counter += size;
231     } else {
232         as_warn("Ignoring attempt to re-define symbol from %d. to %d.",
233                 S_GET_VALUE(symbolP), local_bss_counter);
234     } /* if not redefining */
235     
236     demand_empty_rest_of_line();
237     return;
238 } /* s_reserve() */
239
240 static void s_common() {
241         register char *name;
242     register char c;
243     register char *p;
244     register int temp;
245     register symbolS *  symbolP;
246     
247     name = input_line_pointer;
248     c = get_symbol_end();
249     /* just after name is now '\0' */
250     p = input_line_pointer;
251     *p = c;
252     SKIP_WHITESPACE();
253     if (* input_line_pointer != ',') {
254         as_bad("Expected comma after symbol-name");
255         ignore_rest_of_line();
256         return;
257     }
258     input_line_pointer ++; /* skip ',' */
259     if ((temp = get_absolute_expression ()) < 0) {
260         as_bad(".COMMon length (%d.) <0! Ignored.", temp);
261         ignore_rest_of_line();
262         return;
263     }
264     *p = 0;
265     symbolP = symbol_find_or_make(name);
266     *p = c;
267     if (S_IS_DEFINED(symbolP)) {
268         as_bad("Ignoring attempt to re-define symbol");
269         ignore_rest_of_line();
270         return;
271     }
272     if (S_GET_VALUE(symbolP) != 0) {
273         if (S_GET_VALUE(symbolP) != temp) {
274             as_warn("Length of .comm \"%s\" is already %d. Not changed to %d.",
275                     S_GET_NAME(symbolP), S_GET_VALUE(symbolP), temp);
276         }
277     } else {
278         S_SET_VALUE(symbolP, temp);
279         S_SET_EXTERNAL(symbolP);
280     }
281     know(symbolP->sy_frag == &zero_address_frag);
282     if (strncmp(input_line_pointer, ",\"bss\"", 6) != 0
283         && strncmp(input_line_pointer, ",\"data\"", 7) != 0) {
284         p=input_line_pointer;
285         while(*p && *p!='\n')
286             p++;
287         c= *p;
288         *p='\0';
289         as_bad("bad .common segment: `%s'", input_line_pointer);
290         *p=c;
291         return;
292     }
293     input_line_pointer += 6 + (input_line_pointer[2] == 'd'); /* Skip either */
294     demand_empty_rest_of_line();
295     return;
296 } /* s_common() */
297
298 static void s_seg() {
299         
300         if (strncmp(input_line_pointer, "\"text\"", 6) == 0) {
301             input_line_pointer += 6;
302             s_text();
303             return;
304         }
305     if (strncmp(input_line_pointer, "\"data\"", 6) == 0) {
306         input_line_pointer += 6;
307         s_data();
308         return;
309     }
310     if (strncmp(input_line_pointer, "\"data1\"", 7) == 0) {
311         input_line_pointer += 7;
312         s_data1();
313         return;
314     }
315     if (strncmp(input_line_pointer, "\"bss\"", 5) == 0) {
316         input_line_pointer += 5;
317         /* We only support 2 segments -- text and data -- for now, so
318            things in the "bss segment" will have to go into data for now.
319            You can still allocate SEG_BSS stuff with .lcomm or .reserve. */
320         subseg_new(SEG_DATA, 255);      /* FIXME-SOMEDAY */
321         return;
322     }
323     as_bad("Unknown segment type");
324     demand_empty_rest_of_line();
325     return;
326 } /* s_seg() */
327
328 static void s_data1() {
329         subseg_new(SEG_DATA, 1);
330     demand_empty_rest_of_line();
331     return;
332 } /* s_data1() */
333
334 static void s_proc() {
335         extern char is_end_of_line[];
336     
337     while (!is_end_of_line[*input_line_pointer]) {
338         ++input_line_pointer;
339     }
340     ++input_line_pointer;
341     return;
342 } /* s_proc() */
343
344 /* This function is called once, at assembler startup time.  It should
345    set up all the tables, etc. that the MD part of the assembler will need. */
346 void md_begin() {
347         register char *retval = NULL;
348     int lose = 0;
349     register unsigned int i = 0;
350     
351     op_hash = hash_new();
352     if (op_hash == NULL)
353     as_fatal("Virtual memory exhausted");
354     
355     while (i < NUMOPCODES) {
356         const char *name = sparc_opcodes[i].name;
357         retval = hash_insert(op_hash, name, &sparc_opcodes[i]);
358         if(retval != NULL && *retval != '\0') {
359             fprintf (stderr, "internal error: can't hash `%s': %s\n",
360                      sparc_opcodes[i].name, retval);
361             lose = 1;
362         }
363         do
364         {
365             if (sparc_opcodes[i].match & sparc_opcodes[i].lose) {
366                 fprintf (stderr, "internal error: losing opcode: `%s' \"%s\"\n",
367                          sparc_opcodes[i].name, sparc_opcodes[i].args);
368                 lose = 1;
369             }
370             ++i;
371         } while (i < NUMOPCODES
372                  && !strcmp(sparc_opcodes[i].name, name));
373     }
374     
375     if (lose)
376     as_fatal("Broken assembler.  No assembly attempted.");
377     
378     for (i = '0'; i < '8'; ++i)
379     octal[i] = 1;
380     for (i = '0'; i <= '9'; ++i)
381     toHex[i] = i - '0';
382     for (i = 'a'; i <= 'f'; ++i)
383     toHex[i] = i + 10 - 'a';
384     for (i = 'A'; i <= 'F'; ++i)
385     toHex[i] = i + 10 - 'A';
386 } /* md_begin() */
387
388 void md_end() {
389         return;
390 } /* md_end() */
391
392 void md_assemble(str)
393     char *str;
394 {
395     char *toP;
396     int rsd;
397     
398     know(str);
399     sparc_ip(str);
400     
401     /* See if "set" operand is absolute and small; skip sethi if so. */
402     if (special_case == SPECIAL_CASE_SET && the_insn.exp.X_seg == SEG_ABSOLUTE) {
403         if (the_insn.exp.X_add_number >= -(1<<12)
404             && the_insn.exp.X_add_number <   (1<<12)) {
405             the_insn.opcode = 0x80102000                /* or %g0,imm,... */
406                 | (the_insn.opcode & 0x3E000000)        /* dest reg */
407                     | (the_insn.exp.X_add_number & 0x1FFF); /* imm */
408             special_case = 0;           /* No longer special */
409             the_insn.reloc = NO_RELOC;  /* No longer relocated */
410         }
411     }
412     
413     toP = frag_more(4);
414     /* put out the opcode */
415     md_number_to_chars(toP, the_insn.opcode, 4);
416     
417     /* put out the symbol-dependent stuff */
418     if (the_insn.reloc != NO_RELOC) {
419         fix_new(frag_now,                           /* which frag */
420                 (toP - frag_now->fr_literal), /* where */
421                 4,                                  /* size */
422                 the_insn.exp.X_add_symbol,
423                 the_insn.exp.X_subtract_symbol,
424                 the_insn.exp.X_add_number,
425                 the_insn.pcrel,
426                 the_insn.reloc);
427     }
428     switch (special_case) {
429         
430     case SPECIAL_CASE_SET:
431         special_case = 0;
432         assert(the_insn.reloc == RELOC_HI22);
433         /* See if "set" operand has no low-order bits; skip OR if so. */
434         if (the_insn.exp.X_seg == SEG_ABSOLUTE
435             && ((the_insn.exp.X_add_number & 0x3FF) == 0))
436             return;
437         toP = frag_more(4);
438         rsd = (the_insn.opcode >> 25) & 0x1f;
439         the_insn.opcode = 0x80102000 | (rsd << 25) | (rsd << 14);
440         md_number_to_chars(toP, the_insn.opcode, 4);
441         fix_new(frag_now,                           /* which frag */
442                 (toP - frag_now->fr_literal),       /* where */
443                 4,                                  /* size */
444                 the_insn.exp.X_add_symbol,
445                 the_insn.exp.X_subtract_symbol,
446                 the_insn.exp.X_add_number,
447                 the_insn.pcrel,
448                 RELOC_LO10);
449         return;
450         
451     case SPECIAL_CASE_FDIV:
452         /* According to information leaked from Sun, the "fdiv" instructions
453            on early SPARC machines would produce incorrect results sometimes.
454            The workaround is to add an fmovs of the destination register to
455            itself just after the instruction.  This was true on machines
456            with Weitek 1165 float chips, such as the Sun-4/260 and /280. */
457         special_case = 0;
458         assert(the_insn.reloc == NO_RELOC);
459         toP = frag_more(4);
460         rsd = (the_insn.opcode >> 25) & 0x1f;
461         the_insn.opcode = 0x81A00020 | (rsd << 25) | rsd;  /* fmovs dest,dest */
462         md_number_to_chars(toP, the_insn.opcode, 4);
463         return;
464         
465     case 0:
466         return;
467         
468     default:
469         as_fatal("failed sanity check.");
470     }
471 } /* md_assemble() */
472
473 static void sparc_ip(str)
474     char *str;
475 {
476     char *error_message = "";
477     char *s;
478     const char *args;
479     char c;
480     struct sparc_opcode *insn;
481     char *argsStart;
482     unsigned long opcode;
483     unsigned int mask = 0;
484     int match = 0;
485     int comma = 0;
486     
487     for (s = str; islower(*s) || (*s >= '0' && *s <= '3'); ++s)
488         ;
489     switch (*s) {
490         
491     case '\0':
492         break;
493         
494     case ',':
495         comma = 1;
496         
497         /*FALLTHROUGH */
498         
499     case ' ':
500         *s++ = '\0';
501         break;
502         
503     default:
504         as_bad("Unknown opcode: `%s'", str);
505         exit(1);
506     }
507     if ((insn = (struct sparc_opcode *) hash_find(op_hash, str)) == NULL) {
508         as_bad("Unknown opcode: `%s'", str);
509         return;
510     }
511     if (comma) {
512         *--s = ',';
513     }
514     argsStart = s;
515     for (;;) {
516         opcode = insn->match;
517         bzero(&the_insn, sizeof(the_insn));
518         the_insn.reloc = NO_RELOC;
519         
520         /*
521          * Build the opcode, checking as we go to make
522          * sure that the operands match
523          */
524         for (args = insn->args; ; ++args) {
525             switch (*args) {
526                 
527             case 'M':
528             case 'm':
529                 if (strncmp(s, "%asr", 4) == 0) {
530                     s += 4;
531                     
532                     if (isdigit(*s)) {
533                         long num = 0;
534                         
535                         while (isdigit(*s)) {
536                             num = num*10 + *s-'0';
537                             ++s;
538                         }
539                         
540                         if (num < 16 || 31 < num) {
541                             error_message = ": asr number must be between 15 and 31";
542                             goto error;
543                         } /* out of range */
544                         
545                         opcode |= (*args == 'M' ? RS1(num) : RD(num));
546                         continue;
547                     } else {
548                         error_message = ": expecting %asrN";
549                         goto error;
550                     } /* if %asr followed by a number. */
551                     
552                 } /* if %asr */
553                 break;
554                 
555                 /* start-sanitize-v9 */
556 #ifndef NO_V9
557             case 'I':
558                 the_insn.reloc = RELOC_11;
559                 goto immediate;
560                 
561             case 'k':
562                 the_insn.reloc = RELOC_WDISP2_14;
563                 the_insn.pcrel = 1;
564                 goto immediate;
565                 
566             case 'G':
567                 the_insn.reloc = RELOC_WDISP19;
568                 the_insn.pcrel = 1;
569                 goto immediate;
570                 
571             case 'N':
572                 if (*s == 'p' && s[1] == 'n') {
573                     s += 2;
574                     continue;
575                 }
576                 break;
577                 
578             case 'T':
579                 if (*s == 'p' && s[1] == 't') {
580                     s += 2;
581                     continue;
582                 }
583                 break;
584                 
585             case 'Y':
586                 if (strncmp(s, "%amr", 4) == 0) {
587                     s += 4;
588                     continue;
589                 }
590                 break;
591                 
592             case 'z':
593                 if (*s == ' ') {
594                     ++s;
595                 }
596                 if (strncmp(s, "icc", 3) == 0) {
597                     s += 3;
598                     continue;
599                 }
600                 break;
601                 
602             case 'Z':
603                 if (*s == ' ') {
604                     ++s;
605                 }
606                 if (strncmp(s, "xcc", 3) == 0) {
607                     s += 3;
608                     continue;
609                 }
610                 break;
611                 
612             case '6':
613                 if (*s == ' ') {
614                     ++s;
615                 }
616                 if (strncmp(s, "fcc0", 4) == 0) {
617                     s += 4;
618                     continue;
619                 }
620                 break;
621                 
622             case '7':
623                 if (*s == ' ') {
624                     ++s;
625                 }
626                 if (strncmp(s, "fcc1", 4) == 0) {
627                     s += 4;
628                     continue;
629                 }
630                 break;
631                 
632             case '8':
633                 if (*s == ' ') {
634                     ++s;
635                 }
636                 if (strncmp(s, "fcc2", 4) == 0) {
637                     s += 4;
638                     continue;
639                 }
640                 break;
641                 
642             case '9':
643                 if (*s == ' ') {
644                     ++s;
645                 }
646                 if (strncmp(s, "fcc3", 4) == 0) {
647                     s += 4;
648                     continue;
649                 }
650                 break;
651                 
652             case 'P':
653                 if (strncmp(s, "%pc", 3) == 0) {
654                     s += 3;
655                     continue;
656                 }
657                 break;
658                 
659             case 'E':
660                 if (strncmp(s, "%modes", 6) == 0) {
661                     s += 6;
662                     continue;
663                 }
664                 break;
665                 
666             case 'W':
667                 if (strncmp(s, "%tick", 5) == 0) {
668                     s += 5;
669                     continue;
670                 }
671                 break;
672 #endif /* NO_V9 */
673                 /* end-sanitize-v9 */
674                 
675             case '\0':  /* end of args */
676                 if (*s == '\0') {
677                     match = 1;
678                 }
679                 break;
680                 
681             case '+':
682                 if (*s == '+') {
683                     ++s;
684                     continue;
685                 }
686                 if (*s == '-') {
687                     continue;
688                 }
689                 break;
690                 
691             case '[':   /* these must match exactly */
692             case ']':
693             case ',':
694             case ' ':
695                 if (*s++ == *args)
696                     continue;
697                 break;
698                 
699             case '#':   /* must be at least one digit */
700                 if (isdigit(*s++)) {
701                     while (isdigit(*s)) {
702                         ++s;
703                     }
704                     continue;
705                 }
706                 break;
707                 
708             case 'C':   /* coprocessor state register */
709                 if (strncmp(s, "%csr", 4) == 0) {
710                     s += 4;
711                     continue;
712                 }
713                 break;
714                 
715             case 'b':    /* next operand is a coprocessor register */
716             case 'c':
717             case 'D':
718                 if (*s++ == '%' && *s++ == 'c' && isdigit(*s)) {
719                     mask = *s++;
720                     if (isdigit(*s)) {
721                         mask = 10 * (mask - '0') + (*s++ - '0');
722                         if (mask >= 32) {
723                             break;
724                         }
725                     } else {
726                         mask -= '0';
727                     }
728                     switch (*args) {
729                         
730                     case 'b':
731                         opcode |= mask << 14;
732                         continue;
733                         
734                     case 'c':
735                         opcode |= mask;
736                         continue;
737                         
738                     case 'D':
739                         opcode |= mask << 25;
740                         continue;
741                     }
742                 }
743                 break;
744                 
745             case 'r':   /* next operand must be a register */
746             case '1':
747             case '2':
748             case 'd':
749                 if (*s++ == '%') {
750                     switch (c = *s++) {
751                         
752                     case 'f':   /* frame pointer */
753                         if (*s++ == 'p') {
754                             mask = 0x1e;
755                             break;
756                         }
757                         goto error;
758                         
759                     case 'g':   /* global register */
760                         if (isoctal(c = *s++)) {
761                             mask = c - '0';
762                             break;
763                         }
764                         goto error;
765                         
766                     case 'i':   /* in register */
767                         if (isoctal(c = *s++)) {
768                             mask = c - '0' + 24;
769                             break;
770                         }
771                         goto error;
772                         
773                     case 'l':   /* local register */
774                         if (isoctal(c = *s++)) {
775                             mask= (c - '0' + 16) ;
776                             break;
777                         }
778                         goto error;
779                         
780                     case 'o':   /* out register */
781                         if (isoctal(c = *s++)) {
782                             mask= (c - '0' + 8) ;
783                             break;
784                         }
785                         goto error;
786                         
787                     case 's':   /* stack pointer */
788                         if (*s++ == 'p') {
789                             mask= 0xe;
790                             break;
791                         }
792                         goto error;
793                         
794                     case 'r': /* any register */
795                         if (!isdigit(c = *s++)) {
796                             goto error;
797                         }
798                         /* FALLTHROUGH */
799                     case '0': case '1': case '2': case '3': case '4':
800                     case '5': case '6': case '7': case '8': case '9':
801                         if (isdigit(*s)) {
802                             if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32) {
803                                 goto error;
804                             }
805                         } else {
806                             c -= '0';
807                         }
808                         mask= c;
809                         break;
810                         
811                     default:
812                         goto error;
813                     }
814                     /*
815                      * Got the register, now figure out where
816                      * it goes in the opcode.
817                      */
818                     switch (*args) {
819                         
820                     case '1':
821                         opcode |= mask << 14;
822                         continue;
823                         
824                     case '2':
825                         opcode |= mask;
826                         continue;
827                         
828                     case 'd':
829                         opcode |= mask << 25;
830                         continue;
831                         
832                     case 'r':
833                         opcode |= (mask << 25) | (mask << 14);
834                         continue;
835                     }
836                 }
837                 break;
838                 
839                 /* start-sanitize-v9 */
840 #ifndef NO_V9
841             case 'j':
842             case 'u':
843             case 'U':
844 #endif /* NO_V9 */
845                 /* end-sanitize-v9 */
846             case 'e': /* next operand is a floating point register */
847             case 'v':
848             case 'V':
849                 
850             case 'f':
851             case 'B':
852             case 'R':
853                 
854             case 'g':
855             case 'H':
856             case 'J': {
857                 char format;
858                 
859                 if (*s++ == '%'
860                     
861                     /* start-sanitize-v9 */
862 #ifndef NO_V9
863                     && ((format = *s) == 'f'
864                         || *s == 'd'
865                         || *s == 'q')
866 #else
867                     /* end-sanitize-v9 */
868                     && ((format = *s) == 'f')
869                     
870                     /* start-sanitize-v9 */
871 #endif /* NO_V9 */
872                     /* end-sanitize-v9 */
873                     && isdigit(*++s)) {
874                     
875                     
876                     
877                     for (mask = 0; isdigit(*s); ++s) {
878                         mask = 10 * mask + (*s - '0');
879                     } /* read the number */
880                     
881                     if ((*args == 'u'
882                          || *args == 'v'
883                          || *args == 'B'
884                          || *args == 'H')
885                         && (mask & 1)) {
886                         break;
887                     } /* register must be even numbered */
888                     
889                     if ((*args == 'U'
890                          || *args == 'V'
891                          || *args == 'R'
892                          || *args == 'J')
893                         && (mask & 3)) {
894                         break;
895                     } /* register must be multiple of 4 */
896                     
897                     if (format == 'f') {
898                         if (mask >= 32) {
899                             error_message = ": There are only 32 f registers; [0-31]";
900                             goto error;
901                         } /* on error */
902                         /* start-sanitize-v9 */
903 #ifndef NO_V9
904                     } else {
905                         if (format == 'd') {
906                             if (mask >= 64) {
907                                 error_message = ": There are only 32 d registers [0, 2, ... 62].";
908                                 goto error;
909                             } else if (mask & 1) {
910                                 error_message = ": Only even numbered d registers exist.";
911                                 goto error;
912                             } /* on error */
913                             
914                         } else if (format == 'q') {
915                             if (mask >= 64) {
916                                 error_message =
917                                     ": There are only 16 q registers [0, 4, ... 60].";
918                                 goto error;
919                             } else if (mask & 3) {
920                                 error_message =
921                                     ": Only q registers evenly divisible by four exist.";
922                                 goto error;
923                             } /* on error */
924                         } else {
925                             know(0);
926                         } /* depending on format */
927                         
928                         if (mask >= 32) {
929                             mask -= 31;
930                         } /* wrap high bit */
931 #endif /* NO_V9 */
932                         /* end-sanitize-v9 */
933                     } /* if not an 'f' register. */
934                 } /* on error */
935                 
936                 switch (*args) {
937                     /* start-sanitize-v9 */
938 #ifndef NO_V9
939                 case 'j':
940                 case 'u':
941                 case 'U':
942                     opcode |= (mask & 0x1f) << 9;
943                     continue;
944 #endif /* NO_V9 */
945                     /* end-sanitize-v9 */
946                     
947                 case 'v':
948                 case 'V':
949                 case 'e':
950                     opcode |= RS1(mask);
951                     continue;
952                     
953                     
954                 case 'f':
955                 case 'B':
956                 case 'R':
957                     opcode |= RS2(mask);
958                     continue;
959                     
960                 case 'g':
961                 case 'H':
962                 case 'J':
963                     opcode |= RD(mask);
964                     continue;
965                 } /* pack it in. */
966                 
967                 know(0);
968                 break;
969             } /* float arg */
970                 
971             case 'F':
972                 if (strncmp(s, "%fsr", 4) == 0) {
973                     s += 4;
974                     continue;
975                 }
976                 break;
977                 
978             case 'h': /* high 22 bits */
979                 the_insn.reloc = RELOC_HI22;
980                 goto immediate;
981                 
982             case 'l': /* 22 bit PC relative immediate */
983                 the_insn.reloc = RELOC_WDISP22;
984                 the_insn.pcrel = 1;
985                 goto immediate;
986                 
987             case 'L': /* 30 bit immediate */
988                 the_insn.reloc = RELOC_WDISP30;
989                 the_insn.pcrel = 1;
990                 goto immediate;
991                 
992             case 'n': /* 22 bit immediate */
993                 the_insn.reloc = RELOC_22;
994                 goto immediate;
995                 
996             case 'i':   /* 13 bit immediate */
997                 the_insn.reloc = RELOC_BASE13;
998                 
999                 /*FALLTHROUGH */
1000                 
1001             immediate:
1002                 if(*s==' ')
1003                     s++;
1004                 if (*s == '%') {
1005                     if ((c = s[1]) == 'h' && s[2] == 'i') {
1006                         the_insn.reloc = RELOC_HI22;
1007                         s+=3;
1008                     } else if (c == 'l' && s[2] == 'o') {
1009                         the_insn.reloc = RELOC_LO10;
1010                         s+=3;
1011                         /* start-sanitize-v9 */
1012 #ifndef NO_V9
1013                     } else if (c == 'h'
1014                                && s[2] == 'h'
1015                                && s[3] == 'i') {
1016                         the_insn.reloc = RELOC_HHI22;
1017                         s += 4;
1018                         
1019                     } else if (c == 'h'
1020                                && s[2] == 'l'
1021                                && s[3] == 'o') {
1022                         the_insn.reloc = RELOC_HLO10;
1023                         s += 4;
1024 #endif /* NO_V9 */
1025                         /* end-sanitize-v9 */
1026                     } else
1027                         break;
1028                 }
1029                 /* Note that if the getExpression() fails, we
1030                    will still have created U entries in the
1031                    symbol table for the 'symbols' in the input
1032                    string.  Try not to create U symbols for
1033                    registers, etc. */ 
1034             {
1035                 /* This stuff checks to see if the
1036                    expression ends in +%reg If it does,
1037                    it removes the register from the
1038                    expression, and re-sets 's' to point
1039                    to the right place */
1040                 
1041                 char *s1;
1042                 
1043                 for (s1 = s; *s1 && *s1 != ',' && *s1 != ']'; s1++) ;;
1044                 
1045                 if (s1 != s && isdigit(s1[-1])) {
1046                     if(s1[-2] == '%' && s1[-3] == '+') {
1047                         s1 -= 3;
1048                         *s1 = '\0';
1049                         (void) getExpression(s);
1050                         *s1 = '+';
1051                         s = s1;
1052                         continue;
1053                     } else if (strchr("goli0123456789", s1[-2]) && s1[-3] == '%' && s1[-4] == '+') {
1054                         s1 -= 4;
1055                         *s1 = '\0';
1056                         (void) getExpression(s);
1057                         *s1 = '+';
1058                         s = s1;
1059                         continue;
1060                     }
1061                 }
1062             }
1063                 (void)getExpression(s);
1064                 s = expr_end;
1065                 continue;
1066                 
1067             case 'a':
1068                 if (*s++ == 'a') {
1069                     opcode |= ANNUL;
1070                     continue;
1071                 }
1072                 break;
1073                 
1074             case 'A': {
1075                 char *push = input_line_pointer;
1076                 expressionS e;
1077                 
1078                 input_line_pointer = s;
1079                 
1080                 if (expression(&e) == SEG_ABSOLUTE) {
1081                     opcode |= e.X_add_number << 5;
1082                     s = input_line_pointer;
1083                     input_line_pointer = push;
1084                     continue;
1085                 } /* if absolute */
1086                 
1087                 break;
1088             } /* alternate space */
1089                 
1090             case 'p':
1091                 if (strncmp(s, "%psr", 4) == 0) {
1092                     s += 4;
1093                     continue;
1094                 }
1095                 break;
1096                 
1097             case 'q':   /* floating point queue */
1098                 if (strncmp(s, "%fq", 3) == 0) {
1099                     s += 3;
1100                     continue;
1101                 }
1102                 break;
1103                 
1104             case 'Q':   /* coprocessor queue */
1105                 if (strncmp(s, "%cq", 3) == 0) {
1106                     s += 3;
1107                     continue;
1108                 }
1109                 break;
1110                 
1111             case 'S':
1112                 if (strcmp(str, "set") == 0) {
1113                     special_case = SPECIAL_CASE_SET;
1114                     continue;
1115                 } else if (strncmp(str, "fdiv", 4) == 0) {
1116                     special_case = SPECIAL_CASE_FDIV;
1117                     continue;
1118                 }
1119                 break;
1120                 
1121             case 't':
1122                 if (strncmp(s, "%tbr", 4) != 0)
1123                     break;
1124                 s += 4;
1125                 continue;
1126                 
1127             case 'w':
1128                 if (strncmp(s, "%wim", 4) != 0)
1129                     break;
1130                 s += 4;
1131                 continue;
1132                 
1133             case 'y':
1134                 if (strncmp(s, "%y", 2) != 0)
1135                     break;
1136                 s += 2;
1137                 continue;
1138                 
1139             default:
1140                 as_fatal("failed sanity check.");
1141             } /* switch on arg code */
1142             break;
1143         } /* for each arg that we expect */
1144     error:
1145         if (match == 0) {
1146             /* Args don't match. */
1147             if (((unsigned) (&insn[1] - sparc_opcodes)) < NUMOPCODES
1148                 && !strcmp(insn->name, insn[1].name)) {
1149                 ++insn;
1150                 s = argsStart;
1151                 continue;
1152             } else {
1153                 as_bad("Illegal operands%s", error_message);
1154                 return;
1155             }
1156         } else {
1157             if (insn->architecture > current_architecture) {
1158                 if (!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, -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  */
1710 /* start-sanitize-v9 */
1711 /* There is also a -Av9 architecture option.  xoxorich. */
1712 /* end-sanitize-v9 */
1713 int md_parse_option(argP, cntP, vecP)
1714     char **argP;
1715     int *cntP;
1716     char ***vecP;
1717 {
1718     char *p;
1719     const char **arch;
1720     
1721     if (!strcmp(*argP,"bump")){
1722         warn_on_bump = 1;
1723         
1724     } else if (**argP == 'A'){
1725         p = (*argP) + 1;
1726         
1727         for (arch = architecture_pname; *arch != NULL; ++arch){
1728             if (strcmp(p, *arch) == 0){
1729                 break;
1730             } /* found a match */
1731         } /* walk the pname table */
1732         
1733         if (*arch == NULL){
1734             as_bad("unknown architecture: %s", p);
1735         } else {
1736             current_architecture = (enum sparc_architecture) (arch - architecture_pname);
1737             architecture_requested = 1;
1738         }
1739     } else {
1740         /* Unknown option */
1741         (*argP)++;
1742         return 0;
1743     }
1744     **argP = '\0';      /* Done parsing this switch */
1745     return 1;
1746 } /* md_parse_option() */
1747
1748 /* We have no need to default values of symbols. */
1749
1750 /* ARGSUSED */
1751 symbolS *md_undefined_symbol(name)
1752     char *name;
1753 {
1754     return 0;
1755 } /* md_undefined_symbol() */
1756
1757 /* Parse an operand that is machine-specific.
1758    We just return without modifying the expression if we have nothing
1759    to do. */
1760
1761 /* ARGSUSED */
1762 void md_operand(expressionP)
1763     expressionS *expressionP;
1764 {
1765 } /* md_operand() */
1766
1767 /* Round up a section size to the appropriate boundary. */
1768 long md_section_align (segment, size)
1769     segT segment;
1770     long size;
1771 {
1772     return (size + 7) & ~7;     /* Round all sects to multiple of 8 */
1773 } /* md_section_align() */
1774
1775 /* Exactly what point is a PC-relative offset relative TO?
1776    On the sparc, they're relative to the address of the offset, plus
1777    its size.  This gets us to the following instruction.
1778    (??? Is this right?  FIXME-SOON) */
1779 long md_pcrel_from(fixP)
1780     fixS *fixP;
1781 {
1782     return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
1783 } /* md_pcrel_from() */
1784
1785 void tc_aout_pre_write_hook(headers)
1786     object_headers *headers;
1787 {
1788     H_SET_VERSION(headers, 1);
1789     return;
1790 } /* tc_aout_pre_write_hook() */
1791
1792 /*
1793  * Local Variables:
1794  * comment-column: 0
1795  * fill-column: 131
1796  * End:
1797  */
1798
1799 /* end of tc-sparc.c */