xref: /openbsd-src/gnu/usr.bin/binutils-2.17/gas/config/tc-sparc.c (revision f1294bec12c5e236bc62a19a1b7ec7fc9663b4e1)
13d8817e4Smiod /* tc-sparc.c -- Assemble for the SPARC
23d8817e4Smiod    Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
33d8817e4Smiod    1999, 2000, 2001, 2002, 2003, 2004, 2005
43d8817e4Smiod    Free Software Foundation, Inc.
53d8817e4Smiod    This file is part of GAS, the GNU Assembler.
63d8817e4Smiod 
73d8817e4Smiod    GAS is free software; you can redistribute it and/or modify
83d8817e4Smiod    it under the terms of the GNU General Public License as published by
93d8817e4Smiod    the Free Software Foundation; either version 2, or (at your option)
103d8817e4Smiod    any later version.
113d8817e4Smiod 
123d8817e4Smiod    GAS is distributed in the hope that it will be useful,
133d8817e4Smiod    but WITHOUT ANY WARRANTY; without even the implied warranty of
143d8817e4Smiod    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
153d8817e4Smiod    GNU General Public License for more details.
163d8817e4Smiod 
173d8817e4Smiod    You should have received a copy of the GNU General Public
183d8817e4Smiod    License along with GAS; see the file COPYING.  If not, write
193d8817e4Smiod    to the Free Software Foundation, 51 Franklin Street - Fifth Floor,
203d8817e4Smiod    Boston, MA 02110-1301, USA.  */
213d8817e4Smiod 
223d8817e4Smiod #include <stdio.h>
233d8817e4Smiod 
243d8817e4Smiod #include "as.h"
253d8817e4Smiod #include "safe-ctype.h"
263d8817e4Smiod #include "subsegs.h"
273d8817e4Smiod 
283d8817e4Smiod #include "opcode/sparc.h"
293d8817e4Smiod #include "dw2gencfi.h"
303d8817e4Smiod 
313d8817e4Smiod #ifdef OBJ_ELF
323d8817e4Smiod #include "elf/sparc.h"
333d8817e4Smiod #include "dwarf2dbg.h"
343d8817e4Smiod #endif
353d8817e4Smiod 
363d8817e4Smiod /* Some ancient Sun C compilers would not take such hex constants as
373d8817e4Smiod    unsigned, and would end up sign-extending them to form an offsetT,
383d8817e4Smiod    so use these constants instead.  */
393d8817e4Smiod #define U0xffffffff ((((unsigned long) 1 << 16) << 16) - 1)
403d8817e4Smiod #define U0x80000000 ((((unsigned long) 1 << 16) << 15))
413d8817e4Smiod 
423d8817e4Smiod static struct sparc_arch *lookup_arch PARAMS ((char *));
433d8817e4Smiod static void init_default_arch PARAMS ((void));
443d8817e4Smiod static int sparc_ip PARAMS ((char *, const struct sparc_opcode **));
453d8817e4Smiod static int in_signed_range PARAMS ((bfd_signed_vma, bfd_signed_vma));
463d8817e4Smiod static int in_bitfield_range PARAMS ((bfd_signed_vma, bfd_signed_vma));
473d8817e4Smiod static int sparc_ffs PARAMS ((unsigned int));
483d8817e4Smiod static void synthetize_setuw PARAMS ((const struct sparc_opcode *));
493d8817e4Smiod static void synthetize_setsw PARAMS ((const struct sparc_opcode *));
503d8817e4Smiod static void synthetize_setx PARAMS ((const struct sparc_opcode *));
513d8817e4Smiod static bfd_vma BSR PARAMS ((bfd_vma, int));
523d8817e4Smiod static int cmp_reg_entry PARAMS ((const PTR, const PTR));
533d8817e4Smiod static int parse_keyword_arg PARAMS ((int (*) (const char *), char **, int *));
543d8817e4Smiod static int parse_const_expr_arg PARAMS ((char **, int *));
553d8817e4Smiod static int get_expression PARAMS ((char *str));
563d8817e4Smiod 
573d8817e4Smiod /* Default architecture.  */
583d8817e4Smiod /* ??? The default value should be V8, but sparclite support was added
593d8817e4Smiod    by making it the default.  GCC now passes -Asparclite, so maybe sometime in
603d8817e4Smiod    the future we can set this to V8.  */
613d8817e4Smiod #ifndef DEFAULT_ARCH
623d8817e4Smiod #define DEFAULT_ARCH "sparclite"
633d8817e4Smiod #endif
643d8817e4Smiod static char *default_arch = DEFAULT_ARCH;
653d8817e4Smiod 
663d8817e4Smiod /* Non-zero if the initial values of `max_architecture' and `sparc_arch_size'
673d8817e4Smiod    have been set.  */
683d8817e4Smiod static int default_init_p;
693d8817e4Smiod 
703d8817e4Smiod /* Current architecture.  We don't bump up unless necessary.  */
713d8817e4Smiod static enum sparc_opcode_arch_val current_architecture = SPARC_OPCODE_ARCH_V6;
723d8817e4Smiod 
733d8817e4Smiod /* The maximum architecture level we can bump up to.
743d8817e4Smiod    In a 32 bit environment, don't allow bumping up to v9 by default.
753d8817e4Smiod    The native assembler works this way.  The user is required to pass
763d8817e4Smiod    an explicit argument before we'll create v9 object files.  However, if
773d8817e4Smiod    we don't see any v9 insns, a v8plus object file is not created.  */
783d8817e4Smiod static enum sparc_opcode_arch_val max_architecture;
793d8817e4Smiod 
803d8817e4Smiod /* Either 32 or 64, selects file format.  */
813d8817e4Smiod static int sparc_arch_size;
823d8817e4Smiod /* Initial (default) value, recorded separately in case a user option
833d8817e4Smiod    changes the value before md_show_usage is called.  */
843d8817e4Smiod static int default_arch_size;
853d8817e4Smiod 
863d8817e4Smiod #ifdef OBJ_ELF
873d8817e4Smiod /* The currently selected v9 memory model.  Currently only used for
883d8817e4Smiod    ELF.  */
893d8817e4Smiod static enum { MM_TSO, MM_PSO, MM_RMO } sparc_memory_model = MM_RMO;
903d8817e4Smiod #endif
913d8817e4Smiod 
923d8817e4Smiod static int architecture_requested;
933d8817e4Smiod static int warn_on_bump;
943d8817e4Smiod 
953d8817e4Smiod /* If warn_on_bump and the needed architecture is higher than this
963d8817e4Smiod    architecture, issue a warning.  */
973d8817e4Smiod static enum sparc_opcode_arch_val warn_after_architecture;
983d8817e4Smiod 
993d8817e4Smiod /* Non-zero if as should generate error if an undeclared g[23] register
1003d8817e4Smiod    has been used in -64.  */
1013d8817e4Smiod static int no_undeclared_regs;
1023d8817e4Smiod 
1033d8817e4Smiod /* Non-zero if we should try to relax jumps and calls.  */
1043d8817e4Smiod static int sparc_relax;
1053d8817e4Smiod 
1063d8817e4Smiod /* Non-zero if we are generating PIC code.  */
1073d8817e4Smiod int sparc_pic_code;
1083d8817e4Smiod 
1093d8817e4Smiod /* Non-zero if we should give an error when misaligned data is seen.  */
1103d8817e4Smiod static int enforce_aligned_data;
1113d8817e4Smiod 
1123d8817e4Smiod extern int target_big_endian;
1133d8817e4Smiod 
1143d8817e4Smiod static int target_little_endian_data;
1153d8817e4Smiod 
1163d8817e4Smiod /* Symbols for global registers on v9.  */
1173d8817e4Smiod static symbolS *globals[8];
1183d8817e4Smiod 
1193d8817e4Smiod /* The dwarf2 data alignment, adjusted for 32 or 64 bit.  */
1203d8817e4Smiod int sparc_cie_data_alignment;
1213d8817e4Smiod 
1223d8817e4Smiod /* V9 and 86x have big and little endian data, but instructions are always big
1233d8817e4Smiod    endian.  The sparclet has bi-endian support but both data and insns have
1243d8817e4Smiod    the same endianness.  Global `target_big_endian' is used for data.
1253d8817e4Smiod    The following macro is used for instructions.  */
1263d8817e4Smiod #ifndef INSN_BIG_ENDIAN
1273d8817e4Smiod #define INSN_BIG_ENDIAN (target_big_endian \
1283d8817e4Smiod 			 || default_arch_type == sparc86x \
1293d8817e4Smiod 			 || SPARC_OPCODE_ARCH_V9_P (max_architecture))
1303d8817e4Smiod #endif
1313d8817e4Smiod 
1323d8817e4Smiod /* Handle of the OPCODE hash table.  */
1333d8817e4Smiod static struct hash_control *op_hash;
1343d8817e4Smiod 
1353d8817e4Smiod static int mylog2 PARAMS ((int));
1363d8817e4Smiod static void s_data1 PARAMS ((void));
1373d8817e4Smiod static void s_seg PARAMS ((int));
1383d8817e4Smiod static void s_proc PARAMS ((int));
1393d8817e4Smiod static void s_reserve PARAMS ((int));
1403d8817e4Smiod static void s_common PARAMS ((int));
1413d8817e4Smiod static void s_empty PARAMS ((int));
1423d8817e4Smiod static void s_uacons PARAMS ((int));
1433d8817e4Smiod static void s_ncons PARAMS ((int));
1443d8817e4Smiod #ifdef OBJ_ELF
1453d8817e4Smiod static void s_register PARAMS ((int));
1463d8817e4Smiod #endif
1473d8817e4Smiod 
1483d8817e4Smiod const pseudo_typeS md_pseudo_table[] =
1493d8817e4Smiod {
1503d8817e4Smiod   {"align", s_align_bytes, 0},	/* Defaulting is invalid (0).  */
1513d8817e4Smiod   {"common", s_common, 0},
1523d8817e4Smiod   {"empty", s_empty, 0},
1533d8817e4Smiod   {"global", s_globl, 0},
1543d8817e4Smiod   {"half", cons, 2},
1553d8817e4Smiod   {"nword", s_ncons, 0},
1563d8817e4Smiod   {"optim", s_ignore, 0},
1573d8817e4Smiod   {"proc", s_proc, 0},
1583d8817e4Smiod   {"reserve", s_reserve, 0},
1593d8817e4Smiod   {"seg", s_seg, 0},
1603d8817e4Smiod   {"skip", s_space, 0},
1613d8817e4Smiod   {"word", cons, 4},
1623d8817e4Smiod   {"xword", cons, 8},
1633d8817e4Smiod   {"uahalf", s_uacons, 2},
1643d8817e4Smiod   {"uaword", s_uacons, 4},
1653d8817e4Smiod   {"uaxword", s_uacons, 8},
1663d8817e4Smiod #ifdef OBJ_ELF
1673d8817e4Smiod   /* These are specific to sparc/svr4.  */
1683d8817e4Smiod   {"2byte", s_uacons, 2},
1693d8817e4Smiod   {"4byte", s_uacons, 4},
1703d8817e4Smiod   {"8byte", s_uacons, 8},
1713d8817e4Smiod   {"register", s_register, 0},
1723d8817e4Smiod #endif
1733d8817e4Smiod   {NULL, 0, 0},
1743d8817e4Smiod };
1753d8817e4Smiod 
1763d8817e4Smiod /* This array holds the chars that always start a comment.  If the
1773d8817e4Smiod    pre-processor is disabled, these aren't very useful.  */
1783d8817e4Smiod const char comment_chars[] = "!";	/* JF removed '|' from
1793d8817e4Smiod                                            comment_chars.  */
1803d8817e4Smiod 
1813d8817e4Smiod /* This array holds the chars that only start a comment at the beginning of
1823d8817e4Smiod    a line.  If the line seems to have the form '# 123 filename'
1833d8817e4Smiod    .line and .file directives will appear in the pre-processed output.  */
1843d8817e4Smiod /* Note that input_file.c hand checks for '#' at the beginning of the
1853d8817e4Smiod    first line of the input file.  This is because the compiler outputs
1863d8817e4Smiod    #NO_APP at the beginning of its output.  */
1873d8817e4Smiod /* Also note that comments started like this one will always
1883d8817e4Smiod    work if '/' isn't otherwise defined.  */
1893d8817e4Smiod const char line_comment_chars[] = "#";
1903d8817e4Smiod 
1913d8817e4Smiod const char line_separator_chars[] = ";";
1923d8817e4Smiod 
1933d8817e4Smiod /* Chars that can be used to separate mant from exp in floating point
1943d8817e4Smiod    nums.  */
1953d8817e4Smiod const char EXP_CHARS[] = "eE";
1963d8817e4Smiod 
1973d8817e4Smiod /* Chars that mean this number is a floating point constant.
1983d8817e4Smiod    As in 0f12.456
1993d8817e4Smiod    or    0d1.2345e12  */
2003d8817e4Smiod const char FLT_CHARS[] = "rRsSfFdDxXpP";
2013d8817e4Smiod 
2023d8817e4Smiod /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
2033d8817e4Smiod    changed in read.c.  Ideally it shouldn't have to know about it at all,
2043d8817e4Smiod    but nothing is ideal around here.  */
2053d8817e4Smiod 
2063d8817e4Smiod #define isoctal(c)  ((unsigned) ((c) - '0') < 8)
2073d8817e4Smiod 
2083d8817e4Smiod struct sparc_it
2093d8817e4Smiod   {
2103d8817e4Smiod     char *error;
2113d8817e4Smiod     unsigned long opcode;
2123d8817e4Smiod     struct nlist *nlistp;
2133d8817e4Smiod     expressionS exp;
2143d8817e4Smiod     expressionS exp2;
2153d8817e4Smiod     int pcrel;
2163d8817e4Smiod     bfd_reloc_code_real_type reloc;
2173d8817e4Smiod   };
2183d8817e4Smiod 
2193d8817e4Smiod struct sparc_it the_insn, set_insn;
2203d8817e4Smiod 
2213d8817e4Smiod static void output_insn
2223d8817e4Smiod   PARAMS ((const struct sparc_opcode *, struct sparc_it *));
2233d8817e4Smiod 
2243d8817e4Smiod /* Table of arguments to -A.
2253d8817e4Smiod    The sparc_opcode_arch table in sparc-opc.c is insufficient and incorrect
2263d8817e4Smiod    for this use.  That table is for opcodes only.  This table is for opcodes
2273d8817e4Smiod    and file formats.  */
2283d8817e4Smiod 
2293d8817e4Smiod enum sparc_arch_types {v6, v7, v8, sparclet, sparclite, sparc86x, v8plus,
2303d8817e4Smiod 		       v8plusa, v9, v9a, v9b, v9_64};
2313d8817e4Smiod 
2323d8817e4Smiod static struct sparc_arch {
2333d8817e4Smiod   char *name;
2343d8817e4Smiod   char *opcode_arch;
2353d8817e4Smiod   enum sparc_arch_types arch_type;
2363d8817e4Smiod   /* Default word size, as specified during configuration.
2373d8817e4Smiod      A value of zero means can't be used to specify default architecture.  */
2383d8817e4Smiod   int default_arch_size;
2393d8817e4Smiod   /* Allowable arg to -A?  */
2403d8817e4Smiod   int user_option_p;
2413d8817e4Smiod } sparc_arch_table[] = {
2423d8817e4Smiod   { "v6", "v6", v6, 0, 1 },
2433d8817e4Smiod   { "v7", "v7", v7, 0, 1 },
2443d8817e4Smiod   { "v8", "v8", v8, 32, 1 },
2453d8817e4Smiod   { "sparclet", "sparclet", sparclet, 32, 1 },
2463d8817e4Smiod   { "sparclite", "sparclite", sparclite, 32, 1 },
2473d8817e4Smiod   { "sparc86x", "sparclite", sparc86x, 32, 1 },
2483d8817e4Smiod   { "v8plus", "v9", v9, 0, 1 },
2493d8817e4Smiod   { "v8plusa", "v9a", v9, 0, 1 },
2503d8817e4Smiod   { "v8plusb", "v9b", v9, 0, 1 },
2513d8817e4Smiod   { "v9", "v9", v9, 0, 1 },
2523d8817e4Smiod   { "v9a", "v9a", v9, 0, 1 },
2533d8817e4Smiod   { "v9b", "v9b", v9, 0, 1 },
2543d8817e4Smiod   /* This exists to allow configure.in/Makefile.in to pass one
2553d8817e4Smiod      value to specify both the default machine and default word size.  */
2563d8817e4Smiod   { "v9-64", "v9", v9, 64, 0 },
2573d8817e4Smiod   { NULL, NULL, v8, 0, 0 }
2583d8817e4Smiod };
2593d8817e4Smiod 
2603d8817e4Smiod /* Variant of default_arch */
2613d8817e4Smiod static enum sparc_arch_types default_arch_type;
2623d8817e4Smiod 
2633d8817e4Smiod static struct sparc_arch *
lookup_arch(name)2643d8817e4Smiod lookup_arch (name)
2653d8817e4Smiod      char *name;
2663d8817e4Smiod {
2673d8817e4Smiod   struct sparc_arch *sa;
2683d8817e4Smiod 
2693d8817e4Smiod   for (sa = &sparc_arch_table[0]; sa->name != NULL; sa++)
2703d8817e4Smiod     if (strcmp (sa->name, name) == 0)
2713d8817e4Smiod       break;
2723d8817e4Smiod   if (sa->name == NULL)
2733d8817e4Smiod     return NULL;
2743d8817e4Smiod   return sa;
2753d8817e4Smiod }
2763d8817e4Smiod 
2773d8817e4Smiod /* Initialize the default opcode arch and word size from the default
2783d8817e4Smiod    architecture name.  */
2793d8817e4Smiod 
2803d8817e4Smiod static void
init_default_arch()2813d8817e4Smiod init_default_arch ()
2823d8817e4Smiod {
2833d8817e4Smiod   struct sparc_arch *sa = lookup_arch (default_arch);
2843d8817e4Smiod 
2853d8817e4Smiod   if (sa == NULL
2863d8817e4Smiod       || sa->default_arch_size == 0)
2873d8817e4Smiod     as_fatal (_("Invalid default architecture, broken assembler."));
2883d8817e4Smiod 
2893d8817e4Smiod   max_architecture = sparc_opcode_lookup_arch (sa->opcode_arch);
2903d8817e4Smiod   if (max_architecture == SPARC_OPCODE_ARCH_BAD)
2913d8817e4Smiod     as_fatal (_("Bad opcode table, broken assembler."));
2923d8817e4Smiod   default_arch_size = sparc_arch_size = sa->default_arch_size;
2933d8817e4Smiod   default_init_p = 1;
2943d8817e4Smiod   default_arch_type = sa->arch_type;
2953d8817e4Smiod }
2963d8817e4Smiod 
2973d8817e4Smiod /* Called by TARGET_FORMAT.  */
2983d8817e4Smiod 
2993d8817e4Smiod const char *
sparc_target_format()3003d8817e4Smiod sparc_target_format ()
3013d8817e4Smiod {
3023d8817e4Smiod   /* We don't get a chance to initialize anything before we're called,
3033d8817e4Smiod      so handle that now.  */
3043d8817e4Smiod   if (! default_init_p)
3053d8817e4Smiod     init_default_arch ();
3063d8817e4Smiod 
3073d8817e4Smiod #ifdef OBJ_AOUT
308*d2386abeSmiod #if defined(TE_NetBSD) || defined(TE_OpenBSD)
3093d8817e4Smiod   return "a.out-sparc-netbsd";
3103d8817e4Smiod #else
3113d8817e4Smiod #ifdef TE_SPARCAOUT
3123d8817e4Smiod   if (target_big_endian)
3133d8817e4Smiod     return "a.out-sunos-big";
3143d8817e4Smiod   else if (default_arch_type == sparc86x && target_little_endian_data)
3153d8817e4Smiod     return "a.out-sunos-big";
3163d8817e4Smiod   else
3173d8817e4Smiod     return "a.out-sparc-little";
3183d8817e4Smiod #else
3193d8817e4Smiod   return "a.out-sunos-big";
3203d8817e4Smiod #endif
3213d8817e4Smiod #endif
3223d8817e4Smiod #endif
3233d8817e4Smiod 
3243d8817e4Smiod #ifdef OBJ_BOUT
3253d8817e4Smiod   return "b.out.big";
3263d8817e4Smiod #endif
3273d8817e4Smiod 
3283d8817e4Smiod #ifdef OBJ_COFF
3293d8817e4Smiod #ifdef TE_LYNX
3303d8817e4Smiod   return "coff-sparc-lynx";
3313d8817e4Smiod #else
3323d8817e4Smiod   return "coff-sparc";
3333d8817e4Smiod #endif
3343d8817e4Smiod #endif
3353d8817e4Smiod 
3363d8817e4Smiod #ifdef TE_VXWORKS
3373d8817e4Smiod   return "elf32-sparc-vxworks";
3383d8817e4Smiod #endif
3393d8817e4Smiod 
3403d8817e4Smiod #ifdef OBJ_ELF
3413d8817e4Smiod   return sparc_arch_size == 64 ? "elf64-sparc" : "elf32-sparc";
3423d8817e4Smiod #endif
3433d8817e4Smiod 
3443d8817e4Smiod   abort ();
3453d8817e4Smiod }
3463d8817e4Smiod 
3473d8817e4Smiod /* md_parse_option
3483d8817e4Smiod  *	Invocation line includes a switch not recognized by the base assembler.
3493d8817e4Smiod  *	See if it's a processor-specific option.  These are:
3503d8817e4Smiod  *
3513d8817e4Smiod  *	-bump
3523d8817e4Smiod  *		Warn on architecture bumps.  See also -A.
3533d8817e4Smiod  *
3543d8817e4Smiod  *	-Av6, -Av7, -Av8, -Asparclite, -Asparclet
3553d8817e4Smiod  *		Standard 32 bit architectures.
3563d8817e4Smiod  *	-Av9, -Av9a, -Av9b
3573d8817e4Smiod  *		Sparc64 in either a 32 or 64 bit world (-32/-64 says which).
3583d8817e4Smiod  *		This used to only mean 64 bits, but properly specifying it
3593d8817e4Smiod  *		complicated gcc's ASM_SPECs, so now opcode selection is
3603d8817e4Smiod  *		specified orthogonally to word size (except when specifying
3613d8817e4Smiod  *		the default, but that is an internal implementation detail).
3623d8817e4Smiod  *	-Av8plus, -Av8plusa, -Av8plusb
3633d8817e4Smiod  *		Same as -Av9{,a,b}.
3643d8817e4Smiod  *	-xarch=v8plus, -xarch=v8plusa, -xarch=v8plusb
3653d8817e4Smiod  *		Same as -Av8plus{,a,b} -32, for compatibility with Sun's
3663d8817e4Smiod  *		assembler.
3673d8817e4Smiod  *	-xarch=v9, -xarch=v9a, -xarch=v9b
3683d8817e4Smiod  *		Same as -Av9{,a,b} -64, for compatibility with Sun's
3693d8817e4Smiod  *		assembler.
3703d8817e4Smiod  *
3713d8817e4Smiod  *		Select the architecture and possibly the file format.
3723d8817e4Smiod  *		Instructions or features not supported by the selected
3733d8817e4Smiod  *		architecture cause fatal errors.
3743d8817e4Smiod  *
3753d8817e4Smiod  *		The default is to start at v6, and bump the architecture up
3763d8817e4Smiod  *		whenever an instruction is seen at a higher level.  In 32 bit
3773d8817e4Smiod  *		environments, v9 is not bumped up to, the user must pass
3783d8817e4Smiod  * 		-Av8plus{,a,b}.
3793d8817e4Smiod  *
3803d8817e4Smiod  *		If -bump is specified, a warning is printing when bumping to
3813d8817e4Smiod  *		higher levels.
3823d8817e4Smiod  *
3833d8817e4Smiod  *		If an architecture is specified, all instructions must match
3843d8817e4Smiod  *		that architecture.  Any higher level instructions are flagged
3853d8817e4Smiod  *		as errors.  Note that in the 32 bit environment specifying
3863d8817e4Smiod  *		-Av8plus does not automatically create a v8plus object file, a
3873d8817e4Smiod  *		v9 insn must be seen.
3883d8817e4Smiod  *
3893d8817e4Smiod  *		If both an architecture and -bump are specified, the
3903d8817e4Smiod  *		architecture starts at the specified level, but bumps are
3913d8817e4Smiod  *		warnings.  Note that we can't set `current_architecture' to
3923d8817e4Smiod  *		the requested level in this case: in the 32 bit environment,
3933d8817e4Smiod  *		we still must avoid creating v8plus object files unless v9
3943d8817e4Smiod  * 		insns are seen.
3953d8817e4Smiod  *
3963d8817e4Smiod  * Note:
3973d8817e4Smiod  *		Bumping between incompatible architectures is always an
3983d8817e4Smiod  *		error.  For example, from sparclite to v9.
3993d8817e4Smiod  */
4003d8817e4Smiod 
4013d8817e4Smiod #ifdef OBJ_ELF
4023d8817e4Smiod const char *md_shortopts = "A:K:VQ:sq";
4033d8817e4Smiod #else
4043d8817e4Smiod #ifdef OBJ_AOUT
4053d8817e4Smiod const char *md_shortopts = "A:k";
4063d8817e4Smiod #else
4073d8817e4Smiod const char *md_shortopts = "A:";
4083d8817e4Smiod #endif
4093d8817e4Smiod #endif
4103d8817e4Smiod struct option md_longopts[] = {
4113d8817e4Smiod #define OPTION_BUMP (OPTION_MD_BASE)
4123d8817e4Smiod   {"bump", no_argument, NULL, OPTION_BUMP},
4133d8817e4Smiod #define OPTION_SPARC (OPTION_MD_BASE + 1)
4143d8817e4Smiod   {"sparc", no_argument, NULL, OPTION_SPARC},
4153d8817e4Smiod #define OPTION_XARCH (OPTION_MD_BASE + 2)
4163d8817e4Smiod   {"xarch", required_argument, NULL, OPTION_XARCH},
4173d8817e4Smiod #ifdef OBJ_ELF
4183d8817e4Smiod #define OPTION_32 (OPTION_MD_BASE + 3)
4193d8817e4Smiod   {"32", no_argument, NULL, OPTION_32},
4203d8817e4Smiod #define OPTION_64 (OPTION_MD_BASE + 4)
4213d8817e4Smiod   {"64", no_argument, NULL, OPTION_64},
4223d8817e4Smiod #define OPTION_TSO (OPTION_MD_BASE + 5)
4233d8817e4Smiod   {"TSO", no_argument, NULL, OPTION_TSO},
4243d8817e4Smiod #define OPTION_PSO (OPTION_MD_BASE + 6)
4253d8817e4Smiod   {"PSO", no_argument, NULL, OPTION_PSO},
4263d8817e4Smiod #define OPTION_RMO (OPTION_MD_BASE + 7)
4273d8817e4Smiod   {"RMO", no_argument, NULL, OPTION_RMO},
4283d8817e4Smiod #endif
4293d8817e4Smiod #ifdef SPARC_BIENDIAN
4303d8817e4Smiod #define OPTION_LITTLE_ENDIAN (OPTION_MD_BASE + 8)
4313d8817e4Smiod   {"EL", no_argument, NULL, OPTION_LITTLE_ENDIAN},
4323d8817e4Smiod #define OPTION_BIG_ENDIAN (OPTION_MD_BASE + 9)
4333d8817e4Smiod   {"EB", no_argument, NULL, OPTION_BIG_ENDIAN},
4343d8817e4Smiod #endif
4353d8817e4Smiod #define OPTION_ENFORCE_ALIGNED_DATA (OPTION_MD_BASE + 10)
4363d8817e4Smiod   {"enforce-aligned-data", no_argument, NULL, OPTION_ENFORCE_ALIGNED_DATA},
4373d8817e4Smiod #define OPTION_LITTLE_ENDIAN_DATA (OPTION_MD_BASE + 11)
4383d8817e4Smiod   {"little-endian-data", no_argument, NULL, OPTION_LITTLE_ENDIAN_DATA},
4393d8817e4Smiod #ifdef OBJ_ELF
4403d8817e4Smiod #define OPTION_NO_UNDECLARED_REGS (OPTION_MD_BASE + 12)
4413d8817e4Smiod   {"no-undeclared-regs", no_argument, NULL, OPTION_NO_UNDECLARED_REGS},
4423d8817e4Smiod #define OPTION_UNDECLARED_REGS (OPTION_MD_BASE + 13)
4433d8817e4Smiod   {"undeclared-regs", no_argument, NULL, OPTION_UNDECLARED_REGS},
4443d8817e4Smiod #endif
4453d8817e4Smiod #define OPTION_RELAX (OPTION_MD_BASE + 14)
4463d8817e4Smiod   {"relax", no_argument, NULL, OPTION_RELAX},
4473d8817e4Smiod #define OPTION_NO_RELAX (OPTION_MD_BASE + 15)
4483d8817e4Smiod   {"no-relax", no_argument, NULL, OPTION_NO_RELAX},
4493d8817e4Smiod   {NULL, no_argument, NULL, 0}
4503d8817e4Smiod };
4513d8817e4Smiod 
4523d8817e4Smiod size_t md_longopts_size = sizeof (md_longopts);
4533d8817e4Smiod 
4543d8817e4Smiod int
md_parse_option(c,arg)4553d8817e4Smiod md_parse_option (c, arg)
4563d8817e4Smiod      int c;
4573d8817e4Smiod      char *arg;
4583d8817e4Smiod {
4593d8817e4Smiod   /* We don't get a chance to initialize anything before we're called,
4603d8817e4Smiod      so handle that now.  */
4613d8817e4Smiod   if (! default_init_p)
4623d8817e4Smiod     init_default_arch ();
4633d8817e4Smiod 
4643d8817e4Smiod   switch (c)
4653d8817e4Smiod     {
4663d8817e4Smiod     case OPTION_BUMP:
4673d8817e4Smiod       warn_on_bump = 1;
4683d8817e4Smiod       warn_after_architecture = SPARC_OPCODE_ARCH_V6;
4693d8817e4Smiod       break;
4703d8817e4Smiod 
4713d8817e4Smiod     case OPTION_XARCH:
4723d8817e4Smiod #ifdef OBJ_ELF
4733d8817e4Smiod       if (strncmp (arg, "v9", 2) != 0)
4743d8817e4Smiod 	md_parse_option (OPTION_32, NULL);
4753d8817e4Smiod       else
4763d8817e4Smiod 	md_parse_option (OPTION_64, NULL);
4773d8817e4Smiod #endif
4783d8817e4Smiod       /* Fall through.  */
4793d8817e4Smiod 
4803d8817e4Smiod     case 'A':
4813d8817e4Smiod       {
4823d8817e4Smiod 	struct sparc_arch *sa;
4833d8817e4Smiod 	enum sparc_opcode_arch_val opcode_arch;
4843d8817e4Smiod 
4853d8817e4Smiod 	sa = lookup_arch (arg);
4863d8817e4Smiod 	if (sa == NULL
4873d8817e4Smiod 	    || ! sa->user_option_p)
4883d8817e4Smiod 	  {
4893d8817e4Smiod 	    if (c == OPTION_XARCH)
4903d8817e4Smiod 	      as_bad (_("invalid architecture -xarch=%s"), arg);
4913d8817e4Smiod 	    else
4923d8817e4Smiod 	      as_bad (_("invalid architecture -A%s"), arg);
4933d8817e4Smiod 	    return 0;
4943d8817e4Smiod 	  }
4953d8817e4Smiod 
4963d8817e4Smiod 	opcode_arch = sparc_opcode_lookup_arch (sa->opcode_arch);
4973d8817e4Smiod 	if (opcode_arch == SPARC_OPCODE_ARCH_BAD)
4983d8817e4Smiod 	  as_fatal (_("Bad opcode table, broken assembler."));
4993d8817e4Smiod 
5003d8817e4Smiod 	max_architecture = opcode_arch;
5013d8817e4Smiod 	architecture_requested = 1;
5023d8817e4Smiod       }
5033d8817e4Smiod       break;
5043d8817e4Smiod 
5053d8817e4Smiod     case OPTION_SPARC:
5063d8817e4Smiod       /* Ignore -sparc, used by SunOS make default .s.o rule.  */
5073d8817e4Smiod       break;
5083d8817e4Smiod 
5093d8817e4Smiod     case OPTION_ENFORCE_ALIGNED_DATA:
5103d8817e4Smiod       enforce_aligned_data = 1;
5113d8817e4Smiod       break;
5123d8817e4Smiod 
5133d8817e4Smiod #ifdef SPARC_BIENDIAN
5143d8817e4Smiod     case OPTION_LITTLE_ENDIAN:
5153d8817e4Smiod       target_big_endian = 0;
5163d8817e4Smiod       if (default_arch_type != sparclet)
5173d8817e4Smiod 	as_fatal ("This target does not support -EL");
5183d8817e4Smiod       break;
5193d8817e4Smiod     case OPTION_LITTLE_ENDIAN_DATA:
5203d8817e4Smiod       target_little_endian_data = 1;
5213d8817e4Smiod       target_big_endian = 0;
5223d8817e4Smiod       if (default_arch_type != sparc86x
5233d8817e4Smiod 	  && default_arch_type != v9)
5243d8817e4Smiod 	as_fatal ("This target does not support --little-endian-data");
5253d8817e4Smiod       break;
5263d8817e4Smiod     case OPTION_BIG_ENDIAN:
5273d8817e4Smiod       target_big_endian = 1;
5283d8817e4Smiod       break;
5293d8817e4Smiod #endif
5303d8817e4Smiod 
5313d8817e4Smiod #ifdef OBJ_AOUT
5323d8817e4Smiod     case 'k':
5333d8817e4Smiod       sparc_pic_code = 1;
5343d8817e4Smiod       break;
5353d8817e4Smiod #endif
5363d8817e4Smiod 
5373d8817e4Smiod #ifdef OBJ_ELF
5383d8817e4Smiod     case OPTION_32:
5393d8817e4Smiod     case OPTION_64:
5403d8817e4Smiod       {
5413d8817e4Smiod 	const char **list, **l;
5423d8817e4Smiod 
5433d8817e4Smiod 	sparc_arch_size = c == OPTION_32 ? 32 : 64;
5443d8817e4Smiod 	list = bfd_target_list ();
5453d8817e4Smiod 	for (l = list; *l != NULL; l++)
5463d8817e4Smiod 	  {
5473d8817e4Smiod 	    if (sparc_arch_size == 32)
5483d8817e4Smiod 	      {
5493d8817e4Smiod 		if (strcmp (*l, "elf32-sparc") == 0)
5503d8817e4Smiod 		  break;
5513d8817e4Smiod 	      }
5523d8817e4Smiod 	    else
5533d8817e4Smiod 	      {
5543d8817e4Smiod 		if (strcmp (*l, "elf64-sparc") == 0)
5553d8817e4Smiod 		  break;
5563d8817e4Smiod 	      }
5573d8817e4Smiod 	  }
5583d8817e4Smiod 	if (*l == NULL)
5593d8817e4Smiod 	  as_fatal (_("No compiled in support for %d bit object file format"),
5603d8817e4Smiod 		    sparc_arch_size);
5613d8817e4Smiod 	free (list);
5623d8817e4Smiod       }
5633d8817e4Smiod       break;
5643d8817e4Smiod 
5653d8817e4Smiod     case OPTION_TSO:
5663d8817e4Smiod       sparc_memory_model = MM_TSO;
5673d8817e4Smiod       break;
5683d8817e4Smiod 
5693d8817e4Smiod     case OPTION_PSO:
5703d8817e4Smiod       sparc_memory_model = MM_PSO;
5713d8817e4Smiod       break;
5723d8817e4Smiod 
5733d8817e4Smiod     case OPTION_RMO:
5743d8817e4Smiod       sparc_memory_model = MM_RMO;
5753d8817e4Smiod       break;
5763d8817e4Smiod 
5773d8817e4Smiod     case 'V':
5783d8817e4Smiod       print_version_id ();
5793d8817e4Smiod       break;
5803d8817e4Smiod 
5813d8817e4Smiod     case 'Q':
5823d8817e4Smiod       /* Qy - do emit .comment
5833d8817e4Smiod 	 Qn - do not emit .comment.  */
5843d8817e4Smiod       break;
5853d8817e4Smiod 
5863d8817e4Smiod     case 's':
5873d8817e4Smiod       /* Use .stab instead of .stab.excl.  */
5883d8817e4Smiod       break;
5893d8817e4Smiod 
5903d8817e4Smiod     case 'q':
5913d8817e4Smiod       /* quick -- Native assembler does fewer checks.  */
5923d8817e4Smiod       break;
5933d8817e4Smiod 
5943d8817e4Smiod     case 'K':
5953d8817e4Smiod       if (strcmp (arg, "PIC") != 0)
5963d8817e4Smiod 	as_warn (_("Unrecognized option following -K"));
5973d8817e4Smiod       else
5983d8817e4Smiod 	sparc_pic_code = 1;
5993d8817e4Smiod       break;
6003d8817e4Smiod 
6013d8817e4Smiod     case OPTION_NO_UNDECLARED_REGS:
6023d8817e4Smiod       no_undeclared_regs = 1;
6033d8817e4Smiod       break;
6043d8817e4Smiod 
6053d8817e4Smiod     case OPTION_UNDECLARED_REGS:
6063d8817e4Smiod       no_undeclared_regs = 0;
6073d8817e4Smiod       break;
6083d8817e4Smiod #endif
6093d8817e4Smiod 
6103d8817e4Smiod     case OPTION_RELAX:
6113d8817e4Smiod       sparc_relax = 1;
6123d8817e4Smiod       break;
6133d8817e4Smiod 
6143d8817e4Smiod     case OPTION_NO_RELAX:
6153d8817e4Smiod       sparc_relax = 0;
6163d8817e4Smiod       break;
6173d8817e4Smiod 
6183d8817e4Smiod     default:
6193d8817e4Smiod       return 0;
6203d8817e4Smiod     }
6213d8817e4Smiod 
6223d8817e4Smiod   return 1;
6233d8817e4Smiod }
6243d8817e4Smiod 
6253d8817e4Smiod void
md_show_usage(stream)6263d8817e4Smiod md_show_usage (stream)
6273d8817e4Smiod      FILE *stream;
6283d8817e4Smiod {
6293d8817e4Smiod   const struct sparc_arch *arch;
6303d8817e4Smiod   int column;
6313d8817e4Smiod 
6323d8817e4Smiod   /* We don't get a chance to initialize anything before we're called,
6333d8817e4Smiod      so handle that now.  */
6343d8817e4Smiod   if (! default_init_p)
6353d8817e4Smiod     init_default_arch ();
6363d8817e4Smiod 
6373d8817e4Smiod   fprintf (stream, _("SPARC options:\n"));
6383d8817e4Smiod   column = 0;
6393d8817e4Smiod   for (arch = &sparc_arch_table[0]; arch->name; arch++)
6403d8817e4Smiod     {
6413d8817e4Smiod       if (!arch->user_option_p)
6423d8817e4Smiod 	continue;
6433d8817e4Smiod       if (arch != &sparc_arch_table[0])
6443d8817e4Smiod 	fprintf (stream, " | ");
6453d8817e4Smiod       if (column + strlen (arch->name) > 70)
6463d8817e4Smiod 	{
6473d8817e4Smiod 	  column = 0;
6483d8817e4Smiod 	  fputc ('\n', stream);
6493d8817e4Smiod 	}
6503d8817e4Smiod       column += 5 + 2 + strlen (arch->name);
6513d8817e4Smiod       fprintf (stream, "-A%s", arch->name);
6523d8817e4Smiod     }
6533d8817e4Smiod   for (arch = &sparc_arch_table[0]; arch->name; arch++)
6543d8817e4Smiod     {
6553d8817e4Smiod       if (!arch->user_option_p)
6563d8817e4Smiod 	continue;
6573d8817e4Smiod       fprintf (stream, " | ");
6583d8817e4Smiod       if (column + strlen (arch->name) > 65)
6593d8817e4Smiod 	{
6603d8817e4Smiod 	  column = 0;
6613d8817e4Smiod 	  fputc ('\n', stream);
6623d8817e4Smiod 	}
6633d8817e4Smiod       column += 5 + 7 + strlen (arch->name);
6643d8817e4Smiod       fprintf (stream, "-xarch=%s", arch->name);
6653d8817e4Smiod     }
6663d8817e4Smiod   fprintf (stream, _("\n\
6673d8817e4Smiod 			specify variant of SPARC architecture\n\
6683d8817e4Smiod -bump			warn when assembler switches architectures\n\
6693d8817e4Smiod -sparc			ignored\n\
6703d8817e4Smiod --enforce-aligned-data	force .long, etc., to be aligned correctly\n\
6713d8817e4Smiod -relax			relax jumps and branches (default)\n\
6723d8817e4Smiod -no-relax		avoid changing any jumps and branches\n"));
6733d8817e4Smiod #ifdef OBJ_AOUT
6743d8817e4Smiod   fprintf (stream, _("\
6753d8817e4Smiod -k			generate PIC\n"));
6763d8817e4Smiod #endif
6773d8817e4Smiod #ifdef OBJ_ELF
6783d8817e4Smiod   fprintf (stream, _("\
6793d8817e4Smiod -32			create 32 bit object file\n\
6803d8817e4Smiod -64			create 64 bit object file\n"));
6813d8817e4Smiod   fprintf (stream, _("\
6823d8817e4Smiod 			[default is %d]\n"), default_arch_size);
6833d8817e4Smiod   fprintf (stream, _("\
6843d8817e4Smiod -TSO			use Total Store Ordering\n\
6853d8817e4Smiod -PSO			use Partial Store Ordering\n\
6863d8817e4Smiod -RMO			use Relaxed Memory Ordering\n"));
6873d8817e4Smiod   fprintf (stream, _("\
6883d8817e4Smiod 			[default is %s]\n"), (default_arch_size == 64) ? "RMO" : "TSO");
6893d8817e4Smiod   fprintf (stream, _("\
6903d8817e4Smiod -KPIC			generate PIC\n\
6913d8817e4Smiod -V			print assembler version number\n\
6923d8817e4Smiod -undeclared-regs	ignore application global register usage without\n\
6933d8817e4Smiod 			appropriate .register directive (default)\n\
6943d8817e4Smiod -no-undeclared-regs	force error on application global register usage\n\
6953d8817e4Smiod 			without appropriate .register directive\n\
6963d8817e4Smiod -q			ignored\n\
6973d8817e4Smiod -Qy, -Qn		ignored\n\
6983d8817e4Smiod -s			ignored\n"));
6993d8817e4Smiod #endif
7003d8817e4Smiod #ifdef SPARC_BIENDIAN
7013d8817e4Smiod   fprintf (stream, _("\
7023d8817e4Smiod -EL			generate code for a little endian machine\n\
7033d8817e4Smiod -EB			generate code for a big endian machine\n\
7043d8817e4Smiod --little-endian-data	generate code for a machine having big endian\n\
7053d8817e4Smiod                         instructions and little endian data.\n"));
7063d8817e4Smiod #endif
7073d8817e4Smiod }
7083d8817e4Smiod 
7093d8817e4Smiod /* Native operand size opcode translation.  */
7103d8817e4Smiod struct
7113d8817e4Smiod   {
7123d8817e4Smiod     char *name;
7133d8817e4Smiod     char *name32;
7143d8817e4Smiod     char *name64;
7153d8817e4Smiod   } native_op_table[] =
7163d8817e4Smiod {
7173d8817e4Smiod   {"ldn", "ld", "ldx"},
7183d8817e4Smiod   {"ldna", "lda", "ldxa"},
7193d8817e4Smiod   {"stn", "st", "stx"},
7203d8817e4Smiod   {"stna", "sta", "stxa"},
7213d8817e4Smiod   {"slln", "sll", "sllx"},
7223d8817e4Smiod   {"srln", "srl", "srlx"},
7233d8817e4Smiod   {"sran", "sra", "srax"},
7243d8817e4Smiod   {"casn", "cas", "casx"},
7253d8817e4Smiod   {"casna", "casa", "casxa"},
7263d8817e4Smiod   {"clrn", "clr", "clrx"},
7273d8817e4Smiod   {NULL, NULL, NULL},
7283d8817e4Smiod };
7293d8817e4Smiod 
7303d8817e4Smiod /* sparc64 privileged and hyperprivileged registers.  */
7313d8817e4Smiod 
7323d8817e4Smiod struct priv_reg_entry
7333d8817e4Smiod {
7343d8817e4Smiod   char *name;
7353d8817e4Smiod   int regnum;
7363d8817e4Smiod };
7373d8817e4Smiod 
7383d8817e4Smiod struct priv_reg_entry priv_reg_table[] =
7393d8817e4Smiod {
7403d8817e4Smiod   {"tpc", 0},
7413d8817e4Smiod   {"tnpc", 1},
7423d8817e4Smiod   {"tstate", 2},
7433d8817e4Smiod   {"tt", 3},
7443d8817e4Smiod   {"tick", 4},
7453d8817e4Smiod   {"tba", 5},
7463d8817e4Smiod   {"pstate", 6},
7473d8817e4Smiod   {"tl", 7},
7483d8817e4Smiod   {"pil", 8},
7493d8817e4Smiod   {"cwp", 9},
7503d8817e4Smiod   {"cansave", 10},
7513d8817e4Smiod   {"canrestore", 11},
7523d8817e4Smiod   {"cleanwin", 12},
7533d8817e4Smiod   {"otherwin", 13},
7543d8817e4Smiod   {"wstate", 14},
7553d8817e4Smiod   {"fq", 15},
7563d8817e4Smiod   {"gl", 16},
7573d8817e4Smiod   {"ver", 31},
7583d8817e4Smiod   {"", -1},			/* End marker.  */
7593d8817e4Smiod };
7603d8817e4Smiod 
7613d8817e4Smiod struct priv_reg_entry hpriv_reg_table[] =
7623d8817e4Smiod {
7633d8817e4Smiod   {"hpstate", 0},
7643d8817e4Smiod   {"htstate", 1},
7653d8817e4Smiod   {"hintp", 3},
7663d8817e4Smiod   {"htba", 5},
7673d8817e4Smiod   {"hver", 6},
7683d8817e4Smiod   {"hstick_cmpr", 31},
7693d8817e4Smiod   {"", -1},			/* End marker.  */
7703d8817e4Smiod };
7713d8817e4Smiod 
7723d8817e4Smiod /* v9a specific asrs.  */
7733d8817e4Smiod 
7743d8817e4Smiod struct priv_reg_entry v9a_asr_table[] =
7753d8817e4Smiod {
7763d8817e4Smiod   {"tick_cmpr", 23},
7773d8817e4Smiod   {"sys_tick_cmpr", 25},
7783d8817e4Smiod   {"sys_tick", 24},
7793d8817e4Smiod   {"softint", 22},
7803d8817e4Smiod   {"set_softint", 20},
7813d8817e4Smiod   {"pic", 17},
7823d8817e4Smiod   {"pcr", 16},
7833d8817e4Smiod   {"gsr", 19},
7843d8817e4Smiod   {"dcr", 18},
7853d8817e4Smiod   {"clear_softint", 21},
7863d8817e4Smiod   {"", -1},			/* End marker.  */
7873d8817e4Smiod };
7883d8817e4Smiod 
7893d8817e4Smiod static int
cmp_reg_entry(parg,qarg)7903d8817e4Smiod cmp_reg_entry (parg, qarg)
7913d8817e4Smiod      const PTR parg;
7923d8817e4Smiod      const PTR qarg;
7933d8817e4Smiod {
7943d8817e4Smiod   const struct priv_reg_entry *p = (const struct priv_reg_entry *) parg;
7953d8817e4Smiod   const struct priv_reg_entry *q = (const struct priv_reg_entry *) qarg;
7963d8817e4Smiod 
7973d8817e4Smiod   return strcmp (q->name, p->name);
7983d8817e4Smiod }
7993d8817e4Smiod 
8003d8817e4Smiod /* This function is called once, at assembler startup time.  It should
8013d8817e4Smiod    set up all the tables, etc. that the MD part of the assembler will
8023d8817e4Smiod    need.  */
8033d8817e4Smiod 
8043d8817e4Smiod void
md_begin()8053d8817e4Smiod md_begin ()
8063d8817e4Smiod {
8073d8817e4Smiod   register const char *retval = NULL;
8083d8817e4Smiod   int lose = 0;
8093d8817e4Smiod   register unsigned int i = 0;
8103d8817e4Smiod 
8113d8817e4Smiod   /* We don't get a chance to initialize anything before md_parse_option
8123d8817e4Smiod      is called, and it may not be called, so handle default initialization
8133d8817e4Smiod      now if not already done.  */
8143d8817e4Smiod   if (! default_init_p)
8153d8817e4Smiod     init_default_arch ();
8163d8817e4Smiod 
8173d8817e4Smiod   sparc_cie_data_alignment = sparc_arch_size == 64 ? -8 : -4;
8183d8817e4Smiod   op_hash = hash_new ();
8193d8817e4Smiod 
8203d8817e4Smiod   while (i < (unsigned int) sparc_num_opcodes)
8213d8817e4Smiod     {
8223d8817e4Smiod       const char *name = sparc_opcodes[i].name;
8233d8817e4Smiod       retval = hash_insert (op_hash, name, (PTR) &sparc_opcodes[i]);
8243d8817e4Smiod       if (retval != NULL)
8253d8817e4Smiod 	{
8263d8817e4Smiod 	  as_bad (_("Internal error: can't hash `%s': %s\n"),
8273d8817e4Smiod 		  sparc_opcodes[i].name, retval);
8283d8817e4Smiod 	  lose = 1;
8293d8817e4Smiod 	}
8303d8817e4Smiod       do
8313d8817e4Smiod 	{
8323d8817e4Smiod 	  if (sparc_opcodes[i].match & sparc_opcodes[i].lose)
8333d8817e4Smiod 	    {
8343d8817e4Smiod 	      as_bad (_("Internal error: losing opcode: `%s' \"%s\"\n"),
8353d8817e4Smiod 		      sparc_opcodes[i].name, sparc_opcodes[i].args);
8363d8817e4Smiod 	      lose = 1;
8373d8817e4Smiod 	    }
8383d8817e4Smiod 	  ++i;
8393d8817e4Smiod 	}
8403d8817e4Smiod       while (i < (unsigned int) sparc_num_opcodes
8413d8817e4Smiod 	     && !strcmp (sparc_opcodes[i].name, name));
8423d8817e4Smiod     }
8433d8817e4Smiod 
8443d8817e4Smiod   for (i = 0; native_op_table[i].name; i++)
8453d8817e4Smiod     {
8463d8817e4Smiod       const struct sparc_opcode *insn;
8473d8817e4Smiod       char *name = ((sparc_arch_size == 32)
8483d8817e4Smiod 		    ? native_op_table[i].name32
8493d8817e4Smiod 		    : native_op_table[i].name64);
8503d8817e4Smiod       insn = (struct sparc_opcode *) hash_find (op_hash, name);
8513d8817e4Smiod       if (insn == NULL)
8523d8817e4Smiod 	{
8533d8817e4Smiod 	  as_bad (_("Internal error: can't find opcode `%s' for `%s'\n"),
8543d8817e4Smiod 		  name, native_op_table[i].name);
8553d8817e4Smiod 	  lose = 1;
8563d8817e4Smiod 	}
8573d8817e4Smiod       else
8583d8817e4Smiod 	{
8593d8817e4Smiod 	  retval = hash_insert (op_hash, native_op_table[i].name, (PTR) insn);
8603d8817e4Smiod 	  if (retval != NULL)
8613d8817e4Smiod 	    {
8623d8817e4Smiod 	      as_bad (_("Internal error: can't hash `%s': %s\n"),
8633d8817e4Smiod 		      sparc_opcodes[i].name, retval);
8643d8817e4Smiod 	      lose = 1;
8653d8817e4Smiod 	    }
8663d8817e4Smiod 	}
8673d8817e4Smiod     }
8683d8817e4Smiod 
8693d8817e4Smiod   if (lose)
8703d8817e4Smiod     as_fatal (_("Broken assembler.  No assembly attempted."));
8713d8817e4Smiod 
8723d8817e4Smiod   qsort (priv_reg_table, sizeof (priv_reg_table) / sizeof (priv_reg_table[0]),
8733d8817e4Smiod 	 sizeof (priv_reg_table[0]), cmp_reg_entry);
8743d8817e4Smiod 
8753d8817e4Smiod   /* If -bump, record the architecture level at which we start issuing
8763d8817e4Smiod      warnings.  The behaviour is different depending upon whether an
8773d8817e4Smiod      architecture was explicitly specified.  If it wasn't, we issue warnings
8783d8817e4Smiod      for all upwards bumps.  If it was, we don't start issuing warnings until
8793d8817e4Smiod      we need to bump beyond the requested architecture or when we bump between
8803d8817e4Smiod      conflicting architectures.  */
8813d8817e4Smiod 
8823d8817e4Smiod   if (warn_on_bump
8833d8817e4Smiod       && architecture_requested)
8843d8817e4Smiod     {
8853d8817e4Smiod       /* `max_architecture' records the requested architecture.
8863d8817e4Smiod 	 Issue warnings if we go above it.  */
8873d8817e4Smiod       warn_after_architecture = max_architecture;
8883d8817e4Smiod 
8893d8817e4Smiod       /* Find the highest architecture level that doesn't conflict with
8903d8817e4Smiod 	 the requested one.  */
8913d8817e4Smiod       for (max_architecture = SPARC_OPCODE_ARCH_MAX;
8923d8817e4Smiod 	   max_architecture > warn_after_architecture;
8933d8817e4Smiod 	   --max_architecture)
8943d8817e4Smiod 	if (! SPARC_OPCODE_CONFLICT_P (max_architecture,
8953d8817e4Smiod 				       warn_after_architecture))
8963d8817e4Smiod 	  break;
8973d8817e4Smiod     }
8983d8817e4Smiod }
8993d8817e4Smiod 
9003d8817e4Smiod /* Called after all assembly has been done.  */
9013d8817e4Smiod 
9023d8817e4Smiod void
sparc_md_end()9033d8817e4Smiod sparc_md_end ()
9043d8817e4Smiod {
9053d8817e4Smiod   unsigned long mach = bfd_mach_sparc;
9063d8817e4Smiod 
9073d8817e4Smiod   if (sparc_arch_size == 64)
9083d8817e4Smiod     switch (current_architecture)
9093d8817e4Smiod       {
9103d8817e4Smiod       case SPARC_OPCODE_ARCH_V9A: mach = bfd_mach_sparc_v9a; break;
9113d8817e4Smiod       case SPARC_OPCODE_ARCH_V9B: mach = bfd_mach_sparc_v9b; break;
9123d8817e4Smiod       default: mach = bfd_mach_sparc_v9; break;
9133d8817e4Smiod       }
9143d8817e4Smiod   else
9153d8817e4Smiod     switch (current_architecture)
9163d8817e4Smiod       {
9173d8817e4Smiod       case SPARC_OPCODE_ARCH_SPARCLET: mach = bfd_mach_sparc_sparclet; break;
9183d8817e4Smiod       case SPARC_OPCODE_ARCH_V9: mach = bfd_mach_sparc_v8plus; break;
9193d8817e4Smiod       case SPARC_OPCODE_ARCH_V9A: mach = bfd_mach_sparc_v8plusa; break;
9203d8817e4Smiod       case SPARC_OPCODE_ARCH_V9B: mach = bfd_mach_sparc_v8plusb; break;
9213d8817e4Smiod       /* The sparclite is treated like a normal sparc.  Perhaps it shouldn't
9223d8817e4Smiod 	 be but for now it is (since that's the way it's always been
9233d8817e4Smiod 	 treated).  */
9243d8817e4Smiod       default: break;
9253d8817e4Smiod       }
9263d8817e4Smiod   bfd_set_arch_mach (stdoutput, bfd_arch_sparc, mach);
9273d8817e4Smiod }
9283d8817e4Smiod 
9293d8817e4Smiod /* Return non-zero if VAL is in the range -(MAX+1) to MAX.  */
9303d8817e4Smiod 
9313d8817e4Smiod static INLINE int
in_signed_range(val,max)9323d8817e4Smiod in_signed_range (val, max)
9333d8817e4Smiod      bfd_signed_vma val, max;
9343d8817e4Smiod {
9353d8817e4Smiod   if (max <= 0)
9363d8817e4Smiod     abort ();
9373d8817e4Smiod   /* Sign-extend the value from the architecture word size, so that
9383d8817e4Smiod      0xffffffff is always considered -1 on sparc32.  */
9393d8817e4Smiod   if (sparc_arch_size == 32)
9403d8817e4Smiod     {
9413d8817e4Smiod       bfd_signed_vma sign = (bfd_signed_vma) 1 << 31;
9423d8817e4Smiod       val = ((val & U0xffffffff) ^ sign) - sign;
9433d8817e4Smiod     }
9443d8817e4Smiod   if (val > max)
9453d8817e4Smiod     return 0;
9463d8817e4Smiod   if (val < ~max)
9473d8817e4Smiod     return 0;
9483d8817e4Smiod   return 1;
9493d8817e4Smiod }
9503d8817e4Smiod 
9513d8817e4Smiod /* Return non-zero if VAL is in the range -(MAX/2+1) to MAX.
9523d8817e4Smiod    (e.g. -15 to +31).  */
9533d8817e4Smiod 
9543d8817e4Smiod static INLINE int
in_bitfield_range(val,max)9553d8817e4Smiod in_bitfield_range (val, max)
9563d8817e4Smiod      bfd_signed_vma val, max;
9573d8817e4Smiod {
9583d8817e4Smiod   if (max <= 0)
9593d8817e4Smiod     abort ();
9603d8817e4Smiod   if (val > max)
9613d8817e4Smiod     return 0;
9623d8817e4Smiod   if (val < ~(max >> 1))
9633d8817e4Smiod     return 0;
9643d8817e4Smiod   return 1;
9653d8817e4Smiod }
9663d8817e4Smiod 
9673d8817e4Smiod static int
sparc_ffs(mask)9683d8817e4Smiod sparc_ffs (mask)
9693d8817e4Smiod      unsigned int mask;
9703d8817e4Smiod {
9713d8817e4Smiod   int i;
9723d8817e4Smiod 
9733d8817e4Smiod   if (mask == 0)
9743d8817e4Smiod     return -1;
9753d8817e4Smiod 
9763d8817e4Smiod   for (i = 0; (mask & 1) == 0; ++i)
9773d8817e4Smiod     mask >>= 1;
9783d8817e4Smiod   return i;
9793d8817e4Smiod }
9803d8817e4Smiod 
9813d8817e4Smiod /* Implement big shift right.  */
9823d8817e4Smiod static bfd_vma
BSR(val,amount)9833d8817e4Smiod BSR (val, amount)
9843d8817e4Smiod      bfd_vma val;
9853d8817e4Smiod      int amount;
9863d8817e4Smiod {
9873d8817e4Smiod   if (sizeof (bfd_vma) <= 4 && amount >= 32)
9883d8817e4Smiod     as_fatal (_("Support for 64-bit arithmetic not compiled in."));
9893d8817e4Smiod   return val >> amount;
9903d8817e4Smiod }
9913d8817e4Smiod 
9923d8817e4Smiod /* For communication between sparc_ip and get_expression.  */
9933d8817e4Smiod static char *expr_end;
9943d8817e4Smiod 
9953d8817e4Smiod /* Values for `special_case'.
9963d8817e4Smiod    Instructions that require wierd handling because they're longer than
9973d8817e4Smiod    4 bytes.  */
9983d8817e4Smiod #define SPECIAL_CASE_NONE	0
9993d8817e4Smiod #define	SPECIAL_CASE_SET	1
10003d8817e4Smiod #define SPECIAL_CASE_SETSW	2
10013d8817e4Smiod #define SPECIAL_CASE_SETX	3
10023d8817e4Smiod /* FIXME: sparc-opc.c doesn't have necessary "S" trigger to enable this.  */
10033d8817e4Smiod #define	SPECIAL_CASE_FDIV	4
10043d8817e4Smiod 
10053d8817e4Smiod /* Bit masks of various insns.  */
10063d8817e4Smiod #define NOP_INSN 0x01000000
10073d8817e4Smiod #define OR_INSN 0x80100000
10083d8817e4Smiod #define XOR_INSN 0x80180000
10093d8817e4Smiod #define FMOVS_INSN 0x81A00020
10103d8817e4Smiod #define SETHI_INSN 0x01000000
10113d8817e4Smiod #define SLLX_INSN 0x81281000
10123d8817e4Smiod #define SRA_INSN 0x81380000
10133d8817e4Smiod 
10143d8817e4Smiod /* The last instruction to be assembled.  */
10153d8817e4Smiod static const struct sparc_opcode *last_insn;
10163d8817e4Smiod /* The assembled opcode of `last_insn'.  */
10173d8817e4Smiod static unsigned long last_opcode;
10183d8817e4Smiod 
10193d8817e4Smiod /* Handle the set and setuw synthetic instructions.  */
10203d8817e4Smiod 
10213d8817e4Smiod static void
synthetize_setuw(insn)10223d8817e4Smiod synthetize_setuw (insn)
10233d8817e4Smiod      const struct sparc_opcode *insn;
10243d8817e4Smiod {
10253d8817e4Smiod   int need_hi22_p = 0;
10263d8817e4Smiod   int rd = (the_insn.opcode & RD (~0)) >> 25;
10273d8817e4Smiod 
10283d8817e4Smiod   if (the_insn.exp.X_op == O_constant)
10293d8817e4Smiod     {
10303d8817e4Smiod       if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
10313d8817e4Smiod 	{
10323d8817e4Smiod 	  if (sizeof (offsetT) > 4
10333d8817e4Smiod 	      && (the_insn.exp.X_add_number < 0
10343d8817e4Smiod 		  || the_insn.exp.X_add_number > (offsetT) U0xffffffff))
10353d8817e4Smiod 	    as_warn (_("set: number not in 0..4294967295 range"));
10363d8817e4Smiod 	}
10373d8817e4Smiod       else
10383d8817e4Smiod 	{
10393d8817e4Smiod 	  if (sizeof (offsetT) > 4
10403d8817e4Smiod 	      && (the_insn.exp.X_add_number < -(offsetT) U0x80000000
10413d8817e4Smiod 		  || the_insn.exp.X_add_number > (offsetT) U0xffffffff))
10423d8817e4Smiod 	    as_warn (_("set: number not in -2147483648..4294967295 range"));
10433d8817e4Smiod 	  the_insn.exp.X_add_number = (int) the_insn.exp.X_add_number;
10443d8817e4Smiod 	}
10453d8817e4Smiod     }
10463d8817e4Smiod 
10473d8817e4Smiod   /* See if operand is absolute and small; skip sethi if so.  */
10483d8817e4Smiod   if (the_insn.exp.X_op != O_constant
10493d8817e4Smiod       || the_insn.exp.X_add_number >= (1 << 12)
10503d8817e4Smiod       || the_insn.exp.X_add_number < -(1 << 12))
10513d8817e4Smiod     {
10523d8817e4Smiod       the_insn.opcode = (SETHI_INSN | RD (rd)
10533d8817e4Smiod 			 | ((the_insn.exp.X_add_number >> 10)
10543d8817e4Smiod 			    & (the_insn.exp.X_op == O_constant
10553d8817e4Smiod 			       ? 0x3fffff : 0)));
10563d8817e4Smiod       the_insn.reloc = (the_insn.exp.X_op != O_constant
10573d8817e4Smiod 			? BFD_RELOC_HI22 : BFD_RELOC_NONE);
10583d8817e4Smiod       output_insn (insn, &the_insn);
10593d8817e4Smiod       need_hi22_p = 1;
10603d8817e4Smiod     }
10613d8817e4Smiod 
10623d8817e4Smiod   /* See if operand has no low-order bits; skip OR if so.  */
10633d8817e4Smiod   if (the_insn.exp.X_op != O_constant
10643d8817e4Smiod       || (need_hi22_p && (the_insn.exp.X_add_number & 0x3FF) != 0)
10653d8817e4Smiod       || ! need_hi22_p)
10663d8817e4Smiod     {
10673d8817e4Smiod       the_insn.opcode = (OR_INSN | (need_hi22_p ? RS1 (rd) : 0)
10683d8817e4Smiod 			 | RD (rd) | IMMED
10693d8817e4Smiod 			 | (the_insn.exp.X_add_number
10703d8817e4Smiod 			    & (the_insn.exp.X_op != O_constant
10713d8817e4Smiod 			       ? 0 : need_hi22_p ? 0x3ff : 0x1fff)));
10723d8817e4Smiod       the_insn.reloc = (the_insn.exp.X_op != O_constant
10733d8817e4Smiod 			? BFD_RELOC_LO10 : BFD_RELOC_NONE);
10743d8817e4Smiod       output_insn (insn, &the_insn);
10753d8817e4Smiod     }
10763d8817e4Smiod }
10773d8817e4Smiod 
10783d8817e4Smiod /* Handle the setsw synthetic instruction.  */
10793d8817e4Smiod 
10803d8817e4Smiod static void
synthetize_setsw(insn)10813d8817e4Smiod synthetize_setsw (insn)
10823d8817e4Smiod      const struct sparc_opcode *insn;
10833d8817e4Smiod {
10843d8817e4Smiod   int low32, rd, opc;
10853d8817e4Smiod 
10863d8817e4Smiod   rd = (the_insn.opcode & RD (~0)) >> 25;
10873d8817e4Smiod 
10883d8817e4Smiod   if (the_insn.exp.X_op != O_constant)
10893d8817e4Smiod     {
10903d8817e4Smiod       synthetize_setuw (insn);
10913d8817e4Smiod 
10923d8817e4Smiod       /* Need to sign extend it.  */
10933d8817e4Smiod       the_insn.opcode = (SRA_INSN | RS1 (rd) | RD (rd));
10943d8817e4Smiod       the_insn.reloc = BFD_RELOC_NONE;
10953d8817e4Smiod       output_insn (insn, &the_insn);
10963d8817e4Smiod       return;
10973d8817e4Smiod     }
10983d8817e4Smiod 
10993d8817e4Smiod   if (sizeof (offsetT) > 4
11003d8817e4Smiod       && (the_insn.exp.X_add_number < -(offsetT) U0x80000000
11013d8817e4Smiod 	  || the_insn.exp.X_add_number > (offsetT) U0xffffffff))
11023d8817e4Smiod     as_warn (_("setsw: number not in -2147483648..4294967295 range"));
11033d8817e4Smiod 
11043d8817e4Smiod   low32 = the_insn.exp.X_add_number;
11053d8817e4Smiod 
11063d8817e4Smiod   if (low32 >= 0)
11073d8817e4Smiod     {
11083d8817e4Smiod       synthetize_setuw (insn);
11093d8817e4Smiod       return;
11103d8817e4Smiod     }
11113d8817e4Smiod 
11123d8817e4Smiod   opc = OR_INSN;
11133d8817e4Smiod 
11143d8817e4Smiod   the_insn.reloc = BFD_RELOC_NONE;
11153d8817e4Smiod   /* See if operand is absolute and small; skip sethi if so.  */
11163d8817e4Smiod   if (low32 < -(1 << 12))
11173d8817e4Smiod     {
11183d8817e4Smiod       the_insn.opcode = (SETHI_INSN | RD (rd)
11193d8817e4Smiod 			 | (((~the_insn.exp.X_add_number) >> 10) & 0x3fffff));
11203d8817e4Smiod       output_insn (insn, &the_insn);
11213d8817e4Smiod       low32 = 0x1c00 | (low32 & 0x3ff);
11223d8817e4Smiod       opc = RS1 (rd) | XOR_INSN;
11233d8817e4Smiod     }
11243d8817e4Smiod 
11253d8817e4Smiod   the_insn.opcode = (opc | RD (rd) | IMMED
11263d8817e4Smiod 		     | (low32 & 0x1fff));
11273d8817e4Smiod   output_insn (insn, &the_insn);
11283d8817e4Smiod }
11293d8817e4Smiod 
11303d8817e4Smiod /* Handle the setsw synthetic instruction.  */
11313d8817e4Smiod 
11323d8817e4Smiod static void
synthetize_setx(insn)11333d8817e4Smiod synthetize_setx (insn)
11343d8817e4Smiod      const struct sparc_opcode *insn;
11353d8817e4Smiod {
11363d8817e4Smiod   int upper32, lower32;
11373d8817e4Smiod   int tmpreg = (the_insn.opcode & RS1 (~0)) >> 14;
11383d8817e4Smiod   int dstreg = (the_insn.opcode & RD (~0)) >> 25;
11393d8817e4Smiod   int upper_dstreg;
11403d8817e4Smiod   int need_hh22_p = 0, need_hm10_p = 0, need_hi22_p = 0, need_lo10_p = 0;
11413d8817e4Smiod   int need_xor10_p = 0;
11423d8817e4Smiod 
11433d8817e4Smiod #define SIGNEXT32(x) ((((x) & U0xffffffff) ^ U0x80000000) - U0x80000000)
11443d8817e4Smiod   lower32 = SIGNEXT32 (the_insn.exp.X_add_number);
11453d8817e4Smiod   upper32 = SIGNEXT32 (BSR (the_insn.exp.X_add_number, 32));
11463d8817e4Smiod #undef SIGNEXT32
11473d8817e4Smiod 
11483d8817e4Smiod   upper_dstreg = tmpreg;
11493d8817e4Smiod   /* The tmp reg should not be the dst reg.  */
11503d8817e4Smiod   if (tmpreg == dstreg)
11513d8817e4Smiod     as_warn (_("setx: temporary register same as destination register"));
11523d8817e4Smiod 
11533d8817e4Smiod   /* ??? Obviously there are other optimizations we can do
11543d8817e4Smiod      (e.g. sethi+shift for 0x1f0000000) and perhaps we shouldn't be
11553d8817e4Smiod      doing some of these.  Later.  If you do change things, try to
11563d8817e4Smiod      change all of this to be table driven as well.  */
11573d8817e4Smiod   /* What to output depends on the number if it's constant.
11583d8817e4Smiod      Compute that first, then output what we've decided upon.  */
11593d8817e4Smiod   if (the_insn.exp.X_op != O_constant)
11603d8817e4Smiod     {
11613d8817e4Smiod       if (sparc_arch_size == 32)
11623d8817e4Smiod 	{
11633d8817e4Smiod 	  /* When arch size is 32, we want setx to be equivalent
11643d8817e4Smiod 	     to setuw for anything but constants.  */
11653d8817e4Smiod 	  the_insn.exp.X_add_number &= 0xffffffff;
11663d8817e4Smiod 	  synthetize_setuw (insn);
11673d8817e4Smiod 	  return;
11683d8817e4Smiod 	}
11693d8817e4Smiod       need_hh22_p = need_hm10_p = need_hi22_p = need_lo10_p = 1;
11703d8817e4Smiod       lower32 = 0;
11713d8817e4Smiod       upper32 = 0;
11723d8817e4Smiod     }
11733d8817e4Smiod   else
11743d8817e4Smiod     {
11753d8817e4Smiod       /* Reset X_add_number, we've extracted it as upper32/lower32.
11763d8817e4Smiod 	 Otherwise fixup_segment will complain about not being able to
11773d8817e4Smiod 	 write an 8 byte number in a 4 byte field.  */
11783d8817e4Smiod       the_insn.exp.X_add_number = 0;
11793d8817e4Smiod 
11803d8817e4Smiod       /* Only need hh22 if `or' insn can't handle constant.  */
11813d8817e4Smiod       if (upper32 < -(1 << 12) || upper32 >= (1 << 12))
11823d8817e4Smiod 	need_hh22_p = 1;
11833d8817e4Smiod 
11843d8817e4Smiod       /* Does bottom part (after sethi) have bits?  */
11853d8817e4Smiod       if ((need_hh22_p && (upper32 & 0x3ff) != 0)
11863d8817e4Smiod 	  /* No hh22, but does upper32 still have bits we can't set
11873d8817e4Smiod 	     from lower32?  */
11883d8817e4Smiod 	  || (! need_hh22_p && upper32 != 0 && upper32 != -1))
11893d8817e4Smiod 	need_hm10_p = 1;
11903d8817e4Smiod 
11913d8817e4Smiod       /* If the lower half is all zero, we build the upper half directly
11923d8817e4Smiod 	 into the dst reg.  */
11933d8817e4Smiod       if (lower32 != 0
11943d8817e4Smiod 	  /* Need lower half if number is zero or 0xffffffff00000000.  */
11953d8817e4Smiod 	  || (! need_hh22_p && ! need_hm10_p))
11963d8817e4Smiod 	{
11973d8817e4Smiod 	  /* No need for sethi if `or' insn can handle constant.  */
11983d8817e4Smiod 	  if (lower32 < -(1 << 12) || lower32 >= (1 << 12)
11993d8817e4Smiod 	      /* Note that we can't use a negative constant in the `or'
12003d8817e4Smiod 		 insn unless the upper 32 bits are all ones.  */
12013d8817e4Smiod 	      || (lower32 < 0 && upper32 != -1)
12023d8817e4Smiod 	      || (lower32 >= 0 && upper32 == -1))
12033d8817e4Smiod 	    need_hi22_p = 1;
12043d8817e4Smiod 
12053d8817e4Smiod 	  if (need_hi22_p && upper32 == -1)
12063d8817e4Smiod 	    need_xor10_p = 1;
12073d8817e4Smiod 
12083d8817e4Smiod 	  /* Does bottom part (after sethi) have bits?  */
12093d8817e4Smiod 	  else if ((need_hi22_p && (lower32 & 0x3ff) != 0)
12103d8817e4Smiod 		   /* No sethi.  */
12113d8817e4Smiod 		   || (! need_hi22_p && (lower32 & 0x1fff) != 0)
12123d8817e4Smiod 		   /* Need `or' if we didn't set anything else.  */
12133d8817e4Smiod 		   || (! need_hi22_p && ! need_hh22_p && ! need_hm10_p))
12143d8817e4Smiod 	    need_lo10_p = 1;
12153d8817e4Smiod 	}
12163d8817e4Smiod       else
12173d8817e4Smiod 	/* Output directly to dst reg if lower 32 bits are all zero.  */
12183d8817e4Smiod 	upper_dstreg = dstreg;
12193d8817e4Smiod     }
12203d8817e4Smiod 
12213d8817e4Smiod   if (!upper_dstreg && dstreg)
12223d8817e4Smiod     as_warn (_("setx: illegal temporary register g0"));
12233d8817e4Smiod 
12243d8817e4Smiod   if (need_hh22_p)
12253d8817e4Smiod     {
12263d8817e4Smiod       the_insn.opcode = (SETHI_INSN | RD (upper_dstreg)
12273d8817e4Smiod 			 | ((upper32 >> 10) & 0x3fffff));
12283d8817e4Smiod       the_insn.reloc = (the_insn.exp.X_op != O_constant
12293d8817e4Smiod 			? BFD_RELOC_SPARC_HH22 : BFD_RELOC_NONE);
12303d8817e4Smiod       output_insn (insn, &the_insn);
12313d8817e4Smiod     }
12323d8817e4Smiod 
12333d8817e4Smiod   if (need_hi22_p)
12343d8817e4Smiod     {
12353d8817e4Smiod       the_insn.opcode = (SETHI_INSN | RD (dstreg)
12363d8817e4Smiod 			 | (((need_xor10_p ? ~lower32 : lower32)
12373d8817e4Smiod 			     >> 10) & 0x3fffff));
12383d8817e4Smiod       the_insn.reloc = (the_insn.exp.X_op != O_constant
12393d8817e4Smiod 			? BFD_RELOC_SPARC_LM22 : BFD_RELOC_NONE);
12403d8817e4Smiod       output_insn (insn, &the_insn);
12413d8817e4Smiod     }
12423d8817e4Smiod 
12433d8817e4Smiod   if (need_hm10_p)
12443d8817e4Smiod     {
12453d8817e4Smiod       the_insn.opcode = (OR_INSN
12463d8817e4Smiod 			 | (need_hh22_p ? RS1 (upper_dstreg) : 0)
12473d8817e4Smiod 			 | RD (upper_dstreg)
12483d8817e4Smiod 			 | IMMED
12493d8817e4Smiod 			 | (upper32 & (need_hh22_p ? 0x3ff : 0x1fff)));
12503d8817e4Smiod       the_insn.reloc = (the_insn.exp.X_op != O_constant
12513d8817e4Smiod 			? BFD_RELOC_SPARC_HM10 : BFD_RELOC_NONE);
12523d8817e4Smiod       output_insn (insn, &the_insn);
12533d8817e4Smiod     }
12543d8817e4Smiod 
12553d8817e4Smiod   if (need_lo10_p)
12563d8817e4Smiod     {
12573d8817e4Smiod       /* FIXME: One nice optimization to do here is to OR the low part
12583d8817e4Smiod 	 with the highpart if hi22 isn't needed and the low part is
12593d8817e4Smiod 	 positive.  */
12603d8817e4Smiod       the_insn.opcode = (OR_INSN | (need_hi22_p ? RS1 (dstreg) : 0)
12613d8817e4Smiod 			 | RD (dstreg)
12623d8817e4Smiod 			 | IMMED
12633d8817e4Smiod 			 | (lower32 & (need_hi22_p ? 0x3ff : 0x1fff)));
12643d8817e4Smiod       the_insn.reloc = (the_insn.exp.X_op != O_constant
12653d8817e4Smiod 			? BFD_RELOC_LO10 : BFD_RELOC_NONE);
12663d8817e4Smiod       output_insn (insn, &the_insn);
12673d8817e4Smiod     }
12683d8817e4Smiod 
12693d8817e4Smiod   /* If we needed to build the upper part, shift it into place.  */
12703d8817e4Smiod   if (need_hh22_p || need_hm10_p)
12713d8817e4Smiod     {
12723d8817e4Smiod       the_insn.opcode = (SLLX_INSN | RS1 (upper_dstreg) | RD (upper_dstreg)
12733d8817e4Smiod 			 | IMMED | 32);
12743d8817e4Smiod       the_insn.reloc = BFD_RELOC_NONE;
12753d8817e4Smiod       output_insn (insn, &the_insn);
12763d8817e4Smiod     }
12773d8817e4Smiod 
12783d8817e4Smiod   /* To get -1 in upper32, we do sethi %hi(~x), r; xor r, -0x400 | x, r.  */
12793d8817e4Smiod   if (need_xor10_p)
12803d8817e4Smiod     {
12813d8817e4Smiod       the_insn.opcode = (XOR_INSN | RS1 (dstreg) | RD (dstreg) | IMMED
12823d8817e4Smiod 			 | 0x1c00 | (lower32 & 0x3ff));
12833d8817e4Smiod       the_insn.reloc = BFD_RELOC_NONE;
12843d8817e4Smiod       output_insn (insn, &the_insn);
12853d8817e4Smiod     }
12863d8817e4Smiod 
12873d8817e4Smiod   /* If we needed to build both upper and lower parts, OR them together.  */
12883d8817e4Smiod   else if ((need_hh22_p || need_hm10_p) && (need_hi22_p || need_lo10_p))
12893d8817e4Smiod     {
12903d8817e4Smiod       the_insn.opcode = (OR_INSN | RS1 (dstreg) | RS2 (upper_dstreg)
12913d8817e4Smiod 			 | RD (dstreg));
12923d8817e4Smiod       the_insn.reloc = BFD_RELOC_NONE;
12933d8817e4Smiod       output_insn (insn, &the_insn);
12943d8817e4Smiod     }
12953d8817e4Smiod }
12963d8817e4Smiod 
12973d8817e4Smiod /* Main entry point to assemble one instruction.  */
12983d8817e4Smiod 
12993d8817e4Smiod void
md_assemble(str)13003d8817e4Smiod md_assemble (str)
13013d8817e4Smiod      char *str;
13023d8817e4Smiod {
13033d8817e4Smiod   const struct sparc_opcode *insn;
13043d8817e4Smiod   int special_case;
13053d8817e4Smiod 
13063d8817e4Smiod   know (str);
13073d8817e4Smiod   special_case = sparc_ip (str, &insn);
13083d8817e4Smiod   if (insn == NULL)
13093d8817e4Smiod     return;
13103d8817e4Smiod 
13113d8817e4Smiod   /* We warn about attempts to put a floating point branch in a delay slot,
13123d8817e4Smiod      unless the delay slot has been annulled.  */
13133d8817e4Smiod   if (last_insn != NULL
13143d8817e4Smiod       && (insn->flags & F_FBR) != 0
13153d8817e4Smiod       && (last_insn->flags & F_DELAYED) != 0
13163d8817e4Smiod       /* ??? This test isn't completely accurate.  We assume anything with
13173d8817e4Smiod 	 F_{UNBR,CONDBR,FBR} set is annullable.  */
13183d8817e4Smiod       && ((last_insn->flags & (F_UNBR | F_CONDBR | F_FBR)) == 0
13193d8817e4Smiod 	  || (last_opcode & ANNUL) == 0))
13203d8817e4Smiod     as_warn (_("FP branch in delay slot"));
13213d8817e4Smiod 
13223d8817e4Smiod   /* SPARC before v9 requires a nop instruction between a floating
13233d8817e4Smiod      point instruction and a floating point branch.  We insert one
13243d8817e4Smiod      automatically, with a warning.  */
13253d8817e4Smiod   if (max_architecture < SPARC_OPCODE_ARCH_V9
13263d8817e4Smiod       && last_insn != NULL
13273d8817e4Smiod       && (insn->flags & F_FBR) != 0
13283d8817e4Smiod       && (last_insn->flags & F_FLOAT) != 0)
13293d8817e4Smiod     {
13303d8817e4Smiod       struct sparc_it nop_insn;
13313d8817e4Smiod 
13323d8817e4Smiod       nop_insn.opcode = NOP_INSN;
13333d8817e4Smiod       nop_insn.reloc = BFD_RELOC_NONE;
13343d8817e4Smiod       output_insn (insn, &nop_insn);
13353d8817e4Smiod       as_warn (_("FP branch preceded by FP instruction; NOP inserted"));
13363d8817e4Smiod     }
13373d8817e4Smiod 
13383d8817e4Smiod   switch (special_case)
13393d8817e4Smiod     {
13403d8817e4Smiod     case SPECIAL_CASE_NONE:
13413d8817e4Smiod       /* Normal insn.  */
13423d8817e4Smiod       output_insn (insn, &the_insn);
13433d8817e4Smiod       break;
13443d8817e4Smiod 
13453d8817e4Smiod     case SPECIAL_CASE_SETSW:
13463d8817e4Smiod       synthetize_setsw (insn);
13473d8817e4Smiod       break;
13483d8817e4Smiod 
13493d8817e4Smiod     case SPECIAL_CASE_SET:
13503d8817e4Smiod       synthetize_setuw (insn);
13513d8817e4Smiod       break;
13523d8817e4Smiod 
13533d8817e4Smiod     case SPECIAL_CASE_SETX:
13543d8817e4Smiod       synthetize_setx (insn);
13553d8817e4Smiod       break;
13563d8817e4Smiod 
13573d8817e4Smiod     case SPECIAL_CASE_FDIV:
13583d8817e4Smiod       {
13593d8817e4Smiod 	int rd = (the_insn.opcode >> 25) & 0x1f;
13603d8817e4Smiod 
13613d8817e4Smiod 	output_insn (insn, &the_insn);
13623d8817e4Smiod 
13633d8817e4Smiod 	/* According to information leaked from Sun, the "fdiv" instructions
13643d8817e4Smiod 	   on early SPARC machines would produce incorrect results sometimes.
13653d8817e4Smiod 	   The workaround is to add an fmovs of the destination register to
13663d8817e4Smiod 	   itself just after the instruction.  This was true on machines
13673d8817e4Smiod 	   with Weitek 1165 float chips, such as the Sun-4/260 and /280.  */
13683d8817e4Smiod 	assert (the_insn.reloc == BFD_RELOC_NONE);
13693d8817e4Smiod 	the_insn.opcode = FMOVS_INSN | rd | RD (rd);
13703d8817e4Smiod 	output_insn (insn, &the_insn);
13713d8817e4Smiod 	return;
13723d8817e4Smiod       }
13733d8817e4Smiod 
13743d8817e4Smiod     default:
13753d8817e4Smiod       as_fatal (_("failed special case insn sanity check"));
13763d8817e4Smiod     }
13773d8817e4Smiod }
13783d8817e4Smiod 
13793d8817e4Smiod /* Subroutine of md_assemble to do the actual parsing.  */
13803d8817e4Smiod 
13813d8817e4Smiod static int
sparc_ip(str,pinsn)13823d8817e4Smiod sparc_ip (str, pinsn)
13833d8817e4Smiod      char *str;
13843d8817e4Smiod      const struct sparc_opcode **pinsn;
13853d8817e4Smiod {
13863d8817e4Smiod   char *error_message = "";
13873d8817e4Smiod   char *s;
13883d8817e4Smiod   const char *args;
13893d8817e4Smiod   char c;
13903d8817e4Smiod   const struct sparc_opcode *insn;
13913d8817e4Smiod   char *argsStart;
13923d8817e4Smiod   unsigned long opcode;
13933d8817e4Smiod   unsigned int mask = 0;
13943d8817e4Smiod   int match = 0;
13953d8817e4Smiod   int comma = 0;
13963d8817e4Smiod   int v9_arg_p;
13973d8817e4Smiod   int special_case = SPECIAL_CASE_NONE;
13983d8817e4Smiod 
13993d8817e4Smiod   s = str;
14003d8817e4Smiod   if (ISLOWER (*s))
14013d8817e4Smiod     {
14023d8817e4Smiod       do
14033d8817e4Smiod 	++s;
14043d8817e4Smiod       while (ISLOWER (*s) || ISDIGIT (*s));
14053d8817e4Smiod     }
14063d8817e4Smiod 
14073d8817e4Smiod   switch (*s)
14083d8817e4Smiod     {
14093d8817e4Smiod     case '\0':
14103d8817e4Smiod       break;
14113d8817e4Smiod 
14123d8817e4Smiod     case ',':
14133d8817e4Smiod       comma = 1;
14143d8817e4Smiod       /* Fall through.  */
14153d8817e4Smiod 
14163d8817e4Smiod     case ' ':
14173d8817e4Smiod       *s++ = '\0';
14183d8817e4Smiod       break;
14193d8817e4Smiod 
14203d8817e4Smiod     default:
14213d8817e4Smiod       as_bad (_("Unknown opcode: `%s'"), str);
14223d8817e4Smiod       *pinsn = NULL;
14233d8817e4Smiod       return special_case;
14243d8817e4Smiod     }
14253d8817e4Smiod   insn = (struct sparc_opcode *) hash_find (op_hash, str);
14263d8817e4Smiod   *pinsn = insn;
14273d8817e4Smiod   if (insn == NULL)
14283d8817e4Smiod     {
14293d8817e4Smiod       as_bad (_("Unknown opcode: `%s'"), str);
14303d8817e4Smiod       return special_case;
14313d8817e4Smiod     }
14323d8817e4Smiod   if (comma)
14333d8817e4Smiod     {
14343d8817e4Smiod       *--s = ',';
14353d8817e4Smiod     }
14363d8817e4Smiod 
14373d8817e4Smiod   argsStart = s;
14383d8817e4Smiod   for (;;)
14393d8817e4Smiod     {
14403d8817e4Smiod       opcode = insn->match;
14413d8817e4Smiod       memset (&the_insn, '\0', sizeof (the_insn));
14423d8817e4Smiod       the_insn.reloc = BFD_RELOC_NONE;
14433d8817e4Smiod       v9_arg_p = 0;
14443d8817e4Smiod 
14453d8817e4Smiod       /* Build the opcode, checking as we go to make sure that the
14463d8817e4Smiod          operands match.  */
14473d8817e4Smiod       for (args = insn->args;; ++args)
14483d8817e4Smiod 	{
14493d8817e4Smiod 	  switch (*args)
14503d8817e4Smiod 	    {
14513d8817e4Smiod 	    case 'K':
14523d8817e4Smiod 	      {
14533d8817e4Smiod 		int kmask = 0;
14543d8817e4Smiod 
14553d8817e4Smiod 		/* Parse a series of masks.  */
14563d8817e4Smiod 		if (*s == '#')
14573d8817e4Smiod 		  {
14583d8817e4Smiod 		    while (*s == '#')
14593d8817e4Smiod 		      {
14603d8817e4Smiod 			int mask;
14613d8817e4Smiod 
14623d8817e4Smiod 			if (! parse_keyword_arg (sparc_encode_membar, &s,
14633d8817e4Smiod 						 &mask))
14643d8817e4Smiod 			  {
14653d8817e4Smiod 			    error_message = _(": invalid membar mask name");
14663d8817e4Smiod 			    goto error;
14673d8817e4Smiod 			  }
14683d8817e4Smiod 			kmask |= mask;
14693d8817e4Smiod 			while (*s == ' ')
14703d8817e4Smiod 			  ++s;
14713d8817e4Smiod 			if (*s == '|' || *s == '+')
14723d8817e4Smiod 			  ++s;
14733d8817e4Smiod 			while (*s == ' ')
14743d8817e4Smiod 			  ++s;
14753d8817e4Smiod 		      }
14763d8817e4Smiod 		  }
14773d8817e4Smiod 		else
14783d8817e4Smiod 		  {
14793d8817e4Smiod 		    if (! parse_const_expr_arg (&s, &kmask))
14803d8817e4Smiod 		      {
14813d8817e4Smiod 			error_message = _(": invalid membar mask expression");
14823d8817e4Smiod 			goto error;
14833d8817e4Smiod 		      }
14843d8817e4Smiod 		    if (kmask < 0 || kmask > 127)
14853d8817e4Smiod 		      {
14863d8817e4Smiod 			error_message = _(": invalid membar mask number");
14873d8817e4Smiod 			goto error;
14883d8817e4Smiod 		      }
14893d8817e4Smiod 		  }
14903d8817e4Smiod 
14913d8817e4Smiod 		opcode |= MEMBAR (kmask);
14923d8817e4Smiod 		continue;
14933d8817e4Smiod 	      }
14943d8817e4Smiod 
14953d8817e4Smiod 	    case '3':
14963d8817e4Smiod 	      {
14973d8817e4Smiod 		int smask = 0;
14983d8817e4Smiod 
14993d8817e4Smiod 		if (! parse_const_expr_arg (&s, &smask))
15003d8817e4Smiod 		  {
15013d8817e4Smiod 		    error_message = _(": invalid siam mode expression");
15023d8817e4Smiod 		    goto error;
15033d8817e4Smiod 		  }
15043d8817e4Smiod 		if (smask < 0 || smask > 7)
15053d8817e4Smiod 		  {
15063d8817e4Smiod 		    error_message = _(": invalid siam mode number");
15073d8817e4Smiod 		    goto error;
15083d8817e4Smiod 		  }
15093d8817e4Smiod 		opcode |= smask;
15103d8817e4Smiod 		continue;
15113d8817e4Smiod 	      }
15123d8817e4Smiod 
15133d8817e4Smiod 	    case '*':
15143d8817e4Smiod 	      {
15153d8817e4Smiod 		int fcn = 0;
15163d8817e4Smiod 
15173d8817e4Smiod 		/* Parse a prefetch function.  */
15183d8817e4Smiod 		if (*s == '#')
15193d8817e4Smiod 		  {
15203d8817e4Smiod 		    if (! parse_keyword_arg (sparc_encode_prefetch, &s, &fcn))
15213d8817e4Smiod 		      {
15223d8817e4Smiod 			error_message = _(": invalid prefetch function name");
15233d8817e4Smiod 			goto error;
15243d8817e4Smiod 		      }
15253d8817e4Smiod 		  }
15263d8817e4Smiod 		else
15273d8817e4Smiod 		  {
15283d8817e4Smiod 		    if (! parse_const_expr_arg (&s, &fcn))
15293d8817e4Smiod 		      {
15303d8817e4Smiod 			error_message = _(": invalid prefetch function expression");
15313d8817e4Smiod 			goto error;
15323d8817e4Smiod 		      }
15333d8817e4Smiod 		    if (fcn < 0 || fcn > 31)
15343d8817e4Smiod 		      {
15353d8817e4Smiod 			error_message = _(": invalid prefetch function number");
15363d8817e4Smiod 			goto error;
15373d8817e4Smiod 		      }
15383d8817e4Smiod 		  }
15393d8817e4Smiod 		opcode |= RD (fcn);
15403d8817e4Smiod 		continue;
15413d8817e4Smiod 	      }
15423d8817e4Smiod 
15433d8817e4Smiod 	    case '!':
15443d8817e4Smiod 	    case '?':
15453d8817e4Smiod 	      /* Parse a sparc64 privileged register.  */
15463d8817e4Smiod 	      if (*s == '%')
15473d8817e4Smiod 		{
15483d8817e4Smiod 		  struct priv_reg_entry *p = priv_reg_table;
15493d8817e4Smiod 		  unsigned int len = 9999999; /* Init to make gcc happy.  */
15503d8817e4Smiod 
15513d8817e4Smiod 		  s += 1;
15523d8817e4Smiod 		  while (p->name[0] > s[0])
15533d8817e4Smiod 		    p++;
15543d8817e4Smiod 		  while (p->name[0] == s[0])
15553d8817e4Smiod 		    {
15563d8817e4Smiod 		      len = strlen (p->name);
15573d8817e4Smiod 		      if (strncmp (p->name, s, len) == 0)
15583d8817e4Smiod 			break;
15593d8817e4Smiod 		      p++;
15603d8817e4Smiod 		    }
15613d8817e4Smiod 		  if (p->name[0] != s[0])
15623d8817e4Smiod 		    {
15633d8817e4Smiod 		      error_message = _(": unrecognizable privileged register");
15643d8817e4Smiod 		      goto error;
15653d8817e4Smiod 		    }
15663d8817e4Smiod 		  if (*args == '?')
15673d8817e4Smiod 		    opcode |= (p->regnum << 14);
15683d8817e4Smiod 		  else
15693d8817e4Smiod 		    opcode |= (p->regnum << 25);
15703d8817e4Smiod 		  s += len;
15713d8817e4Smiod 		  continue;
15723d8817e4Smiod 		}
15733d8817e4Smiod 	      else
15743d8817e4Smiod 		{
15753d8817e4Smiod 		  error_message = _(": unrecognizable privileged register");
15763d8817e4Smiod 		  goto error;
15773d8817e4Smiod 		}
15783d8817e4Smiod 
15793d8817e4Smiod 	    case '$':
15803d8817e4Smiod 	    case '%':
15813d8817e4Smiod 	      /* Parse a sparc64 hyperprivileged register.  */
15823d8817e4Smiod 	      if (*s == '%')
15833d8817e4Smiod 		{
15843d8817e4Smiod 		  struct priv_reg_entry *p = hpriv_reg_table;
15853d8817e4Smiod 		  unsigned int len = 9999999; /* Init to make gcc happy.  */
15863d8817e4Smiod 
15873d8817e4Smiod 		  s += 1;
15883d8817e4Smiod 		  while (p->name[0] > s[0])
15893d8817e4Smiod 		    p++;
15903d8817e4Smiod 		  while (p->name[0] == s[0])
15913d8817e4Smiod 		    {
15923d8817e4Smiod 		      len = strlen (p->name);
15933d8817e4Smiod 		      if (strncmp (p->name, s, len) == 0)
15943d8817e4Smiod 			break;
15953d8817e4Smiod 		      p++;
15963d8817e4Smiod 		    }
15973d8817e4Smiod 		  if (p->name[0] != s[0])
15983d8817e4Smiod 		    {
15993d8817e4Smiod 		      error_message = _(": unrecognizable hyperprivileged register");
16003d8817e4Smiod 		      goto error;
16013d8817e4Smiod 		    }
16023d8817e4Smiod 		  if (*args == '$')
16033d8817e4Smiod 		    opcode |= (p->regnum << 14);
16043d8817e4Smiod 		  else
16053d8817e4Smiod 		    opcode |= (p->regnum << 25);
16063d8817e4Smiod 		  s += len;
16073d8817e4Smiod 		  continue;
16083d8817e4Smiod 		}
16093d8817e4Smiod 	      else
16103d8817e4Smiod 		{
16113d8817e4Smiod 		  error_message = _(": unrecognizable hyperprivileged register");
16123d8817e4Smiod 		  goto error;
16133d8817e4Smiod 		}
16143d8817e4Smiod 
16153d8817e4Smiod 	    case '_':
16163d8817e4Smiod 	    case '/':
16173d8817e4Smiod 	      /* Parse a v9a/v9b ancillary state register.  */
16183d8817e4Smiod 	      if (*s == '%')
16193d8817e4Smiod 		{
16203d8817e4Smiod 		  struct priv_reg_entry *p = v9a_asr_table;
16213d8817e4Smiod 		  unsigned int len = 9999999; /* Init to make gcc happy.  */
16223d8817e4Smiod 
16233d8817e4Smiod 		  s += 1;
16243d8817e4Smiod 		  while (p->name[0] > s[0])
16253d8817e4Smiod 		    p++;
16263d8817e4Smiod 		  while (p->name[0] == s[0])
16273d8817e4Smiod 		    {
16283d8817e4Smiod 		      len = strlen (p->name);
16293d8817e4Smiod 		      if (strncmp (p->name, s, len) == 0)
16303d8817e4Smiod 			break;
16313d8817e4Smiod 		      p++;
16323d8817e4Smiod 		    }
16333d8817e4Smiod 		  if (p->name[0] != s[0])
16343d8817e4Smiod 		    {
16353d8817e4Smiod 		      error_message = _(": unrecognizable v9a or v9b ancillary state register");
16363d8817e4Smiod 		      goto error;
16373d8817e4Smiod 		    }
16383d8817e4Smiod 		  if (*args == '/' && (p->regnum == 20 || p->regnum == 21))
16393d8817e4Smiod 		    {
16403d8817e4Smiod 		      error_message = _(": rd on write only ancillary state register");
16413d8817e4Smiod 		      goto error;
16423d8817e4Smiod 		    }
16433d8817e4Smiod 		  if (p->regnum >= 24
16443d8817e4Smiod 		      && (insn->architecture
16453d8817e4Smiod 			  & SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9A)))
16463d8817e4Smiod 		    {
16473d8817e4Smiod 		      /* %sys_tick and %sys_tick_cmpr are v9bnotv9a */
16483d8817e4Smiod 		      error_message = _(": unrecognizable v9a ancillary state register");
16493d8817e4Smiod 		      goto error;
16503d8817e4Smiod 		    }
16513d8817e4Smiod 		  if (*args == '/')
16523d8817e4Smiod 		    opcode |= (p->regnum << 14);
16533d8817e4Smiod 		  else
16543d8817e4Smiod 		    opcode |= (p->regnum << 25);
16553d8817e4Smiod 		  s += len;
16563d8817e4Smiod 		  continue;
16573d8817e4Smiod 		}
16583d8817e4Smiod 	      else
16593d8817e4Smiod 		{
16603d8817e4Smiod 		  error_message = _(": unrecognizable v9a or v9b ancillary state register");
16613d8817e4Smiod 		  goto error;
16623d8817e4Smiod 		}
16633d8817e4Smiod 
16643d8817e4Smiod 	    case 'M':
16653d8817e4Smiod 	    case 'm':
16663d8817e4Smiod 	      if (strncmp (s, "%asr", 4) == 0)
16673d8817e4Smiod 		{
16683d8817e4Smiod 		  s += 4;
16693d8817e4Smiod 
16703d8817e4Smiod 		  if (ISDIGIT (*s))
16713d8817e4Smiod 		    {
16723d8817e4Smiod 		      long num = 0;
16733d8817e4Smiod 
16743d8817e4Smiod 		      while (ISDIGIT (*s))
16753d8817e4Smiod 			{
16763d8817e4Smiod 			  num = num * 10 + *s - '0';
16773d8817e4Smiod 			  ++s;
16783d8817e4Smiod 			}
16793d8817e4Smiod 
16803d8817e4Smiod 		      if (current_architecture >= SPARC_OPCODE_ARCH_V9)
16813d8817e4Smiod 			{
16823d8817e4Smiod 			  if (num < 16 || 31 < num)
16833d8817e4Smiod 			    {
16843d8817e4Smiod 			      error_message = _(": asr number must be between 16 and 31");
16853d8817e4Smiod 			      goto error;
16863d8817e4Smiod 			    }
16873d8817e4Smiod 			}
16883d8817e4Smiod 		      else
16893d8817e4Smiod 			{
16903d8817e4Smiod 			  if (num < 0 || 31 < num)
16913d8817e4Smiod 			    {
16923d8817e4Smiod 			      error_message = _(": asr number must be between 0 and 31");
16933d8817e4Smiod 			      goto error;
16943d8817e4Smiod 			    }
16953d8817e4Smiod 			}
16963d8817e4Smiod 
16973d8817e4Smiod 		      opcode |= (*args == 'M' ? RS1 (num) : RD (num));
16983d8817e4Smiod 		      continue;
16993d8817e4Smiod 		    }
17003d8817e4Smiod 		  else
17013d8817e4Smiod 		    {
17023d8817e4Smiod 		      error_message = _(": expecting %asrN");
17033d8817e4Smiod 		      goto error;
17043d8817e4Smiod 		    }
17053d8817e4Smiod 		} /* if %asr  */
17063d8817e4Smiod 	      break;
17073d8817e4Smiod 
17083d8817e4Smiod 	    case 'I':
17093d8817e4Smiod 	      the_insn.reloc = BFD_RELOC_SPARC_11;
17103d8817e4Smiod 	      goto immediate;
17113d8817e4Smiod 
17123d8817e4Smiod 	    case 'j':
17133d8817e4Smiod 	      the_insn.reloc = BFD_RELOC_SPARC_10;
17143d8817e4Smiod 	      goto immediate;
17153d8817e4Smiod 
17163d8817e4Smiod 	    case 'X':
17173d8817e4Smiod 	      /* V8 systems don't understand BFD_RELOC_SPARC_5.  */
17183d8817e4Smiod 	      if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
17193d8817e4Smiod 		the_insn.reloc = BFD_RELOC_SPARC_5;
17203d8817e4Smiod 	      else
17213d8817e4Smiod 		the_insn.reloc = BFD_RELOC_SPARC13;
17223d8817e4Smiod 	      /* These fields are unsigned, but for upward compatibility,
17233d8817e4Smiod 		 allow negative values as well.  */
17243d8817e4Smiod 	      goto immediate;
17253d8817e4Smiod 
17263d8817e4Smiod 	    case 'Y':
17273d8817e4Smiod 	      /* V8 systems don't understand BFD_RELOC_SPARC_6.  */
17283d8817e4Smiod 	      if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
17293d8817e4Smiod 		the_insn.reloc = BFD_RELOC_SPARC_6;
17303d8817e4Smiod 	      else
17313d8817e4Smiod 		the_insn.reloc = BFD_RELOC_SPARC13;
17323d8817e4Smiod 	      /* These fields are unsigned, but for upward compatibility,
17333d8817e4Smiod 		 allow negative values as well.  */
17343d8817e4Smiod 	      goto immediate;
17353d8817e4Smiod 
17363d8817e4Smiod 	    case 'k':
17373d8817e4Smiod 	      the_insn.reloc = /* RELOC_WDISP2_14 */ BFD_RELOC_SPARC_WDISP16;
17383d8817e4Smiod 	      the_insn.pcrel = 1;
17393d8817e4Smiod 	      goto immediate;
17403d8817e4Smiod 
17413d8817e4Smiod 	    case 'G':
17423d8817e4Smiod 	      the_insn.reloc = BFD_RELOC_SPARC_WDISP19;
17433d8817e4Smiod 	      the_insn.pcrel = 1;
17443d8817e4Smiod 	      goto immediate;
17453d8817e4Smiod 
17463d8817e4Smiod 	    case 'N':
17473d8817e4Smiod 	      if (*s == 'p' && s[1] == 'n')
17483d8817e4Smiod 		{
17493d8817e4Smiod 		  s += 2;
17503d8817e4Smiod 		  continue;
17513d8817e4Smiod 		}
17523d8817e4Smiod 	      break;
17533d8817e4Smiod 
17543d8817e4Smiod 	    case 'T':
17553d8817e4Smiod 	      if (*s == 'p' && s[1] == 't')
17563d8817e4Smiod 		{
17573d8817e4Smiod 		  s += 2;
17583d8817e4Smiod 		  continue;
17593d8817e4Smiod 		}
17603d8817e4Smiod 	      break;
17613d8817e4Smiod 
17623d8817e4Smiod 	    case 'z':
17633d8817e4Smiod 	      if (*s == ' ')
17643d8817e4Smiod 		{
17653d8817e4Smiod 		  ++s;
17663d8817e4Smiod 		}
17673d8817e4Smiod 	      if (strncmp (s, "%icc", 4) == 0)
17683d8817e4Smiod 		{
17693d8817e4Smiod 		  s += 4;
17703d8817e4Smiod 		  continue;
17713d8817e4Smiod 		}
17723d8817e4Smiod 	      break;
17733d8817e4Smiod 
17743d8817e4Smiod 	    case 'Z':
17753d8817e4Smiod 	      if (*s == ' ')
17763d8817e4Smiod 		{
17773d8817e4Smiod 		  ++s;
17783d8817e4Smiod 		}
17793d8817e4Smiod 	      if (strncmp (s, "%xcc", 4) == 0)
17803d8817e4Smiod 		{
17813d8817e4Smiod 		  s += 4;
17823d8817e4Smiod 		  continue;
17833d8817e4Smiod 		}
17843d8817e4Smiod 	      break;
17853d8817e4Smiod 
17863d8817e4Smiod 	    case '6':
17873d8817e4Smiod 	      if (*s == ' ')
17883d8817e4Smiod 		{
17893d8817e4Smiod 		  ++s;
17903d8817e4Smiod 		}
17913d8817e4Smiod 	      if (strncmp (s, "%fcc0", 5) == 0)
17923d8817e4Smiod 		{
17933d8817e4Smiod 		  s += 5;
17943d8817e4Smiod 		  continue;
17953d8817e4Smiod 		}
17963d8817e4Smiod 	      break;
17973d8817e4Smiod 
17983d8817e4Smiod 	    case '7':
17993d8817e4Smiod 	      if (*s == ' ')
18003d8817e4Smiod 		{
18013d8817e4Smiod 		  ++s;
18023d8817e4Smiod 		}
18033d8817e4Smiod 	      if (strncmp (s, "%fcc1", 5) == 0)
18043d8817e4Smiod 		{
18053d8817e4Smiod 		  s += 5;
18063d8817e4Smiod 		  continue;
18073d8817e4Smiod 		}
18083d8817e4Smiod 	      break;
18093d8817e4Smiod 
18103d8817e4Smiod 	    case '8':
18113d8817e4Smiod 	      if (*s == ' ')
18123d8817e4Smiod 		{
18133d8817e4Smiod 		  ++s;
18143d8817e4Smiod 		}
18153d8817e4Smiod 	      if (strncmp (s, "%fcc2", 5) == 0)
18163d8817e4Smiod 		{
18173d8817e4Smiod 		  s += 5;
18183d8817e4Smiod 		  continue;
18193d8817e4Smiod 		}
18203d8817e4Smiod 	      break;
18213d8817e4Smiod 
18223d8817e4Smiod 	    case '9':
18233d8817e4Smiod 	      if (*s == ' ')
18243d8817e4Smiod 		{
18253d8817e4Smiod 		  ++s;
18263d8817e4Smiod 		}
18273d8817e4Smiod 	      if (strncmp (s, "%fcc3", 5) == 0)
18283d8817e4Smiod 		{
18293d8817e4Smiod 		  s += 5;
18303d8817e4Smiod 		  continue;
18313d8817e4Smiod 		}
18323d8817e4Smiod 	      break;
18333d8817e4Smiod 
18343d8817e4Smiod 	    case 'P':
18353d8817e4Smiod 	      if (strncmp (s, "%pc", 3) == 0)
18363d8817e4Smiod 		{
18373d8817e4Smiod 		  s += 3;
18383d8817e4Smiod 		  continue;
18393d8817e4Smiod 		}
18403d8817e4Smiod 	      break;
18413d8817e4Smiod 
18423d8817e4Smiod 	    case 'W':
18433d8817e4Smiod 	      if (strncmp (s, "%tick", 5) == 0)
18443d8817e4Smiod 		{
18453d8817e4Smiod 		  s += 5;
18463d8817e4Smiod 		  continue;
18473d8817e4Smiod 		}
18483d8817e4Smiod 	      break;
18493d8817e4Smiod 
18503d8817e4Smiod 	    case '\0':		/* End of args.  */
18513d8817e4Smiod 	      if (s[0] == ',' && s[1] == '%')
18523d8817e4Smiod 		{
18533d8817e4Smiod 		  static const struct tls_ops {
18543d8817e4Smiod 		    /* The name as it appears in assembler.  */
18553d8817e4Smiod 		    char *name;
18563d8817e4Smiod 		    /* strlen (name), precomputed for speed */
18573d8817e4Smiod 		    int len;
18583d8817e4Smiod 		    /* The reloc this pseudo-op translates to.  */
18593d8817e4Smiod 		    int reloc;
18603d8817e4Smiod 		    /* 1 if call.  */
18613d8817e4Smiod 		    int call;
18623d8817e4Smiod 		  } tls_ops[] = {
18633d8817e4Smiod 		    { "tgd_add", 7, BFD_RELOC_SPARC_TLS_GD_ADD, 0 },
18643d8817e4Smiod 		    { "tgd_call", 8, BFD_RELOC_SPARC_TLS_GD_CALL, 1 },
18653d8817e4Smiod 		    { "tldm_add", 8, BFD_RELOC_SPARC_TLS_LDM_ADD, 0 },
18663d8817e4Smiod 		    { "tldm_call", 9, BFD_RELOC_SPARC_TLS_LDM_CALL, 1 },
18673d8817e4Smiod 		    { "tldo_add", 8, BFD_RELOC_SPARC_TLS_LDO_ADD, 0 },
18683d8817e4Smiod 		    { "tie_ldx", 7, BFD_RELOC_SPARC_TLS_IE_LDX, 0 },
18693d8817e4Smiod 		    { "tie_ld", 6, BFD_RELOC_SPARC_TLS_IE_LD, 0 },
18703d8817e4Smiod 		    { "tie_add", 7, BFD_RELOC_SPARC_TLS_IE_ADD, 0 }
18713d8817e4Smiod 		  };
18723d8817e4Smiod 		  const struct tls_ops *o;
18733d8817e4Smiod 		  char *s1;
18743d8817e4Smiod 		  int npar = 0;
18753d8817e4Smiod 
18763d8817e4Smiod 		  for (o = tls_ops; o->name; o++)
18773d8817e4Smiod 		    if (strncmp (s + 2, o->name, o->len) == 0)
18783d8817e4Smiod 		      break;
18793d8817e4Smiod 		  if (o->name == NULL)
18803d8817e4Smiod 		    break;
18813d8817e4Smiod 
18823d8817e4Smiod 		  if (s[o->len + 2] != '(')
18833d8817e4Smiod 		    {
18843d8817e4Smiod 		      as_bad (_("Illegal operands: %%%s requires arguments in ()"), o->name);
18853d8817e4Smiod 		      return special_case;
18863d8817e4Smiod 		    }
18873d8817e4Smiod 
18883d8817e4Smiod 		  if (! o->call && the_insn.reloc != BFD_RELOC_NONE)
18893d8817e4Smiod 		    {
18903d8817e4Smiod 		      as_bad (_("Illegal operands: %%%s cannot be used together with other relocs in the insn ()"),
18913d8817e4Smiod 			      o->name);
18923d8817e4Smiod 		      return special_case;
18933d8817e4Smiod 		    }
18943d8817e4Smiod 
18953d8817e4Smiod 		  if (o->call
18963d8817e4Smiod 		      && (the_insn.reloc != BFD_RELOC_32_PCREL_S2
18973d8817e4Smiod 			  || the_insn.exp.X_add_number != 0
18983d8817e4Smiod 			  || the_insn.exp.X_add_symbol
18993d8817e4Smiod 			     != symbol_find_or_make ("__tls_get_addr")))
19003d8817e4Smiod 		    {
19013d8817e4Smiod 		      as_bad (_("Illegal operands: %%%s can be only used with call __tls_get_addr"),
19023d8817e4Smiod 			      o->name);
19033d8817e4Smiod 		      return special_case;
19043d8817e4Smiod 		    }
19053d8817e4Smiod 
19063d8817e4Smiod 		  the_insn.reloc = o->reloc;
19073d8817e4Smiod 		  memset (&the_insn.exp, 0, sizeof (the_insn.exp));
19083d8817e4Smiod 		  s += o->len + 3;
19093d8817e4Smiod 
19103d8817e4Smiod 		  for (s1 = s; *s1 && *s1 != ',' && *s1 != ']'; s1++)
19113d8817e4Smiod 		    if (*s1 == '(')
19123d8817e4Smiod 		      npar++;
19133d8817e4Smiod 		    else if (*s1 == ')')
19143d8817e4Smiod 		      {
19153d8817e4Smiod 			if (!npar)
19163d8817e4Smiod 			  break;
19173d8817e4Smiod 			npar--;
19183d8817e4Smiod 		      }
19193d8817e4Smiod 
19203d8817e4Smiod 		  if (*s1 != ')')
19213d8817e4Smiod 		    {
19223d8817e4Smiod 		      as_bad (_("Illegal operands: %%%s requires arguments in ()"), o->name);
19233d8817e4Smiod 		      return special_case;
19243d8817e4Smiod 		    }
19253d8817e4Smiod 
19263d8817e4Smiod 		  *s1 = '\0';
19273d8817e4Smiod 		  (void) get_expression (s);
19283d8817e4Smiod 		  *s1 = ')';
19293d8817e4Smiod 		  s = s1 + 1;
19303d8817e4Smiod 		}
19313d8817e4Smiod 	      if (*s == '\0')
19323d8817e4Smiod 		match = 1;
19333d8817e4Smiod 	      break;
19343d8817e4Smiod 
19353d8817e4Smiod 	    case '+':
19363d8817e4Smiod 	      if (*s == '+')
19373d8817e4Smiod 		{
19383d8817e4Smiod 		  ++s;
19393d8817e4Smiod 		  continue;
19403d8817e4Smiod 		}
19413d8817e4Smiod 	      if (*s == '-')
19423d8817e4Smiod 		{
19433d8817e4Smiod 		  continue;
19443d8817e4Smiod 		}
19453d8817e4Smiod 	      break;
19463d8817e4Smiod 
19473d8817e4Smiod 	    case '[':		/* These must match exactly.  */
19483d8817e4Smiod 	    case ']':
19493d8817e4Smiod 	    case ',':
19503d8817e4Smiod 	    case ' ':
19513d8817e4Smiod 	      if (*s++ == *args)
19523d8817e4Smiod 		continue;
19533d8817e4Smiod 	      break;
19543d8817e4Smiod 
19553d8817e4Smiod 	    case '#':		/* Must be at least one digit.  */
19563d8817e4Smiod 	      if (ISDIGIT (*s++))
19573d8817e4Smiod 		{
19583d8817e4Smiod 		  while (ISDIGIT (*s))
19593d8817e4Smiod 		    {
19603d8817e4Smiod 		      ++s;
19613d8817e4Smiod 		    }
19623d8817e4Smiod 		  continue;
19633d8817e4Smiod 		}
19643d8817e4Smiod 	      break;
19653d8817e4Smiod 
19663d8817e4Smiod 	    case 'C':		/* Coprocessor state register.  */
19673d8817e4Smiod 	      if (strncmp (s, "%csr", 4) == 0)
19683d8817e4Smiod 		{
19693d8817e4Smiod 		  s += 4;
19703d8817e4Smiod 		  continue;
19713d8817e4Smiod 		}
19723d8817e4Smiod 	      break;
19733d8817e4Smiod 
19743d8817e4Smiod 	    case 'b':		/* Next operand is a coprocessor register.  */
19753d8817e4Smiod 	    case 'c':
19763d8817e4Smiod 	    case 'D':
19773d8817e4Smiod 	      if (*s++ == '%' && *s++ == 'c' && ISDIGIT (*s))
19783d8817e4Smiod 		{
19793d8817e4Smiod 		  mask = *s++;
19803d8817e4Smiod 		  if (ISDIGIT (*s))
19813d8817e4Smiod 		    {
19823d8817e4Smiod 		      mask = 10 * (mask - '0') + (*s++ - '0');
19833d8817e4Smiod 		      if (mask >= 32)
19843d8817e4Smiod 			{
19853d8817e4Smiod 			  break;
19863d8817e4Smiod 			}
19873d8817e4Smiod 		    }
19883d8817e4Smiod 		  else
19893d8817e4Smiod 		    {
19903d8817e4Smiod 		      mask -= '0';
19913d8817e4Smiod 		    }
19923d8817e4Smiod 		  switch (*args)
19933d8817e4Smiod 		    {
19943d8817e4Smiod 
19953d8817e4Smiod 		    case 'b':
19963d8817e4Smiod 		      opcode |= mask << 14;
19973d8817e4Smiod 		      continue;
19983d8817e4Smiod 
19993d8817e4Smiod 		    case 'c':
20003d8817e4Smiod 		      opcode |= mask;
20013d8817e4Smiod 		      continue;
20023d8817e4Smiod 
20033d8817e4Smiod 		    case 'D':
20043d8817e4Smiod 		      opcode |= mask << 25;
20053d8817e4Smiod 		      continue;
20063d8817e4Smiod 		    }
20073d8817e4Smiod 		}
20083d8817e4Smiod 	      break;
20093d8817e4Smiod 
20103d8817e4Smiod 	    case 'r':		/* next operand must be a register */
20113d8817e4Smiod 	    case 'O':
20123d8817e4Smiod 	    case '1':
20133d8817e4Smiod 	    case '2':
20143d8817e4Smiod 	    case 'd':
20153d8817e4Smiod 	      if (*s++ == '%')
20163d8817e4Smiod 		{
20173d8817e4Smiod 		  switch (c = *s++)
20183d8817e4Smiod 		    {
20193d8817e4Smiod 
20203d8817e4Smiod 		    case 'f':	/* frame pointer */
20213d8817e4Smiod 		      if (*s++ == 'p')
20223d8817e4Smiod 			{
20233d8817e4Smiod 			  mask = 0x1e;
20243d8817e4Smiod 			  break;
20253d8817e4Smiod 			}
20263d8817e4Smiod 		      goto error;
20273d8817e4Smiod 
20283d8817e4Smiod 		    case 'g':	/* global register */
20293d8817e4Smiod 		      c = *s++;
20303d8817e4Smiod 		      if (isoctal (c))
20313d8817e4Smiod 			{
20323d8817e4Smiod 			  mask = c - '0';
20333d8817e4Smiod 			  break;
20343d8817e4Smiod 			}
20353d8817e4Smiod 		      goto error;
20363d8817e4Smiod 
20373d8817e4Smiod 		    case 'i':	/* in register */
20383d8817e4Smiod 		      c = *s++;
20393d8817e4Smiod 		      if (isoctal (c))
20403d8817e4Smiod 			{
20413d8817e4Smiod 			  mask = c - '0' + 24;
20423d8817e4Smiod 			  break;
20433d8817e4Smiod 			}
20443d8817e4Smiod 		      goto error;
20453d8817e4Smiod 
20463d8817e4Smiod 		    case 'l':	/* local register */
20473d8817e4Smiod 		      c = *s++;
20483d8817e4Smiod 		      if (isoctal (c))
20493d8817e4Smiod 			{
20503d8817e4Smiod 			  mask = (c - '0' + 16);
20513d8817e4Smiod 			  break;
20523d8817e4Smiod 			}
20533d8817e4Smiod 		      goto error;
20543d8817e4Smiod 
20553d8817e4Smiod 		    case 'o':	/* out register */
20563d8817e4Smiod 		      c = *s++;
20573d8817e4Smiod 		      if (isoctal (c))
20583d8817e4Smiod 			{
20593d8817e4Smiod 			  mask = (c - '0' + 8);
20603d8817e4Smiod 			  break;
20613d8817e4Smiod 			}
20623d8817e4Smiod 		      goto error;
20633d8817e4Smiod 
20643d8817e4Smiod 		    case 's':	/* stack pointer */
20653d8817e4Smiod 		      if (*s++ == 'p')
20663d8817e4Smiod 			{
20673d8817e4Smiod 			  mask = 0xe;
20683d8817e4Smiod 			  break;
20693d8817e4Smiod 			}
20703d8817e4Smiod 		      goto error;
20713d8817e4Smiod 
20723d8817e4Smiod 		    case 'r':	/* any register */
20733d8817e4Smiod 		      if (!ISDIGIT ((c = *s++)))
20743d8817e4Smiod 			{
20753d8817e4Smiod 			  goto error;
20763d8817e4Smiod 			}
20773d8817e4Smiod 		      /* FALLTHROUGH */
20783d8817e4Smiod 		    case '0':
20793d8817e4Smiod 		    case '1':
20803d8817e4Smiod 		    case '2':
20813d8817e4Smiod 		    case '3':
20823d8817e4Smiod 		    case '4':
20833d8817e4Smiod 		    case '5':
20843d8817e4Smiod 		    case '6':
20853d8817e4Smiod 		    case '7':
20863d8817e4Smiod 		    case '8':
20873d8817e4Smiod 		    case '9':
20883d8817e4Smiod 		      if (ISDIGIT (*s))
20893d8817e4Smiod 			{
20903d8817e4Smiod 			  if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32)
20913d8817e4Smiod 			    {
20923d8817e4Smiod 			      goto error;
20933d8817e4Smiod 			    }
20943d8817e4Smiod 			}
20953d8817e4Smiod 		      else
20963d8817e4Smiod 			{
20973d8817e4Smiod 			  c -= '0';
20983d8817e4Smiod 			}
20993d8817e4Smiod 		      mask = c;
21003d8817e4Smiod 		      break;
21013d8817e4Smiod 
21023d8817e4Smiod 		    default:
21033d8817e4Smiod 		      goto error;
21043d8817e4Smiod 		    }
21053d8817e4Smiod 
21063d8817e4Smiod 		  if ((mask & ~1) == 2 && sparc_arch_size == 64
21073d8817e4Smiod 		      && no_undeclared_regs && ! globals[mask])
21083d8817e4Smiod 		    as_bad (_("detected global register use not covered by .register pseudo-op"));
21093d8817e4Smiod 
21103d8817e4Smiod 		  /* Got the register, now figure out where
21113d8817e4Smiod 		     it goes in the opcode.  */
21123d8817e4Smiod 		  switch (*args)
21133d8817e4Smiod 		    {
21143d8817e4Smiod 		    case '1':
21153d8817e4Smiod 		      opcode |= mask << 14;
21163d8817e4Smiod 		      continue;
21173d8817e4Smiod 
21183d8817e4Smiod 		    case '2':
21193d8817e4Smiod 		      opcode |= mask;
21203d8817e4Smiod 		      continue;
21213d8817e4Smiod 
21223d8817e4Smiod 		    case 'd':
21233d8817e4Smiod 		      opcode |= mask << 25;
21243d8817e4Smiod 		      continue;
21253d8817e4Smiod 
21263d8817e4Smiod 		    case 'r':
21273d8817e4Smiod 		      opcode |= (mask << 25) | (mask << 14);
21283d8817e4Smiod 		      continue;
21293d8817e4Smiod 
21303d8817e4Smiod 		    case 'O':
21313d8817e4Smiod 		      opcode |= (mask << 25) | (mask << 0);
21323d8817e4Smiod 		      continue;
21333d8817e4Smiod 		    }
21343d8817e4Smiod 		}
21353d8817e4Smiod 	      break;
21363d8817e4Smiod 
21373d8817e4Smiod 	    case 'e':		/* next operand is a floating point register */
21383d8817e4Smiod 	    case 'v':
21393d8817e4Smiod 	    case 'V':
21403d8817e4Smiod 
21413d8817e4Smiod 	    case 'f':
21423d8817e4Smiod 	    case 'B':
21433d8817e4Smiod 	    case 'R':
21443d8817e4Smiod 
21453d8817e4Smiod 	    case 'g':
21463d8817e4Smiod 	    case 'H':
21473d8817e4Smiod 	    case 'J':
21483d8817e4Smiod 	      {
21493d8817e4Smiod 		char format;
21503d8817e4Smiod 
21513d8817e4Smiod 		if (*s++ == '%'
21523d8817e4Smiod 		    && ((format = *s) == 'f')
21533d8817e4Smiod 		    && ISDIGIT (*++s))
21543d8817e4Smiod 		  {
21553d8817e4Smiod 		    for (mask = 0; ISDIGIT (*s); ++s)
21563d8817e4Smiod 		      {
21573d8817e4Smiod 			mask = 10 * mask + (*s - '0');
21583d8817e4Smiod 		      }		/* read the number */
21593d8817e4Smiod 
21603d8817e4Smiod 		    if ((*args == 'v'
21613d8817e4Smiod 			 || *args == 'B'
21623d8817e4Smiod 			 || *args == 'H')
21633d8817e4Smiod 			&& (mask & 1))
21643d8817e4Smiod 		      {
21653d8817e4Smiod 			break;
21663d8817e4Smiod 		      }		/* register must be even numbered */
21673d8817e4Smiod 
21683d8817e4Smiod 		    if ((*args == 'V'
21693d8817e4Smiod 			 || *args == 'R'
21703d8817e4Smiod 			 || *args == 'J')
21713d8817e4Smiod 			&& (mask & 3))
21723d8817e4Smiod 		      {
21733d8817e4Smiod 			break;
21743d8817e4Smiod 		      }		/* register must be multiple of 4 */
21753d8817e4Smiod 
21763d8817e4Smiod 		    if (mask >= 64)
21773d8817e4Smiod 		      {
21783d8817e4Smiod 			if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
21793d8817e4Smiod 			  error_message = _(": There are only 64 f registers; [0-63]");
21803d8817e4Smiod 			else
21813d8817e4Smiod 			  error_message = _(": There are only 32 f registers; [0-31]");
21823d8817e4Smiod 			goto error;
21833d8817e4Smiod 		      }	/* on error */
21843d8817e4Smiod 		    else if (mask >= 32)
21853d8817e4Smiod 		      {
21863d8817e4Smiod 			if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
21873d8817e4Smiod 			  {
2188*d2386abeSmiod #if !defined(TE_OpenBSD)
21893d8817e4Smiod 			    if (*args == 'e' || *args == 'f' || *args == 'g')
21903d8817e4Smiod 			      {
21913d8817e4Smiod 				error_message
21923d8817e4Smiod 				  = _(": There are only 32 single precision f registers; [0-31]");
21933d8817e4Smiod 				goto error;
21943d8817e4Smiod 			      }
2195*d2386abeSmiod #endif
21963d8817e4Smiod 			    v9_arg_p = 1;
21973d8817e4Smiod 			    mask -= 31;	/* wrap high bit */
21983d8817e4Smiod 			  }
21993d8817e4Smiod 			else
22003d8817e4Smiod 			  {
22013d8817e4Smiod 			    error_message = _(": There are only 32 f registers; [0-31]");
22023d8817e4Smiod 			    goto error;
22033d8817e4Smiod 			  }
22043d8817e4Smiod 		      }
22053d8817e4Smiod 		  }
22063d8817e4Smiod 		else
22073d8817e4Smiod 		  {
22083d8817e4Smiod 		    break;
22093d8817e4Smiod 		  }	/* if not an 'f' register.  */
22103d8817e4Smiod 
22113d8817e4Smiod 		switch (*args)
22123d8817e4Smiod 		  {
22133d8817e4Smiod 		  case 'v':
22143d8817e4Smiod 		  case 'V':
22153d8817e4Smiod 		  case 'e':
22163d8817e4Smiod 		    opcode |= RS1 (mask);
22173d8817e4Smiod 		    continue;
22183d8817e4Smiod 
22193d8817e4Smiod 		  case 'f':
22203d8817e4Smiod 		  case 'B':
22213d8817e4Smiod 		  case 'R':
22223d8817e4Smiod 		    opcode |= RS2 (mask);
22233d8817e4Smiod 		    continue;
22243d8817e4Smiod 
22253d8817e4Smiod 		  case 'g':
22263d8817e4Smiod 		  case 'H':
22273d8817e4Smiod 		  case 'J':
22283d8817e4Smiod 		    opcode |= RD (mask);
22293d8817e4Smiod 		    continue;
22303d8817e4Smiod 		  }		/* Pack it in.  */
22313d8817e4Smiod 
22323d8817e4Smiod 		know (0);
22333d8817e4Smiod 		break;
22343d8817e4Smiod 	      }			/* float arg  */
22353d8817e4Smiod 
22363d8817e4Smiod 	    case 'F':
22373d8817e4Smiod 	      if (strncmp (s, "%fsr", 4) == 0)
22383d8817e4Smiod 		{
22393d8817e4Smiod 		  s += 4;
22403d8817e4Smiod 		  continue;
22413d8817e4Smiod 		}
22423d8817e4Smiod 	      break;
22433d8817e4Smiod 
22443d8817e4Smiod 	    case '0':		/* 64 bit immediate (set, setsw, setx insn)  */
22453d8817e4Smiod 	      the_insn.reloc = BFD_RELOC_NONE; /* reloc handled elsewhere  */
22463d8817e4Smiod 	      goto immediate;
22473d8817e4Smiod 
22483d8817e4Smiod 	    case 'l':		/* 22 bit PC relative immediate  */
22493d8817e4Smiod 	      the_insn.reloc = BFD_RELOC_SPARC_WDISP22;
22503d8817e4Smiod 	      the_insn.pcrel = 1;
22513d8817e4Smiod 	      goto immediate;
22523d8817e4Smiod 
22533d8817e4Smiod 	    case 'L':		/* 30 bit immediate  */
22543d8817e4Smiod 	      the_insn.reloc = BFD_RELOC_32_PCREL_S2;
22553d8817e4Smiod 	      the_insn.pcrel = 1;
22563d8817e4Smiod 	      goto immediate;
22573d8817e4Smiod 
22583d8817e4Smiod 	    case 'h':
22593d8817e4Smiod 	    case 'n':		/* 22 bit immediate  */
22603d8817e4Smiod 	      the_insn.reloc = BFD_RELOC_SPARC22;
22613d8817e4Smiod 	      goto immediate;
22623d8817e4Smiod 
22633d8817e4Smiod 	    case 'i':		/* 13 bit immediate  */
22643d8817e4Smiod 	      the_insn.reloc = BFD_RELOC_SPARC13;
22653d8817e4Smiod 
22663d8817e4Smiod 	      /* fallthrough */
22673d8817e4Smiod 
22683d8817e4Smiod 	    immediate:
22693d8817e4Smiod 	      if (*s == ' ')
22703d8817e4Smiod 		s++;
22713d8817e4Smiod 
22723d8817e4Smiod 	      {
22733d8817e4Smiod 		char *s1;
22743d8817e4Smiod 		char *op_arg = NULL;
22753d8817e4Smiod 		static expressionS op_exp;
22763d8817e4Smiod 		bfd_reloc_code_real_type old_reloc = the_insn.reloc;
22773d8817e4Smiod 
22783d8817e4Smiod 		/* Check for %hi, etc.  */
22793d8817e4Smiod 		if (*s == '%')
22803d8817e4Smiod 		  {
22813d8817e4Smiod 		    static const struct ops {
22823d8817e4Smiod 		      /* The name as it appears in assembler.  */
22833d8817e4Smiod 		      char *name;
22843d8817e4Smiod 		      /* strlen (name), precomputed for speed */
22853d8817e4Smiod 		      int len;
22863d8817e4Smiod 		      /* The reloc this pseudo-op translates to.  */
22873d8817e4Smiod 		      int reloc;
22883d8817e4Smiod 		      /* Non-zero if for v9 only.  */
22893d8817e4Smiod 		      int v9_p;
22903d8817e4Smiod 		      /* Non-zero if can be used in pc-relative contexts.  */
22913d8817e4Smiod 		      int pcrel_p;/*FIXME:wip*/
22923d8817e4Smiod 		    } ops[] = {
22933d8817e4Smiod 		      /* hix/lox must appear before hi/lo so %hix won't be
22943d8817e4Smiod 			 mistaken for %hi.  */
22953d8817e4Smiod 		      { "hix", 3, BFD_RELOC_SPARC_HIX22, 1, 0 },
22963d8817e4Smiod 		      { "lox", 3, BFD_RELOC_SPARC_LOX10, 1, 0 },
22973d8817e4Smiod 		      { "hi", 2, BFD_RELOC_HI22, 0, 1 },
22983d8817e4Smiod 		      { "lo", 2, BFD_RELOC_LO10, 0, 1 },
22993d8817e4Smiod 		      { "hh", 2, BFD_RELOC_SPARC_HH22, 1, 1 },
23003d8817e4Smiod 		      { "hm", 2, BFD_RELOC_SPARC_HM10, 1, 1 },
23013d8817e4Smiod 		      { "lm", 2, BFD_RELOC_SPARC_LM22, 1, 1 },
23023d8817e4Smiod 		      { "h44", 3, BFD_RELOC_SPARC_H44, 1, 0 },
23033d8817e4Smiod 		      { "m44", 3, BFD_RELOC_SPARC_M44, 1, 0 },
23043d8817e4Smiod 		      { "l44", 3, BFD_RELOC_SPARC_L44, 1, 0 },
23053d8817e4Smiod 		      { "uhi", 3, BFD_RELOC_SPARC_HH22, 1, 0 },
23063d8817e4Smiod 		      { "ulo", 3, BFD_RELOC_SPARC_HM10, 1, 0 },
23073d8817e4Smiod 		      { "tgd_hi22", 8, BFD_RELOC_SPARC_TLS_GD_HI22, 0, 0 },
23083d8817e4Smiod 		      { "tgd_lo10", 8, BFD_RELOC_SPARC_TLS_GD_LO10, 0, 0 },
23093d8817e4Smiod 		      { "tldm_hi22", 9, BFD_RELOC_SPARC_TLS_LDM_HI22, 0, 0 },
23103d8817e4Smiod 		      { "tldm_lo10", 9, BFD_RELOC_SPARC_TLS_LDM_LO10, 0, 0 },
23113d8817e4Smiod 		      { "tldo_hix22", 10, BFD_RELOC_SPARC_TLS_LDO_HIX22, 0,
23123d8817e4Smiod 									 0 },
23133d8817e4Smiod 		      { "tldo_lox10", 10, BFD_RELOC_SPARC_TLS_LDO_LOX10, 0,
23143d8817e4Smiod 									 0 },
23153d8817e4Smiod 		      { "tie_hi22", 8, BFD_RELOC_SPARC_TLS_IE_HI22, 0, 0 },
23163d8817e4Smiod 		      { "tie_lo10", 8, BFD_RELOC_SPARC_TLS_IE_LO10, 0, 0 },
23173d8817e4Smiod 		      { "tle_hix22", 9, BFD_RELOC_SPARC_TLS_LE_HIX22, 0, 0 },
23183d8817e4Smiod 		      { "tle_lox10", 9, BFD_RELOC_SPARC_TLS_LE_LOX10, 0, 0 },
23193d8817e4Smiod 		      { NULL, 0, 0, 0, 0 }
23203d8817e4Smiod 		    };
23213d8817e4Smiod 		    const struct ops *o;
23223d8817e4Smiod 
23233d8817e4Smiod 		    for (o = ops; o->name; o++)
23243d8817e4Smiod 		      if (strncmp (s + 1, o->name, o->len) == 0)
23253d8817e4Smiod 			break;
23263d8817e4Smiod 		    if (o->name == NULL)
23273d8817e4Smiod 		      break;
23283d8817e4Smiod 
23293d8817e4Smiod 		    if (s[o->len + 1] != '(')
23303d8817e4Smiod 		      {
23313d8817e4Smiod 			as_bad (_("Illegal operands: %%%s requires arguments in ()"), o->name);
23323d8817e4Smiod 			return special_case;
23333d8817e4Smiod 		      }
23343d8817e4Smiod 
23353d8817e4Smiod 		    op_arg = o->name;
23363d8817e4Smiod 		    the_insn.reloc = o->reloc;
23373d8817e4Smiod 		    s += o->len + 2;
23383d8817e4Smiod 		    v9_arg_p = o->v9_p;
23393d8817e4Smiod 		  }
23403d8817e4Smiod 
23413d8817e4Smiod 		/* Note that if the get_expression() fails, we will still
23423d8817e4Smiod 		   have created U entries in the symbol table for the
23433d8817e4Smiod 		   'symbols' in the input string.  Try not to create U
23443d8817e4Smiod 		   symbols for registers, etc.  */
23453d8817e4Smiod 
23463d8817e4Smiod 		/* This stuff checks to see if the expression ends in
23473d8817e4Smiod 		   +%reg.  If it does, it removes the register from
23483d8817e4Smiod 		   the expression, and re-sets 's' to point to the
23493d8817e4Smiod 		   right place.  */
23503d8817e4Smiod 
23513d8817e4Smiod 		if (op_arg)
23523d8817e4Smiod 		  {
23533d8817e4Smiod 		    int npar = 0;
23543d8817e4Smiod 
23553d8817e4Smiod 		    for (s1 = s; *s1 && *s1 != ',' && *s1 != ']'; s1++)
23563d8817e4Smiod 		      if (*s1 == '(')
23573d8817e4Smiod 			npar++;
23583d8817e4Smiod 		      else if (*s1 == ')')
23593d8817e4Smiod 			{
23603d8817e4Smiod 			  if (!npar)
23613d8817e4Smiod 			    break;
23623d8817e4Smiod 			  npar--;
23633d8817e4Smiod 			}
23643d8817e4Smiod 
23653d8817e4Smiod 		    if (*s1 != ')')
23663d8817e4Smiod 		      {
23673d8817e4Smiod 			as_bad (_("Illegal operands: %%%s requires arguments in ()"), op_arg);
23683d8817e4Smiod 			return special_case;
23693d8817e4Smiod 		      }
23703d8817e4Smiod 
23713d8817e4Smiod 		    *s1 = '\0';
23723d8817e4Smiod 		    (void) get_expression (s);
23733d8817e4Smiod 		    *s1 = ')';
23743d8817e4Smiod 		    s = s1 + 1;
23753d8817e4Smiod 		    if (*s == ',' || *s == ']' || !*s)
23763d8817e4Smiod 		      continue;
23773d8817e4Smiod 		    if (*s != '+' && *s != '-')
23783d8817e4Smiod 		      {
23793d8817e4Smiod 			as_bad (_("Illegal operands: Can't do arithmetics other than + and - involving %%%s()"), op_arg);
23803d8817e4Smiod 			return special_case;
23813d8817e4Smiod 		      }
23823d8817e4Smiod 		    *s1 = '0';
23833d8817e4Smiod 		    s = s1;
23843d8817e4Smiod 		    op_exp = the_insn.exp;
23853d8817e4Smiod 		    memset (&the_insn.exp, 0, sizeof (the_insn.exp));
23863d8817e4Smiod 		  }
23873d8817e4Smiod 
23883d8817e4Smiod 		for (s1 = s; *s1 && *s1 != ',' && *s1 != ']'; s1++)
23893d8817e4Smiod 		  ;
23903d8817e4Smiod 
23913d8817e4Smiod 		if (s1 != s && ISDIGIT (s1[-1]))
23923d8817e4Smiod 		  {
23933d8817e4Smiod 		    if (s1[-2] == '%' && s1[-3] == '+')
23943d8817e4Smiod 		      s1 -= 3;
23953d8817e4Smiod 		    else if (strchr ("goli0123456789", s1[-2]) && s1[-3] == '%' && s1[-4] == '+')
23963d8817e4Smiod 		      s1 -= 4;
23973d8817e4Smiod 		    else
23983d8817e4Smiod 		      s1 = NULL;
23993d8817e4Smiod 		    if (s1)
24003d8817e4Smiod 		      {
24013d8817e4Smiod 			*s1 = '\0';
24023d8817e4Smiod 			if (op_arg && s1 == s + 1)
24033d8817e4Smiod 			  the_insn.exp.X_op = O_absent;
24043d8817e4Smiod 			else
24053d8817e4Smiod 			  (void) get_expression (s);
24063d8817e4Smiod 			*s1 = '+';
24073d8817e4Smiod 			if (op_arg)
24083d8817e4Smiod 			  *s = ')';
24093d8817e4Smiod 			s = s1;
24103d8817e4Smiod 		      }
24113d8817e4Smiod 		  }
24123d8817e4Smiod 		else
24133d8817e4Smiod 		  s1 = NULL;
24143d8817e4Smiod 
24153d8817e4Smiod 		if (!s1)
24163d8817e4Smiod 		  {
24173d8817e4Smiod 		    (void) get_expression (s);
24183d8817e4Smiod 		    if (op_arg)
24193d8817e4Smiod 		      *s = ')';
24203d8817e4Smiod 		    s = expr_end;
24213d8817e4Smiod 		  }
24223d8817e4Smiod 
24233d8817e4Smiod 		if (op_arg)
24243d8817e4Smiod 		  {
24253d8817e4Smiod 		    the_insn.exp2 = the_insn.exp;
24263d8817e4Smiod 		    the_insn.exp = op_exp;
24273d8817e4Smiod 		    if (the_insn.exp2.X_op == O_absent)
24283d8817e4Smiod 		      the_insn.exp2.X_op = O_illegal;
24293d8817e4Smiod 		    else if (the_insn.exp.X_op == O_absent)
24303d8817e4Smiod 		      {
24313d8817e4Smiod 			the_insn.exp = the_insn.exp2;
24323d8817e4Smiod 			the_insn.exp2.X_op = O_illegal;
24333d8817e4Smiod 		      }
24343d8817e4Smiod 		    else if (the_insn.exp.X_op == O_constant)
24353d8817e4Smiod 		      {
24363d8817e4Smiod 			valueT val = the_insn.exp.X_add_number;
24373d8817e4Smiod 			switch (the_insn.reloc)
24383d8817e4Smiod 			  {
24393d8817e4Smiod 			  default:
24403d8817e4Smiod 			    break;
24413d8817e4Smiod 
24423d8817e4Smiod 			  case BFD_RELOC_SPARC_HH22:
24433d8817e4Smiod 			    val = BSR (val, 32);
24443d8817e4Smiod 			    /* Fall through.  */
24453d8817e4Smiod 
24463d8817e4Smiod 			  case BFD_RELOC_SPARC_LM22:
24473d8817e4Smiod 			  case BFD_RELOC_HI22:
24483d8817e4Smiod 			    val = (val >> 10) & 0x3fffff;
24493d8817e4Smiod 			    break;
24503d8817e4Smiod 
24513d8817e4Smiod 			  case BFD_RELOC_SPARC_HM10:
24523d8817e4Smiod 			    val = BSR (val, 32);
24533d8817e4Smiod 			    /* Fall through.  */
24543d8817e4Smiod 
24553d8817e4Smiod 			  case BFD_RELOC_LO10:
24563d8817e4Smiod 			    val &= 0x3ff;
24573d8817e4Smiod 			    break;
24583d8817e4Smiod 
24593d8817e4Smiod 			  case BFD_RELOC_SPARC_H44:
24603d8817e4Smiod 			    val >>= 22;
24613d8817e4Smiod 			    val &= 0x3fffff;
24623d8817e4Smiod 			    break;
24633d8817e4Smiod 
24643d8817e4Smiod 			  case BFD_RELOC_SPARC_M44:
24653d8817e4Smiod 			    val >>= 12;
24663d8817e4Smiod 			    val &= 0x3ff;
24673d8817e4Smiod 			    break;
24683d8817e4Smiod 
24693d8817e4Smiod 			  case BFD_RELOC_SPARC_L44:
24703d8817e4Smiod 			    val &= 0xfff;
24713d8817e4Smiod 			    break;
24723d8817e4Smiod 
24733d8817e4Smiod 			  case BFD_RELOC_SPARC_HIX22:
24743d8817e4Smiod 			    val = ~val;
24753d8817e4Smiod 			    val = (val >> 10) & 0x3fffff;
24763d8817e4Smiod 			    break;
24773d8817e4Smiod 
24783d8817e4Smiod 			  case BFD_RELOC_SPARC_LOX10:
24793d8817e4Smiod 			    val = (val & 0x3ff) | 0x1c00;
24803d8817e4Smiod 			    break;
24813d8817e4Smiod 			  }
24823d8817e4Smiod 			the_insn.exp = the_insn.exp2;
24833d8817e4Smiod 			the_insn.exp.X_add_number += val;
24843d8817e4Smiod 			the_insn.exp2.X_op = O_illegal;
24853d8817e4Smiod 			the_insn.reloc = old_reloc;
24863d8817e4Smiod 		      }
24873d8817e4Smiod 		    else if (the_insn.exp2.X_op != O_constant)
24883d8817e4Smiod 		      {
24893d8817e4Smiod 			as_bad (_("Illegal operands: Can't add non-constant expression to %%%s()"), op_arg);
24903d8817e4Smiod 			return special_case;
24913d8817e4Smiod 		      }
24923d8817e4Smiod 		    else
24933d8817e4Smiod 		      {
24943d8817e4Smiod 			if (old_reloc != BFD_RELOC_SPARC13
24953d8817e4Smiod 			    || the_insn.reloc != BFD_RELOC_LO10
24963d8817e4Smiod 			    || sparc_arch_size != 64
24973d8817e4Smiod 			    || sparc_pic_code)
24983d8817e4Smiod 			  {
24993d8817e4Smiod 			    as_bad (_("Illegal operands: Can't do arithmetics involving %%%s() of a relocatable symbol"), op_arg);
25003d8817e4Smiod 			    return special_case;
25013d8817e4Smiod 			  }
25023d8817e4Smiod 			the_insn.reloc = BFD_RELOC_SPARC_OLO10;
25033d8817e4Smiod 		      }
25043d8817e4Smiod 		  }
25053d8817e4Smiod 	      }
25063d8817e4Smiod 	      /* Check for constants that don't require emitting a reloc.  */
25073d8817e4Smiod 	      if (the_insn.exp.X_op == O_constant
25083d8817e4Smiod 		  && the_insn.exp.X_add_symbol == 0
25093d8817e4Smiod 		  && the_insn.exp.X_op_symbol == 0)
25103d8817e4Smiod 		{
25113d8817e4Smiod 		  /* For pc-relative call instructions, we reject
25123d8817e4Smiod 		     constants to get better code.  */
25133d8817e4Smiod 		  if (the_insn.pcrel
25143d8817e4Smiod 		      && the_insn.reloc == BFD_RELOC_32_PCREL_S2
25153d8817e4Smiod 		      && in_signed_range (the_insn.exp.X_add_number, 0x3fff))
25163d8817e4Smiod 		    {
25173d8817e4Smiod 		      error_message = _(": PC-relative operand can't be a constant");
25183d8817e4Smiod 		      goto error;
25193d8817e4Smiod 		    }
25203d8817e4Smiod 
25213d8817e4Smiod 		  if (the_insn.reloc >= BFD_RELOC_SPARC_TLS_GD_HI22
25223d8817e4Smiod 		      && the_insn.reloc <= BFD_RELOC_SPARC_TLS_TPOFF64)
25233d8817e4Smiod 		    {
25243d8817e4Smiod 		      error_message = _(": TLS operand can't be a constant");
25253d8817e4Smiod 		      goto error;
25263d8817e4Smiod 		    }
25273d8817e4Smiod 
25283d8817e4Smiod 		  /* Constants that won't fit are checked in md_apply_fix
25293d8817e4Smiod 		     and bfd_install_relocation.
25303d8817e4Smiod 		     ??? It would be preferable to install the constants
25313d8817e4Smiod 		     into the insn here and save having to create a fixS
25323d8817e4Smiod 		     for each one.  There already exists code to handle
25333d8817e4Smiod 		     all the various cases (e.g. in md_apply_fix and
25343d8817e4Smiod 		     bfd_install_relocation) so duplicating all that code
25353d8817e4Smiod 		     here isn't right.  */
25363d8817e4Smiod 		}
25373d8817e4Smiod 
25383d8817e4Smiod 	      continue;
25393d8817e4Smiod 
25403d8817e4Smiod 	    case 'a':
25413d8817e4Smiod 	      if (*s++ == 'a')
25423d8817e4Smiod 		{
25433d8817e4Smiod 		  opcode |= ANNUL;
25443d8817e4Smiod 		  continue;
25453d8817e4Smiod 		}
25463d8817e4Smiod 	      break;
25473d8817e4Smiod 
25483d8817e4Smiod 	    case 'A':
25493d8817e4Smiod 	      {
25503d8817e4Smiod 		int asi = 0;
25513d8817e4Smiod 
25523d8817e4Smiod 		/* Parse an asi.  */
25533d8817e4Smiod 		if (*s == '#')
25543d8817e4Smiod 		  {
25553d8817e4Smiod 		    if (! parse_keyword_arg (sparc_encode_asi, &s, &asi))
25563d8817e4Smiod 		      {
25573d8817e4Smiod 			error_message = _(": invalid ASI name");
25583d8817e4Smiod 			goto error;
25593d8817e4Smiod 		      }
25603d8817e4Smiod 		  }
25613d8817e4Smiod 		else
25623d8817e4Smiod 		  {
25633d8817e4Smiod 		    if (! parse_const_expr_arg (&s, &asi))
25643d8817e4Smiod 		      {
25653d8817e4Smiod 			error_message = _(": invalid ASI expression");
25663d8817e4Smiod 			goto error;
25673d8817e4Smiod 		      }
25683d8817e4Smiod 		    if (asi < 0 || asi > 255)
25693d8817e4Smiod 		      {
25703d8817e4Smiod 			error_message = _(": invalid ASI number");
25713d8817e4Smiod 			goto error;
25723d8817e4Smiod 		      }
25733d8817e4Smiod 		  }
25743d8817e4Smiod 		opcode |= ASI (asi);
25753d8817e4Smiod 		continue;
25763d8817e4Smiod 	      }			/* Alternate space.  */
25773d8817e4Smiod 
25783d8817e4Smiod 	    case 'p':
25793d8817e4Smiod 	      if (strncmp (s, "%psr", 4) == 0)
25803d8817e4Smiod 		{
25813d8817e4Smiod 		  s += 4;
25823d8817e4Smiod 		  continue;
25833d8817e4Smiod 		}
25843d8817e4Smiod 	      break;
25853d8817e4Smiod 
25863d8817e4Smiod 	    case 'q':		/* Floating point queue.  */
25873d8817e4Smiod 	      if (strncmp (s, "%fq", 3) == 0)
25883d8817e4Smiod 		{
25893d8817e4Smiod 		  s += 3;
25903d8817e4Smiod 		  continue;
25913d8817e4Smiod 		}
25923d8817e4Smiod 	      break;
25933d8817e4Smiod 
25943d8817e4Smiod 	    case 'Q':		/* Coprocessor queue.  */
25953d8817e4Smiod 	      if (strncmp (s, "%cq", 3) == 0)
25963d8817e4Smiod 		{
25973d8817e4Smiod 		  s += 3;
25983d8817e4Smiod 		  continue;
25993d8817e4Smiod 		}
26003d8817e4Smiod 	      break;
26013d8817e4Smiod 
26023d8817e4Smiod 	    case 'S':
26033d8817e4Smiod 	      if (strcmp (str, "set") == 0
26043d8817e4Smiod 		  || strcmp (str, "setuw") == 0)
26053d8817e4Smiod 		{
26063d8817e4Smiod 		  special_case = SPECIAL_CASE_SET;
26073d8817e4Smiod 		  continue;
26083d8817e4Smiod 		}
26093d8817e4Smiod 	      else if (strcmp (str, "setsw") == 0)
26103d8817e4Smiod 		{
26113d8817e4Smiod 		  special_case = SPECIAL_CASE_SETSW;
26123d8817e4Smiod 		  continue;
26133d8817e4Smiod 		}
26143d8817e4Smiod 	      else if (strcmp (str, "setx") == 0)
26153d8817e4Smiod 		{
26163d8817e4Smiod 		  special_case = SPECIAL_CASE_SETX;
26173d8817e4Smiod 		  continue;
26183d8817e4Smiod 		}
26193d8817e4Smiod 	      else if (strncmp (str, "fdiv", 4) == 0)
26203d8817e4Smiod 		{
26213d8817e4Smiod 		  special_case = SPECIAL_CASE_FDIV;
26223d8817e4Smiod 		  continue;
26233d8817e4Smiod 		}
26243d8817e4Smiod 	      break;
26253d8817e4Smiod 
26263d8817e4Smiod 	    case 'o':
26273d8817e4Smiod 	      if (strncmp (s, "%asi", 4) != 0)
26283d8817e4Smiod 		break;
26293d8817e4Smiod 	      s += 4;
26303d8817e4Smiod 	      continue;
26313d8817e4Smiod 
26323d8817e4Smiod 	    case 's':
26333d8817e4Smiod 	      if (strncmp (s, "%fprs", 5) != 0)
26343d8817e4Smiod 		break;
26353d8817e4Smiod 	      s += 5;
26363d8817e4Smiod 	      continue;
26373d8817e4Smiod 
26383d8817e4Smiod 	    case 'E':
26393d8817e4Smiod 	      if (strncmp (s, "%ccr", 4) != 0)
26403d8817e4Smiod 		break;
26413d8817e4Smiod 	      s += 4;
26423d8817e4Smiod 	      continue;
26433d8817e4Smiod 
26443d8817e4Smiod 	    case 't':
26453d8817e4Smiod 	      if (strncmp (s, "%tbr", 4) != 0)
26463d8817e4Smiod 		break;
26473d8817e4Smiod 	      s += 4;
26483d8817e4Smiod 	      continue;
26493d8817e4Smiod 
26503d8817e4Smiod 	    case 'w':
26513d8817e4Smiod 	      if (strncmp (s, "%wim", 4) != 0)
26523d8817e4Smiod 		break;
26533d8817e4Smiod 	      s += 4;
26543d8817e4Smiod 	      continue;
26553d8817e4Smiod 
26563d8817e4Smiod 	    case 'x':
26573d8817e4Smiod 	      {
26583d8817e4Smiod 		char *push = input_line_pointer;
26593d8817e4Smiod 		expressionS e;
26603d8817e4Smiod 
26613d8817e4Smiod 		input_line_pointer = s;
26623d8817e4Smiod 		expression (&e);
26633d8817e4Smiod 		if (e.X_op == O_constant)
26643d8817e4Smiod 		  {
26653d8817e4Smiod 		    int n = e.X_add_number;
26663d8817e4Smiod 		    if (n != e.X_add_number || (n & ~0x1ff) != 0)
26673d8817e4Smiod 		      as_bad (_("OPF immediate operand out of range (0-0x1ff)"));
26683d8817e4Smiod 		    else
26693d8817e4Smiod 		      opcode |= e.X_add_number << 5;
26703d8817e4Smiod 		  }
26713d8817e4Smiod 		else
26723d8817e4Smiod 		  as_bad (_("non-immediate OPF operand, ignored"));
26733d8817e4Smiod 		s = input_line_pointer;
26743d8817e4Smiod 		input_line_pointer = push;
26753d8817e4Smiod 		continue;
26763d8817e4Smiod 	      }
26773d8817e4Smiod 
26783d8817e4Smiod 	    case 'y':
26793d8817e4Smiod 	      if (strncmp (s, "%y", 2) != 0)
26803d8817e4Smiod 		break;
26813d8817e4Smiod 	      s += 2;
26823d8817e4Smiod 	      continue;
26833d8817e4Smiod 
26843d8817e4Smiod 	    case 'u':
26853d8817e4Smiod 	    case 'U':
26863d8817e4Smiod 	      {
26873d8817e4Smiod 		/* Parse a sparclet cpreg.  */
26883d8817e4Smiod 		int cpreg;
26893d8817e4Smiod 		if (! parse_keyword_arg (sparc_encode_sparclet_cpreg, &s, &cpreg))
26903d8817e4Smiod 		  {
26913d8817e4Smiod 		    error_message = _(": invalid cpreg name");
26923d8817e4Smiod 		    goto error;
26933d8817e4Smiod 		  }
26943d8817e4Smiod 		opcode |= (*args == 'U' ? RS1 (cpreg) : RD (cpreg));
26953d8817e4Smiod 		continue;
26963d8817e4Smiod 	      }
26973d8817e4Smiod 
26983d8817e4Smiod 	    default:
26993d8817e4Smiod 	      as_fatal (_("failed sanity check."));
27003d8817e4Smiod 	    }			/* switch on arg code.  */
27013d8817e4Smiod 
27023d8817e4Smiod 	  /* Break out of for() loop.  */
27033d8817e4Smiod 	  break;
27043d8817e4Smiod 	}			/* For each arg that we expect.  */
27053d8817e4Smiod 
27063d8817e4Smiod     error:
27073d8817e4Smiod       if (match == 0)
27083d8817e4Smiod 	{
27093d8817e4Smiod 	  /* Args don't match.  */
27103d8817e4Smiod 	  if (&insn[1] - sparc_opcodes < sparc_num_opcodes
27113d8817e4Smiod 	      && (insn->name == insn[1].name
27123d8817e4Smiod 		  || !strcmp (insn->name, insn[1].name)))
27133d8817e4Smiod 	    {
27143d8817e4Smiod 	      ++insn;
27153d8817e4Smiod 	      s = argsStart;
27163d8817e4Smiod 	      continue;
27173d8817e4Smiod 	    }
27183d8817e4Smiod 	  else
27193d8817e4Smiod 	    {
27203d8817e4Smiod 	      as_bad (_("Illegal operands%s"), error_message);
27213d8817e4Smiod 	      return special_case;
27223d8817e4Smiod 	    }
27233d8817e4Smiod 	}
27243d8817e4Smiod       else
27253d8817e4Smiod 	{
27263d8817e4Smiod 	  /* We have a match.  Now see if the architecture is OK.  */
27273d8817e4Smiod 	  int needed_arch_mask = insn->architecture;
27283d8817e4Smiod 
27293d8817e4Smiod 	  if (v9_arg_p)
27303d8817e4Smiod 	    {
27313d8817e4Smiod 	      needed_arch_mask &=
27323d8817e4Smiod 		~(SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9) - 1);
27333d8817e4Smiod 	      if (! needed_arch_mask)
27343d8817e4Smiod 		needed_arch_mask =
27353d8817e4Smiod 		  SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9);
27363d8817e4Smiod 	    }
27373d8817e4Smiod 
27383d8817e4Smiod 	  if (needed_arch_mask
27393d8817e4Smiod 	      & SPARC_OPCODE_SUPPORTED (current_architecture))
27403d8817e4Smiod 	    /* OK.  */
27413d8817e4Smiod 	    ;
27423d8817e4Smiod 	  /* Can we bump up the architecture?  */
27433d8817e4Smiod 	  else if (needed_arch_mask
27443d8817e4Smiod 		   & SPARC_OPCODE_SUPPORTED (max_architecture))
27453d8817e4Smiod 	    {
27463d8817e4Smiod 	      enum sparc_opcode_arch_val needed_architecture =
27473d8817e4Smiod 		sparc_ffs (SPARC_OPCODE_SUPPORTED (max_architecture)
27483d8817e4Smiod 			   & needed_arch_mask);
27493d8817e4Smiod 
27503d8817e4Smiod 	      assert (needed_architecture <= SPARC_OPCODE_ARCH_MAX);
27513d8817e4Smiod 	      if (warn_on_bump
27523d8817e4Smiod 		  && needed_architecture > warn_after_architecture)
27533d8817e4Smiod 		{
27543d8817e4Smiod 		  as_warn (_("architecture bumped from \"%s\" to \"%s\" on \"%s\""),
27553d8817e4Smiod 			   sparc_opcode_archs[current_architecture].name,
27563d8817e4Smiod 			   sparc_opcode_archs[needed_architecture].name,
27573d8817e4Smiod 			   str);
27583d8817e4Smiod 		  warn_after_architecture = needed_architecture;
27593d8817e4Smiod 		}
27603d8817e4Smiod 	      current_architecture = needed_architecture;
27613d8817e4Smiod 	    }
27623d8817e4Smiod 	  /* Conflict.  */
27633d8817e4Smiod 	  /* ??? This seems to be a bit fragile.  What if the next entry in
27643d8817e4Smiod 	     the opcode table is the one we want and it is supported?
27653d8817e4Smiod 	     It is possible to arrange the table today so that this can't
27663d8817e4Smiod 	     happen but what about tomorrow?  */
27673d8817e4Smiod 	  else
27683d8817e4Smiod 	    {
27693d8817e4Smiod 	      int arch, printed_one_p = 0;
27703d8817e4Smiod 	      char *p;
27713d8817e4Smiod 	      char required_archs[SPARC_OPCODE_ARCH_MAX * 16];
27723d8817e4Smiod 
27733d8817e4Smiod 	      /* Create a list of the architectures that support the insn.  */
27743d8817e4Smiod 	      needed_arch_mask &= ~SPARC_OPCODE_SUPPORTED (max_architecture);
27753d8817e4Smiod 	      p = required_archs;
27763d8817e4Smiod 	      arch = sparc_ffs (needed_arch_mask);
27773d8817e4Smiod 	      while ((1 << arch) <= needed_arch_mask)
27783d8817e4Smiod 		{
27793d8817e4Smiod 		  if ((1 << arch) & needed_arch_mask)
27803d8817e4Smiod 		    {
27813d8817e4Smiod 		      if (printed_one_p)
27823d8817e4Smiod 			*p++ = '|';
27833d8817e4Smiod 		      strcpy (p, sparc_opcode_archs[arch].name);
27843d8817e4Smiod 		      p += strlen (p);
27853d8817e4Smiod 		      printed_one_p = 1;
27863d8817e4Smiod 		    }
27873d8817e4Smiod 		  ++arch;
27883d8817e4Smiod 		}
27893d8817e4Smiod 
27903d8817e4Smiod 	      as_bad (_("Architecture mismatch on \"%s\"."), str);
27913d8817e4Smiod 	      as_tsktsk (_(" (Requires %s; requested architecture is %s.)"),
27923d8817e4Smiod 			 required_archs,
27933d8817e4Smiod 			 sparc_opcode_archs[max_architecture].name);
27943d8817e4Smiod 	      return special_case;
27953d8817e4Smiod 	    }
27963d8817e4Smiod 	} /* If no match.  */
27973d8817e4Smiod 
27983d8817e4Smiod       break;
27993d8817e4Smiod     } /* Forever looking for a match.  */
28003d8817e4Smiod 
28013d8817e4Smiod   the_insn.opcode = opcode;
28023d8817e4Smiod   return special_case;
28033d8817e4Smiod }
28043d8817e4Smiod 
28053d8817e4Smiod /* Parse an argument that can be expressed as a keyword.
28063d8817e4Smiod    (eg: #StoreStore or %ccfr).
28073d8817e4Smiod    The result is a boolean indicating success.
28083d8817e4Smiod    If successful, INPUT_POINTER is updated.  */
28093d8817e4Smiod 
28103d8817e4Smiod static int
28113d8817e4Smiod parse_keyword_arg (lookup_fn, input_pointerP, valueP)
28123d8817e4Smiod      int (*lookup_fn) PARAMS ((const char *));
28133d8817e4Smiod      char **input_pointerP;
28143d8817e4Smiod      int *valueP;
28153d8817e4Smiod {
28163d8817e4Smiod   int value;
28173d8817e4Smiod   char c, *p, *q;
28183d8817e4Smiod 
28193d8817e4Smiod   p = *input_pointerP;
28203d8817e4Smiod   for (q = p + (*p == '#' || *p == '%');
28213d8817e4Smiod        ISALNUM (*q) || *q == '_';
28223d8817e4Smiod        ++q)
28233d8817e4Smiod     continue;
28243d8817e4Smiod   c = *q;
28253d8817e4Smiod   *q = 0;
28263d8817e4Smiod   value = (*lookup_fn) (p);
28273d8817e4Smiod   *q = c;
28283d8817e4Smiod   if (value == -1)
28293d8817e4Smiod     return 0;
28303d8817e4Smiod   *valueP = value;
28313d8817e4Smiod   *input_pointerP = q;
28323d8817e4Smiod   return 1;
28333d8817e4Smiod }
28343d8817e4Smiod 
28353d8817e4Smiod /* Parse an argument that is a constant expression.
28363d8817e4Smiod    The result is a boolean indicating success.  */
28373d8817e4Smiod 
28383d8817e4Smiod static int
parse_const_expr_arg(input_pointerP,valueP)28393d8817e4Smiod parse_const_expr_arg (input_pointerP, valueP)
28403d8817e4Smiod      char **input_pointerP;
28413d8817e4Smiod      int *valueP;
28423d8817e4Smiod {
28433d8817e4Smiod   char *save = input_line_pointer;
28443d8817e4Smiod   expressionS exp;
28453d8817e4Smiod 
28463d8817e4Smiod   input_line_pointer = *input_pointerP;
28473d8817e4Smiod   /* The next expression may be something other than a constant
28483d8817e4Smiod      (say if we're not processing the right variant of the insn).
28493d8817e4Smiod      Don't call expression unless we're sure it will succeed as it will
28503d8817e4Smiod      signal an error (which we want to defer until later).  */
28513d8817e4Smiod   /* FIXME: It might be better to define md_operand and have it recognize
28523d8817e4Smiod      things like %asi, etc. but continuing that route through to the end
28533d8817e4Smiod      is a lot of work.  */
28543d8817e4Smiod   if (*input_line_pointer == '%')
28553d8817e4Smiod     {
28563d8817e4Smiod       input_line_pointer = save;
28573d8817e4Smiod       return 0;
28583d8817e4Smiod     }
28593d8817e4Smiod   expression (&exp);
28603d8817e4Smiod   *input_pointerP = input_line_pointer;
28613d8817e4Smiod   input_line_pointer = save;
28623d8817e4Smiod   if (exp.X_op != O_constant)
28633d8817e4Smiod     return 0;
28643d8817e4Smiod   *valueP = exp.X_add_number;
28653d8817e4Smiod   return 1;
28663d8817e4Smiod }
28673d8817e4Smiod 
28683d8817e4Smiod /* Subroutine of sparc_ip to parse an expression.  */
28693d8817e4Smiod 
28703d8817e4Smiod static int
get_expression(str)28713d8817e4Smiod get_expression (str)
28723d8817e4Smiod      char *str;
28733d8817e4Smiod {
28743d8817e4Smiod   char *save_in;
28753d8817e4Smiod   segT seg;
28763d8817e4Smiod 
28773d8817e4Smiod   save_in = input_line_pointer;
28783d8817e4Smiod   input_line_pointer = str;
28793d8817e4Smiod   seg = expression (&the_insn.exp);
28803d8817e4Smiod   if (seg != absolute_section
28813d8817e4Smiod       && seg != text_section
28823d8817e4Smiod       && seg != data_section
28833d8817e4Smiod       && seg != bss_section
28843d8817e4Smiod       && seg != undefined_section)
28853d8817e4Smiod     {
28863d8817e4Smiod       the_insn.error = _("bad segment");
28873d8817e4Smiod       expr_end = input_line_pointer;
28883d8817e4Smiod       input_line_pointer = save_in;
28893d8817e4Smiod       return 1;
28903d8817e4Smiod     }
28913d8817e4Smiod   expr_end = input_line_pointer;
28923d8817e4Smiod   input_line_pointer = save_in;
28933d8817e4Smiod   return 0;
28943d8817e4Smiod }
28953d8817e4Smiod 
28963d8817e4Smiod /* Subroutine of md_assemble to output one insn.  */
28973d8817e4Smiod 
28983d8817e4Smiod static void
output_insn(insn,the_insn)28993d8817e4Smiod output_insn (insn, the_insn)
29003d8817e4Smiod      const struct sparc_opcode *insn;
29013d8817e4Smiod      struct sparc_it *the_insn;
29023d8817e4Smiod {
29033d8817e4Smiod   char *toP = frag_more (4);
29043d8817e4Smiod 
29053d8817e4Smiod   /* Put out the opcode.  */
29063d8817e4Smiod   if (INSN_BIG_ENDIAN)
29073d8817e4Smiod     number_to_chars_bigendian (toP, (valueT) the_insn->opcode, 4);
29083d8817e4Smiod   else
29093d8817e4Smiod     number_to_chars_littleendian (toP, (valueT) the_insn->opcode, 4);
29103d8817e4Smiod 
29113d8817e4Smiod   /* Put out the symbol-dependent stuff.  */
29123d8817e4Smiod   if (the_insn->reloc != BFD_RELOC_NONE)
29133d8817e4Smiod     {
29143d8817e4Smiod       fixS *fixP =  fix_new_exp (frag_now,	/* Which frag.  */
29153d8817e4Smiod 				 (toP - frag_now->fr_literal),	/* Where.  */
29163d8817e4Smiod 				 4,		/* Size.  */
29173d8817e4Smiod 				 &the_insn->exp,
29183d8817e4Smiod 				 the_insn->pcrel,
29193d8817e4Smiod 				 the_insn->reloc);
29203d8817e4Smiod       /* Turn off overflow checking in fixup_segment.  We'll do our
29213d8817e4Smiod 	 own overflow checking in md_apply_fix.  This is necessary because
29223d8817e4Smiod 	 the insn size is 4 and fixup_segment will signal an overflow for
29233d8817e4Smiod 	 large 8 byte quantities.  */
29243d8817e4Smiod       fixP->fx_no_overflow = 1;
29253d8817e4Smiod       if (the_insn->reloc == BFD_RELOC_SPARC_OLO10)
29263d8817e4Smiod 	fixP->tc_fix_data = the_insn->exp2.X_add_number;
29273d8817e4Smiod     }
29283d8817e4Smiod 
29293d8817e4Smiod   last_insn = insn;
29303d8817e4Smiod   last_opcode = the_insn->opcode;
29313d8817e4Smiod 
29323d8817e4Smiod #ifdef OBJ_ELF
29333d8817e4Smiod   dwarf2_emit_insn (4);
29343d8817e4Smiod #endif
29353d8817e4Smiod }
29363d8817e4Smiod 
29373d8817e4Smiod /* This is identical to the md_atof in m68k.c.  I think this is right,
29383d8817e4Smiod    but I'm not sure.
29393d8817e4Smiod 
29403d8817e4Smiod    Turn a string in input_line_pointer into a floating point constant
29413d8817e4Smiod    of type TYPE, and store the appropriate bytes in *LITP.  The number
29423d8817e4Smiod    of LITTLENUMS emitted is stored in *SIZEP.  An error message is
29433d8817e4Smiod    returned, or NULL on OK.  */
29443d8817e4Smiod 
29453d8817e4Smiod /* Equal to MAX_PRECISION in atof-ieee.c.  */
29463d8817e4Smiod #define MAX_LITTLENUMS 6
29473d8817e4Smiod 
29483d8817e4Smiod char *
md_atof(type,litP,sizeP)29493d8817e4Smiod md_atof (type, litP, sizeP)
29503d8817e4Smiod      char type;
29513d8817e4Smiod      char *litP;
29523d8817e4Smiod      int *sizeP;
29533d8817e4Smiod {
29543d8817e4Smiod   int i, prec;
29553d8817e4Smiod   LITTLENUM_TYPE words[MAX_LITTLENUMS];
29563d8817e4Smiod   char *t;
29573d8817e4Smiod 
29583d8817e4Smiod   switch (type)
29593d8817e4Smiod     {
29603d8817e4Smiod     case 'f':
29613d8817e4Smiod     case 'F':
29623d8817e4Smiod     case 's':
29633d8817e4Smiod     case 'S':
29643d8817e4Smiod       prec = 2;
29653d8817e4Smiod       break;
29663d8817e4Smiod 
29673d8817e4Smiod     case 'd':
29683d8817e4Smiod     case 'D':
29693d8817e4Smiod     case 'r':
29703d8817e4Smiod     case 'R':
29713d8817e4Smiod       prec = 4;
29723d8817e4Smiod       break;
29733d8817e4Smiod 
29743d8817e4Smiod     case 'x':
29753d8817e4Smiod     case 'X':
29763d8817e4Smiod       prec = 6;
29773d8817e4Smiod       break;
29783d8817e4Smiod 
29793d8817e4Smiod     case 'p':
29803d8817e4Smiod     case 'P':
29813d8817e4Smiod       prec = 6;
29823d8817e4Smiod       break;
29833d8817e4Smiod 
29843d8817e4Smiod     default:
29853d8817e4Smiod       *sizeP = 0;
29863d8817e4Smiod       return _("Bad call to MD_ATOF()");
29873d8817e4Smiod     }
29883d8817e4Smiod 
29893d8817e4Smiod   t = atof_ieee (input_line_pointer, type, words);
29903d8817e4Smiod   if (t)
29913d8817e4Smiod     input_line_pointer = t;
29923d8817e4Smiod   *sizeP = prec * sizeof (LITTLENUM_TYPE);
29933d8817e4Smiod 
29943d8817e4Smiod   if (target_big_endian)
29953d8817e4Smiod     {
29963d8817e4Smiod       for (i = 0; i < prec; i++)
29973d8817e4Smiod 	{
29983d8817e4Smiod 	  md_number_to_chars (litP, (valueT) words[i],
29993d8817e4Smiod 			      sizeof (LITTLENUM_TYPE));
30003d8817e4Smiod 	  litP += sizeof (LITTLENUM_TYPE);
30013d8817e4Smiod 	}
30023d8817e4Smiod     }
30033d8817e4Smiod   else
30043d8817e4Smiod     {
30053d8817e4Smiod       for (i = prec - 1; i >= 0; i--)
30063d8817e4Smiod 	{
30073d8817e4Smiod 	  md_number_to_chars (litP, (valueT) words[i],
30083d8817e4Smiod 			      sizeof (LITTLENUM_TYPE));
30093d8817e4Smiod 	  litP += sizeof (LITTLENUM_TYPE);
30103d8817e4Smiod 	}
30113d8817e4Smiod     }
30123d8817e4Smiod 
30133d8817e4Smiod   return 0;
30143d8817e4Smiod }
30153d8817e4Smiod 
30163d8817e4Smiod /* Write a value out to the object file, using the appropriate
30173d8817e4Smiod    endianness.  */
30183d8817e4Smiod 
30193d8817e4Smiod void
md_number_to_chars(buf,val,n)30203d8817e4Smiod md_number_to_chars (buf, val, n)
30213d8817e4Smiod      char *buf;
30223d8817e4Smiod      valueT val;
30233d8817e4Smiod      int n;
30243d8817e4Smiod {
30253d8817e4Smiod   if (target_big_endian)
30263d8817e4Smiod     number_to_chars_bigendian (buf, val, n);
30273d8817e4Smiod   else if (target_little_endian_data
30283d8817e4Smiod 	   && ((n == 4 || n == 2) && ~now_seg->flags & SEC_ALLOC))
30293d8817e4Smiod     /* Output debug words, which are not in allocated sections, as big
30303d8817e4Smiod        endian.  */
30313d8817e4Smiod     number_to_chars_bigendian (buf, val, n);
30323d8817e4Smiod   else if (target_little_endian_data || ! target_big_endian)
30333d8817e4Smiod     number_to_chars_littleendian (buf, val, n);
30343d8817e4Smiod }
30353d8817e4Smiod 
30363d8817e4Smiod /* Apply a fixS to the frags, now that we know the value it ought to
30373d8817e4Smiod    hold.  */
30383d8817e4Smiod 
30393d8817e4Smiod void
md_apply_fix(fixP,valP,segment)30403d8817e4Smiod md_apply_fix (fixP, valP, segment)
30413d8817e4Smiod      fixS *fixP;
30423d8817e4Smiod      valueT *valP;
30433d8817e4Smiod      segT segment ATTRIBUTE_UNUSED;
30443d8817e4Smiod {
30453d8817e4Smiod   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
30463d8817e4Smiod   offsetT val = * (offsetT *) valP;
30473d8817e4Smiod   long insn;
30483d8817e4Smiod 
30493d8817e4Smiod   assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
30503d8817e4Smiod 
30513d8817e4Smiod   fixP->fx_addnumber = val;	/* Remember value for emit_reloc.  */
30523d8817e4Smiod 
30533d8817e4Smiod #ifdef OBJ_ELF
30543d8817e4Smiod   /* SPARC ELF relocations don't use an addend in the data field.  */
30553d8817e4Smiod   if (fixP->fx_addsy != NULL)
30563d8817e4Smiod     {
30573d8817e4Smiod       switch (fixP->fx_r_type)
30583d8817e4Smiod 	{
30593d8817e4Smiod 	case BFD_RELOC_SPARC_TLS_GD_HI22:
30603d8817e4Smiod 	case BFD_RELOC_SPARC_TLS_GD_LO10:
30613d8817e4Smiod 	case BFD_RELOC_SPARC_TLS_GD_ADD:
30623d8817e4Smiod 	case BFD_RELOC_SPARC_TLS_GD_CALL:
30633d8817e4Smiod 	case BFD_RELOC_SPARC_TLS_LDM_HI22:
30643d8817e4Smiod 	case BFD_RELOC_SPARC_TLS_LDM_LO10:
30653d8817e4Smiod 	case BFD_RELOC_SPARC_TLS_LDM_ADD:
30663d8817e4Smiod 	case BFD_RELOC_SPARC_TLS_LDM_CALL:
30673d8817e4Smiod 	case BFD_RELOC_SPARC_TLS_LDO_HIX22:
30683d8817e4Smiod 	case BFD_RELOC_SPARC_TLS_LDO_LOX10:
30693d8817e4Smiod 	case BFD_RELOC_SPARC_TLS_LDO_ADD:
30703d8817e4Smiod 	case BFD_RELOC_SPARC_TLS_IE_HI22:
30713d8817e4Smiod 	case BFD_RELOC_SPARC_TLS_IE_LO10:
30723d8817e4Smiod 	case BFD_RELOC_SPARC_TLS_IE_LD:
30733d8817e4Smiod 	case BFD_RELOC_SPARC_TLS_IE_LDX:
30743d8817e4Smiod 	case BFD_RELOC_SPARC_TLS_IE_ADD:
30753d8817e4Smiod 	case BFD_RELOC_SPARC_TLS_LE_HIX22:
30763d8817e4Smiod 	case BFD_RELOC_SPARC_TLS_LE_LOX10:
30773d8817e4Smiod 	case BFD_RELOC_SPARC_TLS_DTPMOD32:
30783d8817e4Smiod 	case BFD_RELOC_SPARC_TLS_DTPMOD64:
30793d8817e4Smiod 	case BFD_RELOC_SPARC_TLS_DTPOFF32:
30803d8817e4Smiod 	case BFD_RELOC_SPARC_TLS_DTPOFF64:
30813d8817e4Smiod 	case BFD_RELOC_SPARC_TLS_TPOFF32:
30823d8817e4Smiod 	case BFD_RELOC_SPARC_TLS_TPOFF64:
30833d8817e4Smiod 	  S_SET_THREAD_LOCAL (fixP->fx_addsy);
30843d8817e4Smiod 
30853d8817e4Smiod 	default:
30863d8817e4Smiod 	  break;
30873d8817e4Smiod 	}
30883d8817e4Smiod 
30893d8817e4Smiod       return;
30903d8817e4Smiod     }
30913d8817e4Smiod #endif
30923d8817e4Smiod 
30933d8817e4Smiod   /* This is a hack.  There should be a better way to
30943d8817e4Smiod      handle this.  Probably in terms of howto fields, once
30953d8817e4Smiod      we can look at these fixups in terms of howtos.  */
30963d8817e4Smiod   if (fixP->fx_r_type == BFD_RELOC_32_PCREL_S2 && fixP->fx_addsy)
30973d8817e4Smiod     val += fixP->fx_where + fixP->fx_frag->fr_address;
30983d8817e4Smiod 
30993d8817e4Smiod #ifdef OBJ_AOUT
31003d8817e4Smiod   /* FIXME: More ridiculous gas reloc hacking.  If we are going to
31013d8817e4Smiod      generate a reloc, then we just want to let the reloc addend set
31023d8817e4Smiod      the value.  We do not want to also stuff the addend into the
31033d8817e4Smiod      object file.  Including the addend in the object file works when
31043d8817e4Smiod      doing a static link, because the linker will ignore the object
31053d8817e4Smiod      file contents.  However, the dynamic linker does not ignore the
31063d8817e4Smiod      object file contents.  */
31073d8817e4Smiod   if (fixP->fx_addsy != NULL
31083d8817e4Smiod       && fixP->fx_r_type != BFD_RELOC_32_PCREL_S2)
31093d8817e4Smiod     val = 0;
31103d8817e4Smiod 
31113d8817e4Smiod   /* When generating PIC code, we do not want an addend for a reloc
31123d8817e4Smiod      against a local symbol.  We adjust fx_addnumber to cancel out the
31133d8817e4Smiod      value already included in val, and to also cancel out the
31143d8817e4Smiod      adjustment which bfd_install_relocation will create.  */
31153d8817e4Smiod   if (sparc_pic_code
31163d8817e4Smiod       && fixP->fx_r_type != BFD_RELOC_32_PCREL_S2
31173d8817e4Smiod       && fixP->fx_addsy != NULL
31183d8817e4Smiod       && ! S_IS_COMMON (fixP->fx_addsy)
31193d8817e4Smiod       && symbol_section_p (fixP->fx_addsy))
31203d8817e4Smiod     fixP->fx_addnumber -= 2 * S_GET_VALUE (fixP->fx_addsy);
31213d8817e4Smiod 
31223d8817e4Smiod   /* When generating PIC code, we need to fiddle to get
31233d8817e4Smiod      bfd_install_relocation to do the right thing for a PC relative
31243d8817e4Smiod      reloc against a local symbol which we are going to keep.  */
31253d8817e4Smiod   if (sparc_pic_code
31263d8817e4Smiod       && fixP->fx_r_type == BFD_RELOC_32_PCREL_S2
31273d8817e4Smiod       && fixP->fx_addsy != NULL
31283d8817e4Smiod       && (S_IS_EXTERNAL (fixP->fx_addsy)
31293d8817e4Smiod 	  || S_IS_WEAK (fixP->fx_addsy))
31303d8817e4Smiod       && S_IS_DEFINED (fixP->fx_addsy)
31313d8817e4Smiod       && ! S_IS_COMMON (fixP->fx_addsy))
31323d8817e4Smiod     {
31333d8817e4Smiod       val = 0;
31343d8817e4Smiod       fixP->fx_addnumber -= 2 * S_GET_VALUE (fixP->fx_addsy);
31353d8817e4Smiod     }
31363d8817e4Smiod #endif
31373d8817e4Smiod 
31383d8817e4Smiod   /* If this is a data relocation, just output VAL.  */
31393d8817e4Smiod 
31403d8817e4Smiod   if (fixP->fx_r_type == BFD_RELOC_16
31413d8817e4Smiod       || fixP->fx_r_type == BFD_RELOC_SPARC_UA16)
31423d8817e4Smiod     {
31433d8817e4Smiod       md_number_to_chars (buf, val, 2);
31443d8817e4Smiod     }
31453d8817e4Smiod   else if (fixP->fx_r_type == BFD_RELOC_32
31463d8817e4Smiod 	   || fixP->fx_r_type == BFD_RELOC_SPARC_UA32
31473d8817e4Smiod 	   || fixP->fx_r_type == BFD_RELOC_SPARC_REV32)
31483d8817e4Smiod     {
31493d8817e4Smiod       md_number_to_chars (buf, val, 4);
31503d8817e4Smiod     }
31513d8817e4Smiod   else if (fixP->fx_r_type == BFD_RELOC_64
31523d8817e4Smiod 	   || fixP->fx_r_type == BFD_RELOC_SPARC_UA64)
31533d8817e4Smiod     {
31543d8817e4Smiod       md_number_to_chars (buf, val, 8);
31553d8817e4Smiod     }
31563d8817e4Smiod   else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
31573d8817e4Smiod            || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
31583d8817e4Smiod     {
31593d8817e4Smiod       fixP->fx_done = 0;
31603d8817e4Smiod       return;
31613d8817e4Smiod     }
31623d8817e4Smiod   else
31633d8817e4Smiod     {
31643d8817e4Smiod       /* It's a relocation against an instruction.  */
31653d8817e4Smiod 
31663d8817e4Smiod       if (INSN_BIG_ENDIAN)
31673d8817e4Smiod 	insn = bfd_getb32 ((unsigned char *) buf);
31683d8817e4Smiod       else
31693d8817e4Smiod 	insn = bfd_getl32 ((unsigned char *) buf);
31703d8817e4Smiod 
31713d8817e4Smiod       switch (fixP->fx_r_type)
31723d8817e4Smiod 	{
31733d8817e4Smiod 	case BFD_RELOC_32_PCREL_S2:
31743d8817e4Smiod 	  val = val >> 2;
31753d8817e4Smiod 	  /* FIXME: This increment-by-one deserves a comment of why it's
31763d8817e4Smiod 	     being done!  */
31773d8817e4Smiod 	  if (! sparc_pic_code
31783d8817e4Smiod 	      || fixP->fx_addsy == NULL
31793d8817e4Smiod 	      || symbol_section_p (fixP->fx_addsy))
31803d8817e4Smiod 	    ++val;
31813d8817e4Smiod 
31823d8817e4Smiod 	  insn |= val & 0x3fffffff;
31833d8817e4Smiod 
31843d8817e4Smiod 	  /* See if we have a delay slot.  */
31853d8817e4Smiod 	  if (sparc_relax && fixP->fx_where + 8 <= fixP->fx_frag->fr_fix)
31863d8817e4Smiod 	    {
31873d8817e4Smiod #define G0		0
31883d8817e4Smiod #define O7		15
31893d8817e4Smiod #define XCC		(2 << 20)
31903d8817e4Smiod #define COND(x)		(((x)&0xf)<<25)
31913d8817e4Smiod #define CONDA		COND(0x8)
31923d8817e4Smiod #define INSN_BPA	(F2(0,1) | CONDA | BPRED | XCC)
31933d8817e4Smiod #define INSN_BA		(F2(0,2) | CONDA)
31943d8817e4Smiod #define INSN_OR		F3(2, 0x2, 0)
31953d8817e4Smiod #define INSN_NOP	F2(0,4)
31963d8817e4Smiod 
31973d8817e4Smiod 	      long delay;
31983d8817e4Smiod 
31993d8817e4Smiod 	      /* If the instruction is a call with either:
32003d8817e4Smiod 		 restore
32013d8817e4Smiod 		 arithmetic instruction with rd == %o7
32023d8817e4Smiod 		 where rs1 != %o7 and rs2 if it is register != %o7
32033d8817e4Smiod 		 then we can optimize if the call destination is near
32043d8817e4Smiod 		 by changing the call into a branch always.  */
32053d8817e4Smiod 	      if (INSN_BIG_ENDIAN)
32063d8817e4Smiod 		delay = bfd_getb32 ((unsigned char *) buf + 4);
32073d8817e4Smiod 	      else
32083d8817e4Smiod 		delay = bfd_getl32 ((unsigned char *) buf + 4);
32093d8817e4Smiod 	      if ((insn & OP (~0)) != OP (1) || (delay & OP (~0)) != OP (2))
32103d8817e4Smiod 		break;
32113d8817e4Smiod 	      if ((delay & OP3 (~0)) != OP3 (0x3d) /* Restore.  */
32123d8817e4Smiod 		  && ((delay & OP3 (0x28)) != 0 /* Arithmetic.  */
32133d8817e4Smiod 		      || ((delay & RD (~0)) != RD (O7))))
32143d8817e4Smiod 		break;
32153d8817e4Smiod 	      if ((delay & RS1 (~0)) == RS1 (O7)
32163d8817e4Smiod 		  || ((delay & F3I (~0)) == 0
32173d8817e4Smiod 		      && (delay & RS2 (~0)) == RS2 (O7)))
32183d8817e4Smiod 		break;
32193d8817e4Smiod 	      /* Ensure the branch will fit into simm22.  */
32203d8817e4Smiod 	      if ((val & 0x3fe00000)
32213d8817e4Smiod 		  && (val & 0x3fe00000) != 0x3fe00000)
32223d8817e4Smiod 		break;
32233d8817e4Smiod 	      /* Check if the arch is v9 and branch will fit
32243d8817e4Smiod 		 into simm19.  */
32253d8817e4Smiod 	      if (((val & 0x3c0000) == 0
32263d8817e4Smiod 		   || (val & 0x3c0000) == 0x3c0000)
32273d8817e4Smiod 		  && (sparc_arch_size == 64
32283d8817e4Smiod 		      || current_architecture >= SPARC_OPCODE_ARCH_V9))
32293d8817e4Smiod 		/* ba,pt %xcc  */
32303d8817e4Smiod 		insn = INSN_BPA | (val & 0x7ffff);
32313d8817e4Smiod 	      else
32323d8817e4Smiod 		/* ba  */
32333d8817e4Smiod 		insn = INSN_BA | (val & 0x3fffff);
32343d8817e4Smiod 	      if (fixP->fx_where >= 4
32353d8817e4Smiod 		  && ((delay & (0xffffffff ^ RS1 (~0)))
32363d8817e4Smiod 		      == (INSN_OR | RD (O7) | RS2 (G0))))
32373d8817e4Smiod 		{
32383d8817e4Smiod 		  long setter;
32393d8817e4Smiod 		  int reg;
32403d8817e4Smiod 
32413d8817e4Smiod 		  if (INSN_BIG_ENDIAN)
32423d8817e4Smiod 		    setter = bfd_getb32 ((unsigned char *) buf - 4);
32433d8817e4Smiod 		  else
32443d8817e4Smiod 		    setter = bfd_getl32 ((unsigned char *) buf - 4);
32453d8817e4Smiod 		  if ((setter & (0xffffffff ^ RD (~0)))
32463d8817e4Smiod 		      != (INSN_OR | RS1 (O7) | RS2 (G0)))
32473d8817e4Smiod 		    break;
32483d8817e4Smiod 		  /* The sequence was
32493d8817e4Smiod 		     or %o7, %g0, %rN
32503d8817e4Smiod 		     call foo
32513d8817e4Smiod 		     or %rN, %g0, %o7
32523d8817e4Smiod 
32533d8817e4Smiod 		     If call foo was replaced with ba, replace
32543d8817e4Smiod 		     or %rN, %g0, %o7 with nop.  */
32553d8817e4Smiod 		  reg = (delay & RS1 (~0)) >> 14;
32563d8817e4Smiod 		  if (reg != ((setter & RD (~0)) >> 25)
32573d8817e4Smiod 		      || reg == G0 || reg == O7)
32583d8817e4Smiod 		    break;
32593d8817e4Smiod 
32603d8817e4Smiod 		  if (INSN_BIG_ENDIAN)
32613d8817e4Smiod 		    bfd_putb32 (INSN_NOP, (unsigned char *) buf + 4);
32623d8817e4Smiod 		  else
32633d8817e4Smiod 		    bfd_putl32 (INSN_NOP, (unsigned char *) buf + 4);
32643d8817e4Smiod 		}
32653d8817e4Smiod 	    }
32663d8817e4Smiod 	  break;
32673d8817e4Smiod 
32683d8817e4Smiod 	case BFD_RELOC_SPARC_11:
32693d8817e4Smiod 	  if (! in_signed_range (val, 0x7ff))
32703d8817e4Smiod 	    as_bad_where (fixP->fx_file, fixP->fx_line,
32713d8817e4Smiod 			  _("relocation overflow"));
32723d8817e4Smiod 	  insn |= val & 0x7ff;
32733d8817e4Smiod 	  break;
32743d8817e4Smiod 
32753d8817e4Smiod 	case BFD_RELOC_SPARC_10:
32763d8817e4Smiod 	  if (! in_signed_range (val, 0x3ff))
32773d8817e4Smiod 	    as_bad_where (fixP->fx_file, fixP->fx_line,
32783d8817e4Smiod 			  _("relocation overflow"));
32793d8817e4Smiod 	  insn |= val & 0x3ff;
32803d8817e4Smiod 	  break;
32813d8817e4Smiod 
32823d8817e4Smiod 	case BFD_RELOC_SPARC_7:
32833d8817e4Smiod 	  if (! in_bitfield_range (val, 0x7f))
32843d8817e4Smiod 	    as_bad_where (fixP->fx_file, fixP->fx_line,
32853d8817e4Smiod 			  _("relocation overflow"));
32863d8817e4Smiod 	  insn |= val & 0x7f;
32873d8817e4Smiod 	  break;
32883d8817e4Smiod 
32893d8817e4Smiod 	case BFD_RELOC_SPARC_6:
32903d8817e4Smiod 	  if (! in_bitfield_range (val, 0x3f))
32913d8817e4Smiod 	    as_bad_where (fixP->fx_file, fixP->fx_line,
32923d8817e4Smiod 			  _("relocation overflow"));
32933d8817e4Smiod 	  insn |= val & 0x3f;
32943d8817e4Smiod 	  break;
32953d8817e4Smiod 
32963d8817e4Smiod 	case BFD_RELOC_SPARC_5:
32973d8817e4Smiod 	  if (! in_bitfield_range (val, 0x1f))
32983d8817e4Smiod 	    as_bad_where (fixP->fx_file, fixP->fx_line,
32993d8817e4Smiod 			  _("relocation overflow"));
33003d8817e4Smiod 	  insn |= val & 0x1f;
33013d8817e4Smiod 	  break;
33023d8817e4Smiod 
33033d8817e4Smiod 	case BFD_RELOC_SPARC_WDISP16:
33043d8817e4Smiod 	  /* FIXME: simplify.  */
33053d8817e4Smiod 	  if (((val > 0) && (val & ~0x3fffc))
33063d8817e4Smiod 	      || ((val < 0) && (~(val - 1) & ~0x3fffc)))
33073d8817e4Smiod 	    as_bad_where (fixP->fx_file, fixP->fx_line,
33083d8817e4Smiod 			  _("relocation overflow"));
33093d8817e4Smiod 	  /* FIXME: The +1 deserves a comment.  */
33103d8817e4Smiod 	  val = (val >> 2) + 1;
33113d8817e4Smiod 	  insn |= ((val & 0xc000) << 6) | (val & 0x3fff);
33123d8817e4Smiod 	  break;
33133d8817e4Smiod 
33143d8817e4Smiod 	case BFD_RELOC_SPARC_WDISP19:
33153d8817e4Smiod 	  /* FIXME: simplify.  */
33163d8817e4Smiod 	  if (((val > 0) && (val & ~0x1ffffc))
33173d8817e4Smiod 	      || ((val < 0) && (~(val - 1) & ~0x1ffffc)))
33183d8817e4Smiod 	    as_bad_where (fixP->fx_file, fixP->fx_line,
33193d8817e4Smiod 			  _("relocation overflow"));
33203d8817e4Smiod 	  /* FIXME: The +1 deserves a comment.  */
33213d8817e4Smiod 	  val = (val >> 2) + 1;
33223d8817e4Smiod 	  insn |= val & 0x7ffff;
33233d8817e4Smiod 	  break;
33243d8817e4Smiod 
33253d8817e4Smiod 	case BFD_RELOC_SPARC_HH22:
33263d8817e4Smiod 	  val = BSR (val, 32);
33273d8817e4Smiod 	  /* Fall through.  */
33283d8817e4Smiod 
33293d8817e4Smiod 	case BFD_RELOC_SPARC_LM22:
33303d8817e4Smiod 	case BFD_RELOC_HI22:
33313d8817e4Smiod 	  if (!fixP->fx_addsy)
33323d8817e4Smiod 	    insn |= (val >> 10) & 0x3fffff;
33333d8817e4Smiod 	  else
33343d8817e4Smiod 	    /* FIXME: Need comment explaining why we do this.  */
33353d8817e4Smiod 	    insn &= ~0xffff;
33363d8817e4Smiod 	  break;
33373d8817e4Smiod 
33383d8817e4Smiod 	case BFD_RELOC_SPARC22:
33393d8817e4Smiod 	  if (val & ~0x003fffff)
33403d8817e4Smiod 	    as_bad_where (fixP->fx_file, fixP->fx_line,
33413d8817e4Smiod 			  _("relocation overflow"));
33423d8817e4Smiod 	  insn |= (val & 0x3fffff);
33433d8817e4Smiod 	  break;
33443d8817e4Smiod 
33453d8817e4Smiod 	case BFD_RELOC_SPARC_HM10:
33463d8817e4Smiod 	  val = BSR (val, 32);
33473d8817e4Smiod 	  /* Fall through.  */
33483d8817e4Smiod 
33493d8817e4Smiod 	case BFD_RELOC_LO10:
33503d8817e4Smiod 	  if (!fixP->fx_addsy)
33513d8817e4Smiod 	    insn |= val & 0x3ff;
33523d8817e4Smiod 	  else
33533d8817e4Smiod 	    /* FIXME: Need comment explaining why we do this.  */
33543d8817e4Smiod 	    insn &= ~0xff;
33553d8817e4Smiod 	  break;
33563d8817e4Smiod 
33573d8817e4Smiod 	case BFD_RELOC_SPARC_OLO10:
33583d8817e4Smiod 	  val &= 0x3ff;
33593d8817e4Smiod 	  val += fixP->tc_fix_data;
33603d8817e4Smiod 	  /* Fall through.  */
33613d8817e4Smiod 
33623d8817e4Smiod 	case BFD_RELOC_SPARC13:
33633d8817e4Smiod 	  if (! in_signed_range (val, 0x1fff))
33643d8817e4Smiod 	    as_bad_where (fixP->fx_file, fixP->fx_line,
33653d8817e4Smiod 			  _("relocation overflow"));
33663d8817e4Smiod 	  insn |= val & 0x1fff;
33673d8817e4Smiod 	  break;
33683d8817e4Smiod 
33693d8817e4Smiod 	case BFD_RELOC_SPARC_WDISP22:
33703d8817e4Smiod 	  val = (val >> 2) + 1;
33713d8817e4Smiod 	  /* Fall through.  */
33723d8817e4Smiod 	case BFD_RELOC_SPARC_BASE22:
33733d8817e4Smiod 	  insn |= val & 0x3fffff;
33743d8817e4Smiod 	  break;
33753d8817e4Smiod 
33763d8817e4Smiod 	case BFD_RELOC_SPARC_H44:
33773d8817e4Smiod 	  if (!fixP->fx_addsy)
33783d8817e4Smiod 	    {
33793d8817e4Smiod 	      bfd_vma tval = val;
33803d8817e4Smiod 	      tval >>= 22;
33813d8817e4Smiod 	      insn |= tval & 0x3fffff;
33823d8817e4Smiod 	    }
33833d8817e4Smiod 	  break;
33843d8817e4Smiod 
33853d8817e4Smiod 	case BFD_RELOC_SPARC_M44:
33863d8817e4Smiod 	  if (!fixP->fx_addsy)
33873d8817e4Smiod 	    insn |= (val >> 12) & 0x3ff;
33883d8817e4Smiod 	  break;
33893d8817e4Smiod 
33903d8817e4Smiod 	case BFD_RELOC_SPARC_L44:
33913d8817e4Smiod 	  if (!fixP->fx_addsy)
33923d8817e4Smiod 	    insn |= val & 0xfff;
33933d8817e4Smiod 	  break;
33943d8817e4Smiod 
33953d8817e4Smiod 	case BFD_RELOC_SPARC_HIX22:
33963d8817e4Smiod 	  if (!fixP->fx_addsy)
33973d8817e4Smiod 	    {
33983d8817e4Smiod 	      val ^= ~(offsetT) 0;
33993d8817e4Smiod 	      insn |= (val >> 10) & 0x3fffff;
34003d8817e4Smiod 	    }
34013d8817e4Smiod 	  break;
34023d8817e4Smiod 
34033d8817e4Smiod 	case BFD_RELOC_SPARC_LOX10:
34043d8817e4Smiod 	  if (!fixP->fx_addsy)
34053d8817e4Smiod 	    insn |= 0x1c00 | (val & 0x3ff);
34063d8817e4Smiod 	  break;
34073d8817e4Smiod 
34083d8817e4Smiod 	case BFD_RELOC_NONE:
34093d8817e4Smiod 	default:
34103d8817e4Smiod 	  as_bad_where (fixP->fx_file, fixP->fx_line,
34113d8817e4Smiod 			_("bad or unhandled relocation type: 0x%02x"),
34123d8817e4Smiod 			fixP->fx_r_type);
34133d8817e4Smiod 	  break;
34143d8817e4Smiod 	}
34153d8817e4Smiod 
34163d8817e4Smiod       if (INSN_BIG_ENDIAN)
34173d8817e4Smiod 	bfd_putb32 (insn, (unsigned char *) buf);
34183d8817e4Smiod       else
34193d8817e4Smiod 	bfd_putl32 (insn, (unsigned char *) buf);
34203d8817e4Smiod     }
34213d8817e4Smiod 
34223d8817e4Smiod   /* Are we finished with this relocation now?  */
34233d8817e4Smiod   if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
34243d8817e4Smiod     fixP->fx_done = 1;
34253d8817e4Smiod }
34263d8817e4Smiod 
34273d8817e4Smiod /* Translate internal representation of relocation info to BFD target
34283d8817e4Smiod    format.  */
34293d8817e4Smiod 
34303d8817e4Smiod arelent **
tc_gen_reloc(section,fixp)34313d8817e4Smiod tc_gen_reloc (section, fixp)
34323d8817e4Smiod      asection *section ATTRIBUTE_UNUSED;
34333d8817e4Smiod      fixS *fixp;
34343d8817e4Smiod {
34353d8817e4Smiod   static arelent *relocs[3];
34363d8817e4Smiod   arelent *reloc;
34373d8817e4Smiod   bfd_reloc_code_real_type code;
34383d8817e4Smiod 
34393d8817e4Smiod   relocs[0] = reloc = (arelent *) xmalloc (sizeof (arelent));
34403d8817e4Smiod   relocs[1] = NULL;
34413d8817e4Smiod 
34423d8817e4Smiod   reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
34433d8817e4Smiod   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
34443d8817e4Smiod   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
34453d8817e4Smiod 
34463d8817e4Smiod   switch (fixp->fx_r_type)
34473d8817e4Smiod     {
34483d8817e4Smiod     case BFD_RELOC_16:
34493d8817e4Smiod     case BFD_RELOC_32:
34503d8817e4Smiod     case BFD_RELOC_HI22:
34513d8817e4Smiod     case BFD_RELOC_LO10:
34523d8817e4Smiod     case BFD_RELOC_32_PCREL_S2:
34533d8817e4Smiod     case BFD_RELOC_SPARC13:
34543d8817e4Smiod     case BFD_RELOC_SPARC22:
34553d8817e4Smiod     case BFD_RELOC_SPARC_BASE13:
34563d8817e4Smiod     case BFD_RELOC_SPARC_WDISP16:
34573d8817e4Smiod     case BFD_RELOC_SPARC_WDISP19:
34583d8817e4Smiod     case BFD_RELOC_SPARC_WDISP22:
34593d8817e4Smiod     case BFD_RELOC_64:
34603d8817e4Smiod     case BFD_RELOC_SPARC_5:
34613d8817e4Smiod     case BFD_RELOC_SPARC_6:
34623d8817e4Smiod     case BFD_RELOC_SPARC_7:
34633d8817e4Smiod     case BFD_RELOC_SPARC_10:
34643d8817e4Smiod     case BFD_RELOC_SPARC_11:
34653d8817e4Smiod     case BFD_RELOC_SPARC_HH22:
34663d8817e4Smiod     case BFD_RELOC_SPARC_HM10:
34673d8817e4Smiod     case BFD_RELOC_SPARC_LM22:
34683d8817e4Smiod     case BFD_RELOC_SPARC_PC_HH22:
34693d8817e4Smiod     case BFD_RELOC_SPARC_PC_HM10:
34703d8817e4Smiod     case BFD_RELOC_SPARC_PC_LM22:
34713d8817e4Smiod     case BFD_RELOC_SPARC_H44:
34723d8817e4Smiod     case BFD_RELOC_SPARC_M44:
34733d8817e4Smiod     case BFD_RELOC_SPARC_L44:
34743d8817e4Smiod     case BFD_RELOC_SPARC_HIX22:
34753d8817e4Smiod     case BFD_RELOC_SPARC_LOX10:
34763d8817e4Smiod     case BFD_RELOC_SPARC_REV32:
34773d8817e4Smiod     case BFD_RELOC_SPARC_OLO10:
34783d8817e4Smiod     case BFD_RELOC_SPARC_UA16:
34793d8817e4Smiod     case BFD_RELOC_SPARC_UA32:
34803d8817e4Smiod     case BFD_RELOC_SPARC_UA64:
34813d8817e4Smiod     case BFD_RELOC_8_PCREL:
34823d8817e4Smiod     case BFD_RELOC_16_PCREL:
34833d8817e4Smiod     case BFD_RELOC_32_PCREL:
34843d8817e4Smiod     case BFD_RELOC_64_PCREL:
34853d8817e4Smiod     case BFD_RELOC_SPARC_PLT32:
34863d8817e4Smiod     case BFD_RELOC_SPARC_PLT64:
34873d8817e4Smiod     case BFD_RELOC_VTABLE_ENTRY:
34883d8817e4Smiod     case BFD_RELOC_VTABLE_INHERIT:
34893d8817e4Smiod     case BFD_RELOC_SPARC_TLS_GD_HI22:
34903d8817e4Smiod     case BFD_RELOC_SPARC_TLS_GD_LO10:
34913d8817e4Smiod     case BFD_RELOC_SPARC_TLS_GD_ADD:
34923d8817e4Smiod     case BFD_RELOC_SPARC_TLS_GD_CALL:
34933d8817e4Smiod     case BFD_RELOC_SPARC_TLS_LDM_HI22:
34943d8817e4Smiod     case BFD_RELOC_SPARC_TLS_LDM_LO10:
34953d8817e4Smiod     case BFD_RELOC_SPARC_TLS_LDM_ADD:
34963d8817e4Smiod     case BFD_RELOC_SPARC_TLS_LDM_CALL:
34973d8817e4Smiod     case BFD_RELOC_SPARC_TLS_LDO_HIX22:
34983d8817e4Smiod     case BFD_RELOC_SPARC_TLS_LDO_LOX10:
34993d8817e4Smiod     case BFD_RELOC_SPARC_TLS_LDO_ADD:
35003d8817e4Smiod     case BFD_RELOC_SPARC_TLS_IE_HI22:
35013d8817e4Smiod     case BFD_RELOC_SPARC_TLS_IE_LO10:
35023d8817e4Smiod     case BFD_RELOC_SPARC_TLS_IE_LD:
35033d8817e4Smiod     case BFD_RELOC_SPARC_TLS_IE_LDX:
35043d8817e4Smiod     case BFD_RELOC_SPARC_TLS_IE_ADD:
35053d8817e4Smiod     case BFD_RELOC_SPARC_TLS_LE_HIX22:
35063d8817e4Smiod     case BFD_RELOC_SPARC_TLS_LE_LOX10:
35073d8817e4Smiod     case BFD_RELOC_SPARC_TLS_DTPOFF32:
35083d8817e4Smiod     case BFD_RELOC_SPARC_TLS_DTPOFF64:
35093d8817e4Smiod       code = fixp->fx_r_type;
35103d8817e4Smiod       break;
35113d8817e4Smiod     default:
35123d8817e4Smiod       abort ();
35133d8817e4Smiod       return NULL;
35143d8817e4Smiod     }
35153d8817e4Smiod 
35163d8817e4Smiod #if defined (OBJ_ELF) || defined (OBJ_AOUT)
35173d8817e4Smiod   /* If we are generating PIC code, we need to generate a different
35183d8817e4Smiod      set of relocs.  */
35193d8817e4Smiod 
35203d8817e4Smiod #ifdef OBJ_ELF
35213d8817e4Smiod #define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
35223d8817e4Smiod #else
35233d8817e4Smiod #define GOT_NAME "__GLOBAL_OFFSET_TABLE_"
35243d8817e4Smiod #endif
35253d8817e4Smiod #ifdef TE_VXWORKS
35263d8817e4Smiod #define GOTT_BASE "__GOTT_BASE__"
35273d8817e4Smiod #define GOTT_INDEX "__GOTT_INDEX__"
35283d8817e4Smiod #endif
35293d8817e4Smiod 
35303d8817e4Smiod   /* This code must be parallel to the OBJ_ELF tc_fix_adjustable.  */
35313d8817e4Smiod 
35323d8817e4Smiod   if (sparc_pic_code)
35333d8817e4Smiod     {
35343d8817e4Smiod       switch (code)
35353d8817e4Smiod 	{
35363d8817e4Smiod 	case BFD_RELOC_32_PCREL_S2:
35373d8817e4Smiod 	  if (generic_force_reloc (fixp))
35383d8817e4Smiod 	    code = BFD_RELOC_SPARC_WPLT30;
35393d8817e4Smiod 	  break;
35403d8817e4Smiod 	case BFD_RELOC_HI22:
35413d8817e4Smiod 	  code = BFD_RELOC_SPARC_GOT22;
35423d8817e4Smiod 	  if (fixp->fx_addsy != NULL)
35433d8817e4Smiod 	    {
35443d8817e4Smiod 	      if (strcmp (S_GET_NAME (fixp->fx_addsy), GOT_NAME) == 0)
35453d8817e4Smiod 		code = BFD_RELOC_SPARC_PC22;
35463d8817e4Smiod #ifdef TE_VXWORKS
35473d8817e4Smiod 	      if (strcmp (S_GET_NAME (fixp->fx_addsy), GOTT_BASE) == 0
35483d8817e4Smiod 		  || strcmp (S_GET_NAME (fixp->fx_addsy), GOTT_INDEX) == 0)
35493d8817e4Smiod 		code = BFD_RELOC_HI22; /* Unchanged.  */
35503d8817e4Smiod #endif
35513d8817e4Smiod 	    }
35523d8817e4Smiod 	  break;
35533d8817e4Smiod 	case BFD_RELOC_LO10:
35543d8817e4Smiod 	  code = BFD_RELOC_SPARC_GOT10;
35553d8817e4Smiod 	  if (fixp->fx_addsy != NULL)
35563d8817e4Smiod 	    {
35573d8817e4Smiod 	      if (strcmp (S_GET_NAME (fixp->fx_addsy), GOT_NAME) == 0)
35583d8817e4Smiod 		code = BFD_RELOC_SPARC_PC10;
35593d8817e4Smiod #ifdef TE_VXWORKS
35603d8817e4Smiod 	      if (strcmp (S_GET_NAME (fixp->fx_addsy), GOTT_BASE) == 0
35613d8817e4Smiod 		  || strcmp (S_GET_NAME (fixp->fx_addsy), GOTT_INDEX) == 0)
35623d8817e4Smiod 		code = BFD_RELOC_LO10; /* Unchanged.  */
35633d8817e4Smiod #endif
35643d8817e4Smiod 	    }
35653d8817e4Smiod 	  break;
35663d8817e4Smiod 	case BFD_RELOC_SPARC13:
35673d8817e4Smiod 	  code = BFD_RELOC_SPARC_GOT13;
35683d8817e4Smiod 	  break;
35693d8817e4Smiod 	default:
35703d8817e4Smiod 	  break;
35713d8817e4Smiod 	}
35723d8817e4Smiod     }
35733d8817e4Smiod #endif /* defined (OBJ_ELF) || defined (OBJ_AOUT)  */
35743d8817e4Smiod 
35753d8817e4Smiod   if (code == BFD_RELOC_SPARC_OLO10)
35763d8817e4Smiod     reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO10);
35773d8817e4Smiod   else
35783d8817e4Smiod     reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
35793d8817e4Smiod   if (reloc->howto == 0)
35803d8817e4Smiod     {
35813d8817e4Smiod       as_bad_where (fixp->fx_file, fixp->fx_line,
35823d8817e4Smiod 		    _("internal error: can't export reloc type %d (`%s')"),
35833d8817e4Smiod 		    fixp->fx_r_type, bfd_get_reloc_code_name (code));
35843d8817e4Smiod       xfree (reloc);
35853d8817e4Smiod       relocs[0] = NULL;
35863d8817e4Smiod       return relocs;
35873d8817e4Smiod     }
35883d8817e4Smiod 
35893d8817e4Smiod   /* @@ Why fx_addnumber sometimes and fx_offset other times?  */
35903d8817e4Smiod #ifdef OBJ_AOUT
35913d8817e4Smiod 
35923d8817e4Smiod   if (reloc->howto->pc_relative == 0
35933d8817e4Smiod       || code == BFD_RELOC_SPARC_PC10
35943d8817e4Smiod       || code == BFD_RELOC_SPARC_PC22)
35953d8817e4Smiod     reloc->addend = fixp->fx_addnumber;
35963d8817e4Smiod   else if (sparc_pic_code
35973d8817e4Smiod 	   && fixp->fx_r_type == BFD_RELOC_32_PCREL_S2
35983d8817e4Smiod 	   && fixp->fx_addsy != NULL
35993d8817e4Smiod 	   && (S_IS_EXTERNAL (fixp->fx_addsy)
36003d8817e4Smiod 	       || S_IS_WEAK (fixp->fx_addsy))
36013d8817e4Smiod 	   && S_IS_DEFINED (fixp->fx_addsy)
36023d8817e4Smiod 	   && ! S_IS_COMMON (fixp->fx_addsy))
36033d8817e4Smiod     reloc->addend = fixp->fx_addnumber;
36043d8817e4Smiod   else
36053d8817e4Smiod     reloc->addend = fixp->fx_offset - reloc->address;
36063d8817e4Smiod 
36073d8817e4Smiod #else /* elf or coff  */
36083d8817e4Smiod 
36093d8817e4Smiod   if (code != BFD_RELOC_32_PCREL_S2
36103d8817e4Smiod       && code != BFD_RELOC_SPARC_WDISP22
36113d8817e4Smiod       && code != BFD_RELOC_SPARC_WDISP16
36123d8817e4Smiod       && code != BFD_RELOC_SPARC_WDISP19
36133d8817e4Smiod       && code != BFD_RELOC_SPARC_WPLT30
36143d8817e4Smiod       && code != BFD_RELOC_SPARC_TLS_GD_CALL
36153d8817e4Smiod       && code != BFD_RELOC_SPARC_TLS_LDM_CALL)
36163d8817e4Smiod     reloc->addend = fixp->fx_addnumber;
36173d8817e4Smiod   else if (symbol_section_p (fixp->fx_addsy))
36183d8817e4Smiod     reloc->addend = (section->vma
36193d8817e4Smiod 		     + fixp->fx_addnumber
36203d8817e4Smiod 		     + md_pcrel_from (fixp));
36213d8817e4Smiod   else
36223d8817e4Smiod     reloc->addend = fixp->fx_offset;
36233d8817e4Smiod #endif
36243d8817e4Smiod 
36253d8817e4Smiod   /* We expand R_SPARC_OLO10 to R_SPARC_LO10 and R_SPARC_13
36263d8817e4Smiod      on the same location.  */
36273d8817e4Smiod   if (code == BFD_RELOC_SPARC_OLO10)
36283d8817e4Smiod     {
36293d8817e4Smiod       relocs[1] = reloc = (arelent *) xmalloc (sizeof (arelent));
36303d8817e4Smiod       relocs[2] = NULL;
36313d8817e4Smiod 
36323d8817e4Smiod       reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
36333d8817e4Smiod       *reloc->sym_ptr_ptr
36343d8817e4Smiod 	= symbol_get_bfdsym (section_symbol (absolute_section));
36353d8817e4Smiod       reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
36363d8817e4Smiod       reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_SPARC13);
36373d8817e4Smiod       reloc->addend = fixp->tc_fix_data;
36383d8817e4Smiod     }
36393d8817e4Smiod 
36403d8817e4Smiod   return relocs;
36413d8817e4Smiod }
36423d8817e4Smiod 
36433d8817e4Smiod /* We have no need to default values of symbols.  */
36443d8817e4Smiod 
36453d8817e4Smiod symbolS *
md_undefined_symbol(name)36463d8817e4Smiod md_undefined_symbol (name)
36473d8817e4Smiod      char *name ATTRIBUTE_UNUSED;
36483d8817e4Smiod {
36493d8817e4Smiod   return 0;
36503d8817e4Smiod }
36513d8817e4Smiod 
36523d8817e4Smiod /* Round up a section size to the appropriate boundary.  */
36533d8817e4Smiod 
36543d8817e4Smiod valueT
md_section_align(segment,size)36553d8817e4Smiod md_section_align (segment, size)
36563d8817e4Smiod      segT segment ATTRIBUTE_UNUSED;
36573d8817e4Smiod      valueT size;
36583d8817e4Smiod {
36593d8817e4Smiod #ifndef OBJ_ELF
36603d8817e4Smiod   /* This is not right for ELF; a.out wants it, and COFF will force
36613d8817e4Smiod      the alignment anyways.  */
36623d8817e4Smiod   valueT align = ((valueT) 1
36633d8817e4Smiod 		  << (valueT) bfd_get_section_alignment (stdoutput, segment));
36643d8817e4Smiod   valueT newsize;
36653d8817e4Smiod 
36663d8817e4Smiod   /* Turn alignment value into a mask.  */
36673d8817e4Smiod   align--;
36683d8817e4Smiod   newsize = (size + align) & ~align;
36693d8817e4Smiod   return newsize;
36703d8817e4Smiod #else
36713d8817e4Smiod   return size;
36723d8817e4Smiod #endif
36733d8817e4Smiod }
36743d8817e4Smiod 
36753d8817e4Smiod /* Exactly what point is a PC-relative offset relative TO?
36763d8817e4Smiod    On the sparc, they're relative to the address of the offset, plus
36773d8817e4Smiod    its size.  This gets us to the following instruction.
36783d8817e4Smiod    (??? Is this right?  FIXME-SOON)  */
36793d8817e4Smiod long
md_pcrel_from(fixP)36803d8817e4Smiod md_pcrel_from (fixP)
36813d8817e4Smiod      fixS *fixP;
36823d8817e4Smiod {
36833d8817e4Smiod   long ret;
36843d8817e4Smiod 
36853d8817e4Smiod   ret = fixP->fx_where + fixP->fx_frag->fr_address;
36863d8817e4Smiod   if (! sparc_pic_code
36873d8817e4Smiod       || fixP->fx_addsy == NULL
36883d8817e4Smiod       || symbol_section_p (fixP->fx_addsy))
36893d8817e4Smiod     ret += fixP->fx_size;
36903d8817e4Smiod   return ret;
36913d8817e4Smiod }
36923d8817e4Smiod 
36933d8817e4Smiod /* Return log2 (VALUE), or -1 if VALUE is not an exact positive power
36943d8817e4Smiod    of two.  */
36953d8817e4Smiod 
36963d8817e4Smiod static int
mylog2(value)36973d8817e4Smiod mylog2 (value)
36983d8817e4Smiod      int value;
36993d8817e4Smiod {
37003d8817e4Smiod   int shift;
37013d8817e4Smiod 
37023d8817e4Smiod   if (value <= 0)
37033d8817e4Smiod     return -1;
37043d8817e4Smiod 
37053d8817e4Smiod   for (shift = 0; (value & 1) == 0; value >>= 1)
37063d8817e4Smiod     ++shift;
37073d8817e4Smiod 
37083d8817e4Smiod   return (value == 1) ? shift : -1;
37093d8817e4Smiod }
37103d8817e4Smiod 
37113d8817e4Smiod /* Sort of like s_lcomm.  */
37123d8817e4Smiod 
37133d8817e4Smiod #ifndef OBJ_ELF
37143d8817e4Smiod static int max_alignment = 15;
37153d8817e4Smiod #endif
37163d8817e4Smiod 
37173d8817e4Smiod static void
s_reserve(ignore)37183d8817e4Smiod s_reserve (ignore)
37193d8817e4Smiod      int ignore ATTRIBUTE_UNUSED;
37203d8817e4Smiod {
37213d8817e4Smiod   char *name;
37223d8817e4Smiod   char *p;
37233d8817e4Smiod   char c;
37243d8817e4Smiod   int align;
37253d8817e4Smiod   int size;
37263d8817e4Smiod   int temp;
37273d8817e4Smiod   symbolS *symbolP;
37283d8817e4Smiod 
37293d8817e4Smiod   name = input_line_pointer;
37303d8817e4Smiod   c = get_symbol_end ();
37313d8817e4Smiod   p = input_line_pointer;
37323d8817e4Smiod   *p = c;
37333d8817e4Smiod   SKIP_WHITESPACE ();
37343d8817e4Smiod 
37353d8817e4Smiod   if (*input_line_pointer != ',')
37363d8817e4Smiod     {
37373d8817e4Smiod       as_bad (_("Expected comma after name"));
37383d8817e4Smiod       ignore_rest_of_line ();
37393d8817e4Smiod       return;
37403d8817e4Smiod     }
37413d8817e4Smiod 
37423d8817e4Smiod   ++input_line_pointer;
37433d8817e4Smiod 
37443d8817e4Smiod   if ((size = get_absolute_expression ()) < 0)
37453d8817e4Smiod     {
37463d8817e4Smiod       as_bad (_("BSS length (%d.) <0! Ignored."), size);
37473d8817e4Smiod       ignore_rest_of_line ();
37483d8817e4Smiod       return;
37493d8817e4Smiod     }				/* Bad length.  */
37503d8817e4Smiod 
37513d8817e4Smiod   *p = 0;
37523d8817e4Smiod   symbolP = symbol_find_or_make (name);
37533d8817e4Smiod   *p = c;
37543d8817e4Smiod 
37553d8817e4Smiod   if (strncmp (input_line_pointer, ",\"bss\"", 6) != 0
37563d8817e4Smiod       && strncmp (input_line_pointer, ",\".bss\"", 7) != 0)
37573d8817e4Smiod     {
37583d8817e4Smiod       as_bad (_("bad .reserve segment -- expected BSS segment"));
37593d8817e4Smiod       return;
37603d8817e4Smiod     }
37613d8817e4Smiod 
37623d8817e4Smiod   if (input_line_pointer[2] == '.')
37633d8817e4Smiod     input_line_pointer += 7;
37643d8817e4Smiod   else
37653d8817e4Smiod     input_line_pointer += 6;
37663d8817e4Smiod   SKIP_WHITESPACE ();
37673d8817e4Smiod 
37683d8817e4Smiod   if (*input_line_pointer == ',')
37693d8817e4Smiod     {
37703d8817e4Smiod       ++input_line_pointer;
37713d8817e4Smiod 
37723d8817e4Smiod       SKIP_WHITESPACE ();
37733d8817e4Smiod       if (*input_line_pointer == '\n')
37743d8817e4Smiod 	{
37753d8817e4Smiod 	  as_bad (_("missing alignment"));
37763d8817e4Smiod 	  ignore_rest_of_line ();
37773d8817e4Smiod 	  return;
37783d8817e4Smiod 	}
37793d8817e4Smiod 
37803d8817e4Smiod       align = (int) get_absolute_expression ();
37813d8817e4Smiod 
37823d8817e4Smiod #ifndef OBJ_ELF
37833d8817e4Smiod       if (align > max_alignment)
37843d8817e4Smiod 	{
37853d8817e4Smiod 	  align = max_alignment;
37863d8817e4Smiod 	  as_warn (_("alignment too large; assuming %d"), align);
37873d8817e4Smiod 	}
37883d8817e4Smiod #endif
37893d8817e4Smiod 
37903d8817e4Smiod       if (align < 0)
37913d8817e4Smiod 	{
37923d8817e4Smiod 	  as_bad (_("negative alignment"));
37933d8817e4Smiod 	  ignore_rest_of_line ();
37943d8817e4Smiod 	  return;
37953d8817e4Smiod 	}
37963d8817e4Smiod 
37973d8817e4Smiod       if (align != 0)
37983d8817e4Smiod 	{
37993d8817e4Smiod 	  temp = mylog2 (align);
38003d8817e4Smiod 	  if (temp < 0)
38013d8817e4Smiod 	    {
38023d8817e4Smiod 	      as_bad (_("alignment not a power of 2"));
38033d8817e4Smiod 	      ignore_rest_of_line ();
38043d8817e4Smiod 	      return;
38053d8817e4Smiod 	    }
38063d8817e4Smiod 
38073d8817e4Smiod 	  align = temp;
38083d8817e4Smiod 	}
38093d8817e4Smiod 
38103d8817e4Smiod       record_alignment (bss_section, align);
38113d8817e4Smiod     }
38123d8817e4Smiod   else
38133d8817e4Smiod     align = 0;
38143d8817e4Smiod 
38153d8817e4Smiod   if (!S_IS_DEFINED (symbolP)
38163d8817e4Smiod #ifdef OBJ_AOUT
38173d8817e4Smiod       && S_GET_OTHER (symbolP) == 0
38183d8817e4Smiod       && S_GET_DESC (symbolP) == 0
38193d8817e4Smiod #endif
38203d8817e4Smiod       )
38213d8817e4Smiod     {
38223d8817e4Smiod       if (! need_pass_2)
38233d8817e4Smiod 	{
38243d8817e4Smiod 	  char *pfrag;
38253d8817e4Smiod 	  segT current_seg = now_seg;
38263d8817e4Smiod 	  subsegT current_subseg = now_subseg;
38273d8817e4Smiod 
38283d8817e4Smiod 	  /* Switch to bss.  */
38293d8817e4Smiod 	  subseg_set (bss_section, 1);
38303d8817e4Smiod 
38313d8817e4Smiod 	  if (align)
38323d8817e4Smiod 	    /* Do alignment.  */
38333d8817e4Smiod 	    frag_align (align, 0, 0);
38343d8817e4Smiod 
38353d8817e4Smiod 	  /* Detach from old frag.  */
38363d8817e4Smiod 	  if (S_GET_SEGMENT (symbolP) == bss_section)
38373d8817e4Smiod 	    symbol_get_frag (symbolP)->fr_symbol = NULL;
38383d8817e4Smiod 
38393d8817e4Smiod 	  symbol_set_frag (symbolP, frag_now);
38403d8817e4Smiod 	  pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
38413d8817e4Smiod 			    (offsetT) size, (char *) 0);
38423d8817e4Smiod 	  *pfrag = 0;
38433d8817e4Smiod 
38443d8817e4Smiod 	  S_SET_SEGMENT (symbolP, bss_section);
38453d8817e4Smiod 
38463d8817e4Smiod 	  subseg_set (current_seg, current_subseg);
38473d8817e4Smiod 
38483d8817e4Smiod #ifdef OBJ_ELF
38493d8817e4Smiod 	  S_SET_SIZE (symbolP, size);
38503d8817e4Smiod #endif
38513d8817e4Smiod 	}
38523d8817e4Smiod     }
38533d8817e4Smiod   else
38543d8817e4Smiod     {
38553d8817e4Smiod       as_warn ("Ignoring attempt to re-define symbol %s",
38563d8817e4Smiod 	       S_GET_NAME (symbolP));
38573d8817e4Smiod     }				/* if not redefining.  */
38583d8817e4Smiod 
38593d8817e4Smiod   demand_empty_rest_of_line ();
38603d8817e4Smiod }
38613d8817e4Smiod 
38623d8817e4Smiod static void
s_common(ignore)38633d8817e4Smiod s_common (ignore)
38643d8817e4Smiod      int ignore ATTRIBUTE_UNUSED;
38653d8817e4Smiod {
38663d8817e4Smiod   char *name;
38673d8817e4Smiod   char c;
38683d8817e4Smiod   char *p;
38693d8817e4Smiod   offsetT temp, size;
38703d8817e4Smiod   symbolS *symbolP;
38713d8817e4Smiod 
38723d8817e4Smiod   name = input_line_pointer;
38733d8817e4Smiod   c = get_symbol_end ();
38743d8817e4Smiod   /* Just after name is now '\0'.  */
38753d8817e4Smiod   p = input_line_pointer;
38763d8817e4Smiod   *p = c;
38773d8817e4Smiod   SKIP_WHITESPACE ();
38783d8817e4Smiod   if (*input_line_pointer != ',')
38793d8817e4Smiod     {
38803d8817e4Smiod       as_bad (_("Expected comma after symbol-name"));
38813d8817e4Smiod       ignore_rest_of_line ();
38823d8817e4Smiod       return;
38833d8817e4Smiod     }
38843d8817e4Smiod 
38853d8817e4Smiod   /* Skip ','.  */
38863d8817e4Smiod   input_line_pointer++;
38873d8817e4Smiod 
38883d8817e4Smiod   if ((temp = get_absolute_expression ()) < 0)
38893d8817e4Smiod     {
38903d8817e4Smiod       as_bad (_(".COMMon length (%lu) out of range ignored"),
38913d8817e4Smiod 	      (unsigned long) temp);
38923d8817e4Smiod       ignore_rest_of_line ();
38933d8817e4Smiod       return;
38943d8817e4Smiod     }
38953d8817e4Smiod   size = temp;
38963d8817e4Smiod   *p = 0;
38973d8817e4Smiod   symbolP = symbol_find_or_make (name);
38983d8817e4Smiod   *p = c;
38993d8817e4Smiod   if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
39003d8817e4Smiod     {
39013d8817e4Smiod       as_bad (_("Ignoring attempt to re-define symbol"));
39023d8817e4Smiod       ignore_rest_of_line ();
39033d8817e4Smiod       return;
39043d8817e4Smiod     }
39053d8817e4Smiod   if (S_GET_VALUE (symbolP) != 0)
39063d8817e4Smiod     {
39073d8817e4Smiod       if (S_GET_VALUE (symbolP) != (valueT) size)
39083d8817e4Smiod 	{
39093d8817e4Smiod 	  as_warn (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."),
39103d8817e4Smiod 		   S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), (long) size);
39113d8817e4Smiod 	}
39123d8817e4Smiod     }
39133d8817e4Smiod   else
39143d8817e4Smiod     {
39153d8817e4Smiod #ifndef OBJ_ELF
39163d8817e4Smiod       S_SET_VALUE (symbolP, (valueT) size);
39173d8817e4Smiod       S_SET_EXTERNAL (symbolP);
39183d8817e4Smiod #endif
39193d8817e4Smiod     }
39203d8817e4Smiod   know (symbol_get_frag (symbolP) == &zero_address_frag);
39213d8817e4Smiod   if (*input_line_pointer != ',')
39223d8817e4Smiod     {
39233d8817e4Smiod       as_bad (_("Expected comma after common length"));
39243d8817e4Smiod       ignore_rest_of_line ();
39253d8817e4Smiod       return;
39263d8817e4Smiod     }
39273d8817e4Smiod   input_line_pointer++;
39283d8817e4Smiod   SKIP_WHITESPACE ();
39293d8817e4Smiod   if (*input_line_pointer != '"')
39303d8817e4Smiod     {
39313d8817e4Smiod       temp = get_absolute_expression ();
39323d8817e4Smiod 
39333d8817e4Smiod #ifndef OBJ_ELF
39343d8817e4Smiod       if (temp > max_alignment)
39353d8817e4Smiod 	{
39363d8817e4Smiod 	  temp = max_alignment;
39373d8817e4Smiod 	  as_warn (_("alignment too large; assuming %ld"), (long) temp);
39383d8817e4Smiod 	}
39393d8817e4Smiod #endif
39403d8817e4Smiod 
39413d8817e4Smiod       if (temp < 0)
39423d8817e4Smiod 	{
39433d8817e4Smiod 	  as_bad (_("negative alignment"));
39443d8817e4Smiod 	  ignore_rest_of_line ();
39453d8817e4Smiod 	  return;
39463d8817e4Smiod 	}
39473d8817e4Smiod 
39483d8817e4Smiod #ifdef OBJ_ELF
39493d8817e4Smiod       if (symbol_get_obj (symbolP)->local)
39503d8817e4Smiod 	{
39513d8817e4Smiod 	  segT old_sec;
39523d8817e4Smiod 	  int old_subsec;
39533d8817e4Smiod 	  char *p;
39543d8817e4Smiod 	  int align;
39553d8817e4Smiod 
39563d8817e4Smiod 	  old_sec = now_seg;
39573d8817e4Smiod 	  old_subsec = now_subseg;
39583d8817e4Smiod 
39593d8817e4Smiod 	  if (temp == 0)
39603d8817e4Smiod 	    align = 0;
39613d8817e4Smiod 	  else
39623d8817e4Smiod 	    align = mylog2 (temp);
39633d8817e4Smiod 
39643d8817e4Smiod 	  if (align < 0)
39653d8817e4Smiod 	    {
39663d8817e4Smiod 	      as_bad (_("alignment not a power of 2"));
39673d8817e4Smiod 	      ignore_rest_of_line ();
39683d8817e4Smiod 	      return;
39693d8817e4Smiod 	    }
39703d8817e4Smiod 
39713d8817e4Smiod 	  record_alignment (bss_section, align);
39723d8817e4Smiod 	  subseg_set (bss_section, 0);
39733d8817e4Smiod 	  if (align)
39743d8817e4Smiod 	    frag_align (align, 0, 0);
39753d8817e4Smiod 	  if (S_GET_SEGMENT (symbolP) == bss_section)
39763d8817e4Smiod 	    symbol_get_frag (symbolP)->fr_symbol = 0;
39773d8817e4Smiod 	  symbol_set_frag (symbolP, frag_now);
39783d8817e4Smiod 	  p = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
39793d8817e4Smiod 			(offsetT) size, (char *) 0);
39803d8817e4Smiod 	  *p = 0;
39813d8817e4Smiod 	  S_SET_SEGMENT (symbolP, bss_section);
39823d8817e4Smiod 	  S_CLEAR_EXTERNAL (symbolP);
39833d8817e4Smiod 	  S_SET_SIZE (symbolP, size);
39843d8817e4Smiod 	  subseg_set (old_sec, old_subsec);
39853d8817e4Smiod 	}
39863d8817e4Smiod       else
39873d8817e4Smiod #endif /* OBJ_ELF  */
39883d8817e4Smiod 	{
39893d8817e4Smiod 	allocate_common:
39903d8817e4Smiod 	  S_SET_VALUE (symbolP, (valueT) size);
39913d8817e4Smiod #ifdef OBJ_ELF
39923d8817e4Smiod 	  S_SET_ALIGN (symbolP, temp);
39933d8817e4Smiod 	  S_SET_SIZE (symbolP, size);
39943d8817e4Smiod #endif
39953d8817e4Smiod 	  S_SET_EXTERNAL (symbolP);
39963d8817e4Smiod 	  S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
39973d8817e4Smiod 	}
39983d8817e4Smiod     }
39993d8817e4Smiod   else
40003d8817e4Smiod     {
40013d8817e4Smiod       input_line_pointer++;
40023d8817e4Smiod       /* @@ Some use the dot, some don't.  Can we get some consistency??  */
40033d8817e4Smiod       if (*input_line_pointer == '.')
40043d8817e4Smiod 	input_line_pointer++;
40053d8817e4Smiod       /* @@ Some say data, some say bss.  */
40063d8817e4Smiod       if (strncmp (input_line_pointer, "bss\"", 4)
40073d8817e4Smiod 	  && strncmp (input_line_pointer, "data\"", 5))
40083d8817e4Smiod 	{
40093d8817e4Smiod 	  while (*--input_line_pointer != '"')
40103d8817e4Smiod 	    ;
40113d8817e4Smiod 	  input_line_pointer--;
40123d8817e4Smiod 	  goto bad_common_segment;
40133d8817e4Smiod 	}
40143d8817e4Smiod       while (*input_line_pointer++ != '"')
40153d8817e4Smiod 	;
40163d8817e4Smiod       goto allocate_common;
40173d8817e4Smiod     }
40183d8817e4Smiod 
40193d8817e4Smiod   symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
40203d8817e4Smiod 
40213d8817e4Smiod   demand_empty_rest_of_line ();
40223d8817e4Smiod   return;
40233d8817e4Smiod 
40243d8817e4Smiod   {
40253d8817e4Smiod   bad_common_segment:
40263d8817e4Smiod     p = input_line_pointer;
40273d8817e4Smiod     while (*p && *p != '\n')
40283d8817e4Smiod       p++;
40293d8817e4Smiod     c = *p;
40303d8817e4Smiod     *p = '\0';
40313d8817e4Smiod     as_bad (_("bad .common segment %s"), input_line_pointer + 1);
40323d8817e4Smiod     *p = c;
40333d8817e4Smiod     input_line_pointer = p;
40343d8817e4Smiod     ignore_rest_of_line ();
40353d8817e4Smiod     return;
40363d8817e4Smiod   }
40373d8817e4Smiod }
40383d8817e4Smiod 
40393d8817e4Smiod /* Handle the .empty pseudo-op.  This suppresses the warnings about
40403d8817e4Smiod    invalid delay slot usage.  */
40413d8817e4Smiod 
40423d8817e4Smiod static void
s_empty(ignore)40433d8817e4Smiod s_empty (ignore)
40443d8817e4Smiod      int ignore ATTRIBUTE_UNUSED;
40453d8817e4Smiod {
40463d8817e4Smiod   /* The easy way to implement is to just forget about the last
40473d8817e4Smiod      instruction.  */
40483d8817e4Smiod   last_insn = NULL;
40493d8817e4Smiod }
40503d8817e4Smiod 
40513d8817e4Smiod static void
s_seg(ignore)40523d8817e4Smiod s_seg (ignore)
40533d8817e4Smiod      int ignore ATTRIBUTE_UNUSED;
40543d8817e4Smiod {
40553d8817e4Smiod 
40563d8817e4Smiod   if (strncmp (input_line_pointer, "\"text\"", 6) == 0)
40573d8817e4Smiod     {
40583d8817e4Smiod       input_line_pointer += 6;
40593d8817e4Smiod       s_text (0);
40603d8817e4Smiod       return;
40613d8817e4Smiod     }
40623d8817e4Smiod   if (strncmp (input_line_pointer, "\"data\"", 6) == 0)
40633d8817e4Smiod     {
40643d8817e4Smiod       input_line_pointer += 6;
40653d8817e4Smiod       s_data (0);
40663d8817e4Smiod       return;
40673d8817e4Smiod     }
40683d8817e4Smiod   if (strncmp (input_line_pointer, "\"data1\"", 7) == 0)
40693d8817e4Smiod     {
40703d8817e4Smiod       input_line_pointer += 7;
40713d8817e4Smiod       s_data1 ();
40723d8817e4Smiod       return;
40733d8817e4Smiod     }
40743d8817e4Smiod   if (strncmp (input_line_pointer, "\"bss\"", 5) == 0)
40753d8817e4Smiod     {
40763d8817e4Smiod       input_line_pointer += 5;
40773d8817e4Smiod       /* We only support 2 segments -- text and data -- for now, so
40783d8817e4Smiod 	 things in the "bss segment" will have to go into data for now.
40793d8817e4Smiod 	 You can still allocate SEG_BSS stuff with .lcomm or .reserve.  */
40803d8817e4Smiod       subseg_set (data_section, 255);	/* FIXME-SOMEDAY.  */
40813d8817e4Smiod       return;
40823d8817e4Smiod     }
40833d8817e4Smiod   as_bad (_("Unknown segment type"));
40843d8817e4Smiod   demand_empty_rest_of_line ();
40853d8817e4Smiod }
40863d8817e4Smiod 
40873d8817e4Smiod static void
s_data1()40883d8817e4Smiod s_data1 ()
40893d8817e4Smiod {
40903d8817e4Smiod   subseg_set (data_section, 1);
40913d8817e4Smiod   demand_empty_rest_of_line ();
40923d8817e4Smiod }
40933d8817e4Smiod 
40943d8817e4Smiod static void
s_proc(ignore)40953d8817e4Smiod s_proc (ignore)
40963d8817e4Smiod      int ignore ATTRIBUTE_UNUSED;
40973d8817e4Smiod {
40983d8817e4Smiod   while (!is_end_of_line[(unsigned char) *input_line_pointer])
40993d8817e4Smiod     {
41003d8817e4Smiod       ++input_line_pointer;
41013d8817e4Smiod     }
41023d8817e4Smiod   ++input_line_pointer;
41033d8817e4Smiod }
41043d8817e4Smiod 
41053d8817e4Smiod /* This static variable is set by s_uacons to tell sparc_cons_align
41063d8817e4Smiod    that the expression does not need to be aligned.  */
41073d8817e4Smiod 
41083d8817e4Smiod static int sparc_no_align_cons = 0;
41093d8817e4Smiod 
41103d8817e4Smiod /* This static variable is set by sparc_cons to emit requested types
41113d8817e4Smiod    of relocations in cons_fix_new_sparc.  */
41123d8817e4Smiod 
41133d8817e4Smiod static const char *sparc_cons_special_reloc;
41143d8817e4Smiod 
41153d8817e4Smiod /* This handles the unaligned space allocation pseudo-ops, such as
41163d8817e4Smiod    .uaword.  .uaword is just like .word, but the value does not need
41173d8817e4Smiod    to be aligned.  */
41183d8817e4Smiod 
41193d8817e4Smiod static void
s_uacons(bytes)41203d8817e4Smiod s_uacons (bytes)
41213d8817e4Smiod      int bytes;
41223d8817e4Smiod {
41233d8817e4Smiod   /* Tell sparc_cons_align not to align this value.  */
41243d8817e4Smiod   sparc_no_align_cons = 1;
41253d8817e4Smiod   cons (bytes);
41263d8817e4Smiod   sparc_no_align_cons = 0;
41273d8817e4Smiod }
41283d8817e4Smiod 
41293d8817e4Smiod /* This handles the native word allocation pseudo-op .nword.
41303d8817e4Smiod    For sparc_arch_size 32 it is equivalent to .word,  for
41313d8817e4Smiod    sparc_arch_size 64 it is equivalent to .xword.  */
41323d8817e4Smiod 
41333d8817e4Smiod static void
s_ncons(bytes)41343d8817e4Smiod s_ncons (bytes)
41353d8817e4Smiod      int bytes ATTRIBUTE_UNUSED;
41363d8817e4Smiod {
41373d8817e4Smiod   cons (sparc_arch_size == 32 ? 4 : 8);
41383d8817e4Smiod }
41393d8817e4Smiod 
41403d8817e4Smiod #ifdef OBJ_ELF
41413d8817e4Smiod /* Handle the SPARC ELF .register pseudo-op.  This sets the binding of a
41423d8817e4Smiod    global register.
41433d8817e4Smiod    The syntax is:
41443d8817e4Smiod 
41453d8817e4Smiod    .register %g[2367],{#scratch|symbolname|#ignore}
41463d8817e4Smiod */
41473d8817e4Smiod 
41483d8817e4Smiod static void
s_register(ignore)41493d8817e4Smiod s_register (ignore)
41503d8817e4Smiod      int ignore ATTRIBUTE_UNUSED;
41513d8817e4Smiod {
41523d8817e4Smiod   char c;
41533d8817e4Smiod   int reg;
41543d8817e4Smiod   int flags;
41553d8817e4Smiod   const char *regname;
41563d8817e4Smiod 
41573d8817e4Smiod   if (input_line_pointer[0] != '%'
41583d8817e4Smiod       || input_line_pointer[1] != 'g'
41593d8817e4Smiod       || ((input_line_pointer[2] & ~1) != '2'
41603d8817e4Smiod 	  && (input_line_pointer[2] & ~1) != '6')
41613d8817e4Smiod       || input_line_pointer[3] != ',')
41623d8817e4Smiod     as_bad (_("register syntax is .register %%g[2367],{#scratch|symbolname|#ignore}"));
41633d8817e4Smiod   reg = input_line_pointer[2] - '0';
41643d8817e4Smiod   input_line_pointer += 4;
41653d8817e4Smiod 
41663d8817e4Smiod   if (*input_line_pointer == '#')
41673d8817e4Smiod     {
41683d8817e4Smiod       ++input_line_pointer;
41693d8817e4Smiod       regname = input_line_pointer;
41703d8817e4Smiod       c = get_symbol_end ();
41713d8817e4Smiod       if (strcmp (regname, "scratch") && strcmp (regname, "ignore"))
41723d8817e4Smiod 	as_bad (_("register syntax is .register %%g[2367],{#scratch|symbolname|#ignore}"));
41733d8817e4Smiod       if (regname[0] == 'i')
41743d8817e4Smiod 	regname = NULL;
41753d8817e4Smiod       else
41763d8817e4Smiod 	regname = "";
41773d8817e4Smiod     }
41783d8817e4Smiod   else
41793d8817e4Smiod     {
41803d8817e4Smiod       regname = input_line_pointer;
41813d8817e4Smiod       c = get_symbol_end ();
41823d8817e4Smiod     }
41833d8817e4Smiod   if (sparc_arch_size == 64)
41843d8817e4Smiod     {
41853d8817e4Smiod       if (globals[reg])
41863d8817e4Smiod 	{
41873d8817e4Smiod 	  if ((regname && globals[reg] != (symbolS *) 1
41883d8817e4Smiod 	       && strcmp (S_GET_NAME (globals[reg]), regname))
41893d8817e4Smiod 	      || ((regname != NULL) ^ (globals[reg] != (symbolS *) 1)))
41903d8817e4Smiod 	    as_bad (_("redefinition of global register"));
41913d8817e4Smiod 	}
41923d8817e4Smiod       else
41933d8817e4Smiod 	{
41943d8817e4Smiod 	  if (regname == NULL)
41953d8817e4Smiod 	    globals[reg] = (symbolS *) 1;
41963d8817e4Smiod 	  else
41973d8817e4Smiod 	    {
41983d8817e4Smiod 	      if (*regname)
41993d8817e4Smiod 		{
42003d8817e4Smiod 		  if (symbol_find (regname))
42013d8817e4Smiod 		    as_bad (_("Register symbol %s already defined."),
42023d8817e4Smiod 			    regname);
42033d8817e4Smiod 		}
42043d8817e4Smiod 	      globals[reg] = symbol_make (regname);
42053d8817e4Smiod 	      flags = symbol_get_bfdsym (globals[reg])->flags;
42063d8817e4Smiod 	      if (! *regname)
42073d8817e4Smiod 		flags = flags & ~(BSF_GLOBAL|BSF_LOCAL|BSF_WEAK);
42083d8817e4Smiod 	      if (! (flags & (BSF_GLOBAL|BSF_LOCAL|BSF_WEAK)))
42093d8817e4Smiod 		flags |= BSF_GLOBAL;
42103d8817e4Smiod 	      symbol_get_bfdsym (globals[reg])->flags = flags;
42113d8817e4Smiod 	      S_SET_VALUE (globals[reg], (valueT) reg);
42123d8817e4Smiod 	      S_SET_ALIGN (globals[reg], reg);
42133d8817e4Smiod 	      S_SET_SIZE (globals[reg], 0);
42143d8817e4Smiod 	      /* Although we actually want undefined_section here,
42153d8817e4Smiod 		 we have to use absolute_section, because otherwise
42163d8817e4Smiod 		 generic as code will make it a COM section.
42173d8817e4Smiod 		 We fix this up in sparc_adjust_symtab.  */
42183d8817e4Smiod 	      S_SET_SEGMENT (globals[reg], absolute_section);
42193d8817e4Smiod 	      S_SET_OTHER (globals[reg], 0);
42203d8817e4Smiod 	      elf_symbol (symbol_get_bfdsym (globals[reg]))
42213d8817e4Smiod 		->internal_elf_sym.st_info =
42223d8817e4Smiod 		  ELF_ST_INFO(STB_GLOBAL, STT_REGISTER);
42233d8817e4Smiod 	      elf_symbol (symbol_get_bfdsym (globals[reg]))
42243d8817e4Smiod 		->internal_elf_sym.st_shndx = SHN_UNDEF;
42253d8817e4Smiod 	    }
42263d8817e4Smiod 	}
42273d8817e4Smiod     }
42283d8817e4Smiod 
42293d8817e4Smiod   *input_line_pointer = c;
42303d8817e4Smiod 
42313d8817e4Smiod   demand_empty_rest_of_line ();
42323d8817e4Smiod }
42333d8817e4Smiod 
42343d8817e4Smiod /* Adjust the symbol table.  We set undefined sections for STT_REGISTER
42353d8817e4Smiod    symbols which need it.  */
42363d8817e4Smiod 
42373d8817e4Smiod void
sparc_adjust_symtab()42383d8817e4Smiod sparc_adjust_symtab ()
42393d8817e4Smiod {
42403d8817e4Smiod   symbolS *sym;
42413d8817e4Smiod 
42423d8817e4Smiod   for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
42433d8817e4Smiod     {
42443d8817e4Smiod       if (ELF_ST_TYPE (elf_symbol (symbol_get_bfdsym (sym))
42453d8817e4Smiod 		       ->internal_elf_sym.st_info) != STT_REGISTER)
42463d8817e4Smiod 	continue;
42473d8817e4Smiod 
42483d8817e4Smiod       if (ELF_ST_TYPE (elf_symbol (symbol_get_bfdsym (sym))
42493d8817e4Smiod 		       ->internal_elf_sym.st_shndx != SHN_UNDEF))
42503d8817e4Smiod 	continue;
42513d8817e4Smiod 
42523d8817e4Smiod       S_SET_SEGMENT (sym, undefined_section);
42533d8817e4Smiod     }
42543d8817e4Smiod }
42553d8817e4Smiod #endif
42563d8817e4Smiod 
42573d8817e4Smiod /* If the --enforce-aligned-data option is used, we require .word,
42583d8817e4Smiod    et. al., to be aligned correctly.  We do it by setting up an
42593d8817e4Smiod    rs_align_code frag, and checking in HANDLE_ALIGN to make sure that
42603d8817e4Smiod    no unexpected alignment was introduced.
42613d8817e4Smiod 
42623d8817e4Smiod    The SunOS and Solaris native assemblers enforce aligned data by
42633d8817e4Smiod    default.  We don't want to do that, because gcc can deliberately
42643d8817e4Smiod    generate misaligned data if the packed attribute is used.  Instead,
42653d8817e4Smiod    we permit misaligned data by default, and permit the user to set an
42663d8817e4Smiod    option to check for it.  */
42673d8817e4Smiod 
42683d8817e4Smiod void
sparc_cons_align(nbytes)42693d8817e4Smiod sparc_cons_align (nbytes)
42703d8817e4Smiod      int nbytes;
42713d8817e4Smiod {
42723d8817e4Smiod   int nalign;
42733d8817e4Smiod   char *p;
42743d8817e4Smiod 
42753d8817e4Smiod   /* Only do this if we are enforcing aligned data.  */
42763d8817e4Smiod   if (! enforce_aligned_data)
42773d8817e4Smiod     return;
42783d8817e4Smiod 
42793d8817e4Smiod   /* Don't align if this is an unaligned pseudo-op.  */
42803d8817e4Smiod   if (sparc_no_align_cons)
42813d8817e4Smiod     return;
42823d8817e4Smiod 
42833d8817e4Smiod   nalign = mylog2 (nbytes);
42843d8817e4Smiod   if (nalign == 0)
42853d8817e4Smiod     return;
42863d8817e4Smiod 
42873d8817e4Smiod   assert (nalign > 0);
42883d8817e4Smiod 
42893d8817e4Smiod   if (now_seg == absolute_section)
42903d8817e4Smiod     {
42913d8817e4Smiod       if ((abs_section_offset & ((1 << nalign) - 1)) != 0)
42923d8817e4Smiod 	as_bad (_("misaligned data"));
42933d8817e4Smiod       return;
42943d8817e4Smiod     }
42953d8817e4Smiod 
42963d8817e4Smiod   p = frag_var (rs_align_test, 1, 1, (relax_substateT) 0,
42973d8817e4Smiod 		(symbolS *) NULL, (offsetT) nalign, (char *) NULL);
42983d8817e4Smiod 
42993d8817e4Smiod   record_alignment (now_seg, nalign);
43003d8817e4Smiod }
43013d8817e4Smiod 
43023d8817e4Smiod /* This is called from HANDLE_ALIGN in tc-sparc.h.  */
43033d8817e4Smiod 
43043d8817e4Smiod void
sparc_handle_align(fragp)43053d8817e4Smiod sparc_handle_align (fragp)
43063d8817e4Smiod      fragS *fragp;
43073d8817e4Smiod {
43083d8817e4Smiod   int count, fix;
43093d8817e4Smiod   char *p;
43103d8817e4Smiod 
43113d8817e4Smiod   count = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
43123d8817e4Smiod 
43133d8817e4Smiod   switch (fragp->fr_type)
43143d8817e4Smiod     {
43153d8817e4Smiod     case rs_align_test:
43163d8817e4Smiod       if (count != 0)
43173d8817e4Smiod 	as_bad_where (fragp->fr_file, fragp->fr_line, _("misaligned data"));
43183d8817e4Smiod       break;
43193d8817e4Smiod 
43203d8817e4Smiod     case rs_align_code:
43213d8817e4Smiod       p = fragp->fr_literal + fragp->fr_fix;
43223d8817e4Smiod       fix = 0;
43233d8817e4Smiod 
43243d8817e4Smiod       if (count & 3)
43253d8817e4Smiod 	{
43263d8817e4Smiod 	  fix = count & 3;
43273d8817e4Smiod 	  memset (p, 0, fix);
43283d8817e4Smiod 	  p += fix;
43293d8817e4Smiod 	  count -= fix;
43303d8817e4Smiod 	}
43313d8817e4Smiod 
43323d8817e4Smiod       if (SPARC_OPCODE_ARCH_V9_P (max_architecture) && count > 8)
43333d8817e4Smiod 	{
43343d8817e4Smiod 	  unsigned wval = (0x30680000 | count >> 2); /* ba,a,pt %xcc, 1f  */
43353d8817e4Smiod 	  if (INSN_BIG_ENDIAN)
43363d8817e4Smiod 	    number_to_chars_bigendian (p, wval, 4);
43373d8817e4Smiod 	  else
43383d8817e4Smiod 	    number_to_chars_littleendian (p, wval, 4);
43393d8817e4Smiod 	  p += 4;
43403d8817e4Smiod 	  count -= 4;
43413d8817e4Smiod 	  fix += 4;
43423d8817e4Smiod 	}
43433d8817e4Smiod 
43443d8817e4Smiod       if (INSN_BIG_ENDIAN)
43453d8817e4Smiod 	number_to_chars_bigendian (p, 0x01000000, 4);
43463d8817e4Smiod       else
43473d8817e4Smiod 	number_to_chars_littleendian (p, 0x01000000, 4);
43483d8817e4Smiod 
43493d8817e4Smiod       fragp->fr_fix += fix;
43503d8817e4Smiod       fragp->fr_var = 4;
43513d8817e4Smiod       break;
43523d8817e4Smiod 
43533d8817e4Smiod     default:
43543d8817e4Smiod       break;
43553d8817e4Smiod     }
43563d8817e4Smiod }
43573d8817e4Smiod 
43583d8817e4Smiod #ifdef OBJ_ELF
43593d8817e4Smiod /* Some special processing for a Sparc ELF file.  */
43603d8817e4Smiod 
43613d8817e4Smiod void
sparc_elf_final_processing()43623d8817e4Smiod sparc_elf_final_processing ()
43633d8817e4Smiod {
43643d8817e4Smiod   /* Set the Sparc ELF flag bits.  FIXME: There should probably be some
43653d8817e4Smiod      sort of BFD interface for this.  */
43663d8817e4Smiod   if (sparc_arch_size == 64)
43673d8817e4Smiod     {
43683d8817e4Smiod       switch (sparc_memory_model)
43693d8817e4Smiod 	{
43703d8817e4Smiod 	case MM_RMO:
43713d8817e4Smiod 	  elf_elfheader (stdoutput)->e_flags |= EF_SPARCV9_RMO;
43723d8817e4Smiod 	  break;
43733d8817e4Smiod 	case MM_PSO:
43743d8817e4Smiod 	  elf_elfheader (stdoutput)->e_flags |= EF_SPARCV9_PSO;
43753d8817e4Smiod 	  break;
43763d8817e4Smiod 	default:
43773d8817e4Smiod 	  break;
43783d8817e4Smiod 	}
43793d8817e4Smiod     }
43803d8817e4Smiod   else if (current_architecture >= SPARC_OPCODE_ARCH_V9)
43813d8817e4Smiod     elf_elfheader (stdoutput)->e_flags |= EF_SPARC_32PLUS;
43823d8817e4Smiod   if (current_architecture == SPARC_OPCODE_ARCH_V9A)
43833d8817e4Smiod     elf_elfheader (stdoutput)->e_flags |= EF_SPARC_SUN_US1;
43843d8817e4Smiod   else if (current_architecture == SPARC_OPCODE_ARCH_V9B)
43853d8817e4Smiod     elf_elfheader (stdoutput)->e_flags |= EF_SPARC_SUN_US1|EF_SPARC_SUN_US3;
43863d8817e4Smiod }
43873d8817e4Smiod 
43883d8817e4Smiod void
sparc_cons(exp,size)43893d8817e4Smiod sparc_cons (exp, size)
43903d8817e4Smiod      expressionS *exp;
43913d8817e4Smiod      int size;
43923d8817e4Smiod {
43933d8817e4Smiod   char *save;
43943d8817e4Smiod 
43953d8817e4Smiod   SKIP_WHITESPACE ();
43963d8817e4Smiod   sparc_cons_special_reloc = NULL;
43973d8817e4Smiod   save = input_line_pointer;
43983d8817e4Smiod   if (input_line_pointer[0] == '%'
43993d8817e4Smiod       && input_line_pointer[1] == 'r'
44003d8817e4Smiod       && input_line_pointer[2] == '_')
44013d8817e4Smiod     {
44023d8817e4Smiod       if (strncmp (input_line_pointer + 3, "disp", 4) == 0)
44033d8817e4Smiod 	{
44043d8817e4Smiod 	  input_line_pointer += 7;
44053d8817e4Smiod 	  sparc_cons_special_reloc = "disp";
44063d8817e4Smiod 	}
44073d8817e4Smiod       else if (strncmp (input_line_pointer + 3, "plt", 3) == 0)
44083d8817e4Smiod 	{
44093d8817e4Smiod 	  if (size != 4 && size != 8)
44103d8817e4Smiod 	    as_bad (_("Illegal operands: %%r_plt in %d-byte data field"), size);
44113d8817e4Smiod 	  else
44123d8817e4Smiod 	    {
44133d8817e4Smiod 	      input_line_pointer += 6;
44143d8817e4Smiod 	      sparc_cons_special_reloc = "plt";
44153d8817e4Smiod 	    }
44163d8817e4Smiod 	}
44173d8817e4Smiod       else if (strncmp (input_line_pointer + 3, "tls_dtpoff", 10) == 0)
44183d8817e4Smiod 	{
44193d8817e4Smiod 	  if (size != 4 && size != 8)
44203d8817e4Smiod 	    as_bad (_("Illegal operands: %%r_tls_dtpoff in %d-byte data field"), size);
44213d8817e4Smiod 	  else
44223d8817e4Smiod 	    {
44233d8817e4Smiod 	      input_line_pointer += 13;
44243d8817e4Smiod 	      sparc_cons_special_reloc = "tls_dtpoff";
44253d8817e4Smiod 	    }
44263d8817e4Smiod 	}
44273d8817e4Smiod       if (sparc_cons_special_reloc)
44283d8817e4Smiod 	{
44293d8817e4Smiod 	  int bad = 0;
44303d8817e4Smiod 
44313d8817e4Smiod 	  switch (size)
44323d8817e4Smiod 	    {
44333d8817e4Smiod 	    case 1:
44343d8817e4Smiod 	      if (*input_line_pointer != '8')
44353d8817e4Smiod 		bad = 1;
44363d8817e4Smiod 	      input_line_pointer--;
44373d8817e4Smiod 	      break;
44383d8817e4Smiod 	    case 2:
44393d8817e4Smiod 	      if (input_line_pointer[0] != '1' || input_line_pointer[1] != '6')
44403d8817e4Smiod 		bad = 1;
44413d8817e4Smiod 	      break;
44423d8817e4Smiod 	    case 4:
44433d8817e4Smiod 	      if (input_line_pointer[0] != '3' || input_line_pointer[1] != '2')
44443d8817e4Smiod 		bad = 1;
44453d8817e4Smiod 	      break;
44463d8817e4Smiod 	    case 8:
44473d8817e4Smiod 	      if (input_line_pointer[0] != '6' || input_line_pointer[1] != '4')
44483d8817e4Smiod 		bad = 1;
44493d8817e4Smiod 	      break;
44503d8817e4Smiod 	    default:
44513d8817e4Smiod 	      bad = 1;
44523d8817e4Smiod 	      break;
44533d8817e4Smiod 	    }
44543d8817e4Smiod 
44553d8817e4Smiod 	  if (bad)
44563d8817e4Smiod 	    {
44573d8817e4Smiod 	      as_bad (_("Illegal operands: Only %%r_%s%d allowed in %d-byte data fields"),
44583d8817e4Smiod 		      sparc_cons_special_reloc, size * 8, size);
44593d8817e4Smiod 	    }
44603d8817e4Smiod 	  else
44613d8817e4Smiod 	    {
44623d8817e4Smiod 	      input_line_pointer += 2;
44633d8817e4Smiod 	      if (*input_line_pointer != '(')
44643d8817e4Smiod 		{
44653d8817e4Smiod 		  as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
44663d8817e4Smiod 			  sparc_cons_special_reloc, size * 8);
44673d8817e4Smiod 		  bad = 1;
44683d8817e4Smiod 		}
44693d8817e4Smiod 	    }
44703d8817e4Smiod 
44713d8817e4Smiod 	  if (bad)
44723d8817e4Smiod 	    {
44733d8817e4Smiod 	      input_line_pointer = save;
44743d8817e4Smiod 	      sparc_cons_special_reloc = NULL;
44753d8817e4Smiod 	    }
44763d8817e4Smiod 	  else
44773d8817e4Smiod 	    {
44783d8817e4Smiod 	      int c;
44793d8817e4Smiod 	      char *end = ++input_line_pointer;
44803d8817e4Smiod 	      int npar = 0;
44813d8817e4Smiod 
44823d8817e4Smiod 	      while (! is_end_of_line[(c = *end)])
44833d8817e4Smiod 		{
44843d8817e4Smiod 		  if (c == '(')
44853d8817e4Smiod 	  	    npar++;
44863d8817e4Smiod 		  else if (c == ')')
44873d8817e4Smiod 	  	    {
44883d8817e4Smiod 		      if (!npar)
44893d8817e4Smiod 	      		break;
44903d8817e4Smiod 		      npar--;
44913d8817e4Smiod 		    }
44923d8817e4Smiod 	    	  end++;
44933d8817e4Smiod 		}
44943d8817e4Smiod 
44953d8817e4Smiod 	      if (c != ')')
44963d8817e4Smiod 		as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
44973d8817e4Smiod 			sparc_cons_special_reloc, size * 8);
44983d8817e4Smiod 	      else
44993d8817e4Smiod 		{
45003d8817e4Smiod 		  *end = '\0';
45013d8817e4Smiod 		  expression (exp);
45023d8817e4Smiod 		  *end = c;
45033d8817e4Smiod 		  if (input_line_pointer != end)
45043d8817e4Smiod 		    {
45053d8817e4Smiod 		      as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
45063d8817e4Smiod 			      sparc_cons_special_reloc, size * 8);
45073d8817e4Smiod 		    }
45083d8817e4Smiod 		  else
45093d8817e4Smiod 		    {
45103d8817e4Smiod 		      input_line_pointer++;
45113d8817e4Smiod 		      SKIP_WHITESPACE ();
45123d8817e4Smiod 		      c = *input_line_pointer;
45133d8817e4Smiod 		      if (! is_end_of_line[c] && c != ',')
45143d8817e4Smiod 			as_bad (_("Illegal operands: garbage after %%r_%s%d()"),
45153d8817e4Smiod 			        sparc_cons_special_reloc, size * 8);
45163d8817e4Smiod 		    }
45173d8817e4Smiod 		}
45183d8817e4Smiod 	    }
45193d8817e4Smiod 	}
45203d8817e4Smiod     }
45213d8817e4Smiod   if (sparc_cons_special_reloc == NULL)
45223d8817e4Smiod     expression (exp);
45233d8817e4Smiod }
45243d8817e4Smiod 
45253d8817e4Smiod #endif
45263d8817e4Smiod 
45273d8817e4Smiod /* This is called by emit_expr via TC_CONS_FIX_NEW when creating a
45283d8817e4Smiod    reloc for a cons.  We could use the definition there, except that
45293d8817e4Smiod    we want to handle little endian relocs specially.  */
45303d8817e4Smiod 
45313d8817e4Smiod void
cons_fix_new_sparc(frag,where,nbytes,exp)45323d8817e4Smiod cons_fix_new_sparc (frag, where, nbytes, exp)
45333d8817e4Smiod      fragS *frag;
45343d8817e4Smiod      int where;
45353d8817e4Smiod      unsigned int nbytes;
45363d8817e4Smiod      expressionS *exp;
45373d8817e4Smiod {
45383d8817e4Smiod   bfd_reloc_code_real_type r;
45393d8817e4Smiod 
45403d8817e4Smiod   r = (nbytes == 1 ? BFD_RELOC_8 :
45413d8817e4Smiod        (nbytes == 2 ? BFD_RELOC_16 :
45423d8817e4Smiod 	(nbytes == 4 ? BFD_RELOC_32 : BFD_RELOC_64)));
45433d8817e4Smiod 
45443d8817e4Smiod   if (target_little_endian_data
45453d8817e4Smiod       && nbytes == 4
45463d8817e4Smiod       && now_seg->flags & SEC_ALLOC)
45473d8817e4Smiod     r = BFD_RELOC_SPARC_REV32;
45483d8817e4Smiod 
45493d8817e4Smiod   if (sparc_cons_special_reloc)
45503d8817e4Smiod     {
45513d8817e4Smiod       if (*sparc_cons_special_reloc == 'd')
45523d8817e4Smiod 	switch (nbytes)
45533d8817e4Smiod 	  {
45543d8817e4Smiod 	  case 1: r = BFD_RELOC_8_PCREL; break;
45553d8817e4Smiod 	  case 2: r = BFD_RELOC_16_PCREL; break;
45563d8817e4Smiod 	  case 4: r = BFD_RELOC_32_PCREL; break;
45573d8817e4Smiod 	  case 8: r = BFD_RELOC_64_PCREL; break;
45583d8817e4Smiod 	  default: abort ();
45593d8817e4Smiod 	  }
45603d8817e4Smiod       else if (*sparc_cons_special_reloc == 'p')
45613d8817e4Smiod 	switch (nbytes)
45623d8817e4Smiod 	  {
45633d8817e4Smiod 	  case 4: r = BFD_RELOC_SPARC_PLT32; break;
45643d8817e4Smiod 	  case 8: r = BFD_RELOC_SPARC_PLT64; break;
45653d8817e4Smiod 	  }
45663d8817e4Smiod       else
45673d8817e4Smiod 	switch (nbytes)
45683d8817e4Smiod 	  {
45693d8817e4Smiod 	  case 4: r = BFD_RELOC_SPARC_TLS_DTPOFF32; break;
45703d8817e4Smiod 	  case 8: r = BFD_RELOC_SPARC_TLS_DTPOFF64; break;
45713d8817e4Smiod 	  }
45723d8817e4Smiod     }
45733d8817e4Smiod   else if (sparc_no_align_cons)
45743d8817e4Smiod     {
45753d8817e4Smiod       switch (nbytes)
45763d8817e4Smiod 	{
45773d8817e4Smiod 	case 2: r = BFD_RELOC_SPARC_UA16; break;
45783d8817e4Smiod 	case 4: r = BFD_RELOC_SPARC_UA32; break;
45793d8817e4Smiod 	case 8: r = BFD_RELOC_SPARC_UA64; break;
45803d8817e4Smiod 	default: abort ();
45813d8817e4Smiod 	}
45823d8817e4Smiod    }
45833d8817e4Smiod 
45843d8817e4Smiod   fix_new_exp (frag, where, (int) nbytes, exp, 0, r);
45853d8817e4Smiod   sparc_cons_special_reloc = NULL;
45863d8817e4Smiod }
45873d8817e4Smiod 
45883d8817e4Smiod void
sparc_cfi_frame_initial_instructions()45893d8817e4Smiod sparc_cfi_frame_initial_instructions ()
45903d8817e4Smiod {
45913d8817e4Smiod   cfi_add_CFA_def_cfa (14, sparc_arch_size == 64 ? 0x7ff : 0);
45923d8817e4Smiod }
45933d8817e4Smiod 
45943d8817e4Smiod int
sparc_regname_to_dw2regnum(const char * regname)45953d8817e4Smiod sparc_regname_to_dw2regnum (const char *regname)
45963d8817e4Smiod {
45973d8817e4Smiod   char *p, *q;
45983d8817e4Smiod 
45993d8817e4Smiod   if (!regname[0])
46003d8817e4Smiod     return -1;
46013d8817e4Smiod 
46023d8817e4Smiod   q = "goli";
46033d8817e4Smiod   p = strchr (q, regname[0]);
46043d8817e4Smiod   if (p)
46053d8817e4Smiod     {
46063d8817e4Smiod       if (regname[1] < '0' || regname[1] > '8' || regname[2])
46073d8817e4Smiod 	return -1;
46083d8817e4Smiod       return (p - q) * 8 + regname[1] - '0';
46093d8817e4Smiod     }
46103d8817e4Smiod   if (regname[0] == 's' && regname[1] == 'p' && !regname[2])
46113d8817e4Smiod     return 14;
46123d8817e4Smiod   if (regname[0] == 'f' && regname[1] == 'p' && !regname[2])
46133d8817e4Smiod     return 30;
46143d8817e4Smiod   if (regname[0] == 'f' || regname[0] == 'r')
46153d8817e4Smiod     {
46163d8817e4Smiod       unsigned int regnum;
46173d8817e4Smiod 
46183d8817e4Smiod       regnum = strtoul (regname + 1, &q, 10);
46193d8817e4Smiod       if (p == q || *q)
46203d8817e4Smiod         return -1;
46213d8817e4Smiod       if (regnum >= ((regname[0] == 'f'
46223d8817e4Smiod 		      && SPARC_OPCODE_ARCH_V9_P (max_architecture))
46233d8817e4Smiod 		     ? 64 : 32))
46243d8817e4Smiod 	return -1;
46253d8817e4Smiod       if (regname[0] == 'f')
46263d8817e4Smiod 	{
46273d8817e4Smiod           regnum += 32;
46283d8817e4Smiod           if (regnum >= 64 && (regnum & 1))
46293d8817e4Smiod 	    return -1;
46303d8817e4Smiod         }
46313d8817e4Smiod       return regnum;
46323d8817e4Smiod     }
46333d8817e4Smiod   return -1;
46343d8817e4Smiod }
46353d8817e4Smiod 
46363d8817e4Smiod void
sparc_cfi_emit_pcrel_expr(expressionS * exp,unsigned int nbytes)46373d8817e4Smiod sparc_cfi_emit_pcrel_expr (expressionS *exp, unsigned int nbytes)
46383d8817e4Smiod {
46393d8817e4Smiod   sparc_cons_special_reloc = "disp";
46403d8817e4Smiod   sparc_no_align_cons = 1;
46413d8817e4Smiod   emit_expr (exp, nbytes);
46423d8817e4Smiod   sparc_no_align_cons = 0;
46433d8817e4Smiod   sparc_cons_special_reloc = NULL;
46443d8817e4Smiod }
4645