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