159024Sobrien/* tc-sparc.c -- Assemble for the SPARC
278828Sobrien   Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3218822Sdim   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
477298Sobrien   Free Software Foundation, Inc.
559024Sobrien   This file is part of GAS, the GNU Assembler.
659024Sobrien
759024Sobrien   GAS is free software; you can redistribute it and/or modify
859024Sobrien   it under the terms of the GNU General Public License as published by
959024Sobrien   the Free Software Foundation; either version 2, or (at your option)
1059024Sobrien   any later version.
1159024Sobrien
1259024Sobrien   GAS is distributed in the hope that it will be useful,
1359024Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1459024Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1559024Sobrien   GNU General Public License for more details.
1659024Sobrien
1759024Sobrien   You should have received a copy of the GNU General Public
1859024Sobrien   License along with GAS; see the file COPYING.  If not, write
19218822Sdim   to the Free Software Foundation, 51 Franklin Street - Fifth Floor,
20218822Sdim   Boston, MA 02110-1301, USA.  */
2159024Sobrien
2259024Sobrien#include "as.h"
2389857Sobrien#include "safe-ctype.h"
2459024Sobrien#include "subsegs.h"
2559024Sobrien
2659024Sobrien#include "opcode/sparc.h"
27130561Sobrien#include "dw2gencfi.h"
2859024Sobrien
2959024Sobrien#ifdef OBJ_ELF
3059024Sobrien#include "elf/sparc.h"
3177298Sobrien#include "dwarf2dbg.h"
3259024Sobrien#endif
3359024Sobrien
3491041Sobrien/* Some ancient Sun C compilers would not take such hex constants as
3591041Sobrien   unsigned, and would end up sign-extending them to form an offsetT,
3691041Sobrien   so use these constants instead.  */
3791041Sobrien#define U0xffffffff ((((unsigned long) 1 << 16) << 16) - 1)
3891041Sobrien#define U0x80000000 ((((unsigned long) 1 << 16) << 15))
3991041Sobrien
4059024Sobrienstatic struct sparc_arch *lookup_arch PARAMS ((char *));
4159024Sobrienstatic void init_default_arch PARAMS ((void));
4260484Sobrienstatic int sparc_ip PARAMS ((char *, const struct sparc_opcode **));
4359024Sobrienstatic int in_signed_range PARAMS ((bfd_signed_vma, bfd_signed_vma));
4459024Sobrienstatic int in_unsigned_range PARAMS ((bfd_vma, bfd_vma));
4559024Sobrienstatic int in_bitfield_range PARAMS ((bfd_signed_vma, bfd_signed_vma));
4659024Sobrienstatic int sparc_ffs PARAMS ((unsigned int));
4760484Sobrienstatic void synthetize_setuw PARAMS ((const struct sparc_opcode *));
4860484Sobrienstatic void synthetize_setsw PARAMS ((const struct sparc_opcode *));
4960484Sobrienstatic void synthetize_setx PARAMS ((const struct sparc_opcode *));
5059024Sobrienstatic bfd_vma BSR PARAMS ((bfd_vma, int));
5159024Sobrienstatic int cmp_reg_entry PARAMS ((const PTR, const PTR));
5259024Sobrienstatic int parse_keyword_arg PARAMS ((int (*) (const char *), char **, int *));
5359024Sobrienstatic int parse_const_expr_arg PARAMS ((char **, int *));
5459024Sobrienstatic int get_expression PARAMS ((char *str));
5559024Sobrien
5659024Sobrien/* Default architecture.  */
5759024Sobrien/* ??? The default value should be V8, but sparclite support was added
5859024Sobrien   by making it the default.  GCC now passes -Asparclite, so maybe sometime in
5959024Sobrien   the future we can set this to V8.  */
6059024Sobrien#ifndef DEFAULT_ARCH
6159024Sobrien#define DEFAULT_ARCH "sparclite"
6259024Sobrien#endif
6359024Sobrienstatic char *default_arch = DEFAULT_ARCH;
6459024Sobrien
6559024Sobrien/* Non-zero if the initial values of `max_architecture' and `sparc_arch_size'
6659024Sobrien   have been set.  */
6759024Sobrienstatic int default_init_p;
6859024Sobrien
6959024Sobrien/* Current architecture.  We don't bump up unless necessary.  */
7059024Sobrienstatic enum sparc_opcode_arch_val current_architecture = SPARC_OPCODE_ARCH_V6;
7159024Sobrien
7259024Sobrien/* The maximum architecture level we can bump up to.
7359024Sobrien   In a 32 bit environment, don't allow bumping up to v9 by default.
7459024Sobrien   The native assembler works this way.  The user is required to pass
7559024Sobrien   an explicit argument before we'll create v9 object files.  However, if
7659024Sobrien   we don't see any v9 insns, a v8plus object file is not created.  */
7759024Sobrienstatic enum sparc_opcode_arch_val max_architecture;
7859024Sobrien
7959024Sobrien/* Either 32 or 64, selects file format.  */
8059024Sobrienstatic int sparc_arch_size;
8159024Sobrien/* Initial (default) value, recorded separately in case a user option
8259024Sobrien   changes the value before md_show_usage is called.  */
8359024Sobrienstatic int default_arch_size;
8459024Sobrien
8559024Sobrien#ifdef OBJ_ELF
8659024Sobrien/* The currently selected v9 memory model.  Currently only used for
8759024Sobrien   ELF.  */
8859024Sobrienstatic enum { MM_TSO, MM_PSO, MM_RMO } sparc_memory_model = MM_RMO;
8959024Sobrien#endif
9059024Sobrien
9159024Sobrienstatic int architecture_requested;
9259024Sobrienstatic int warn_on_bump;
9359024Sobrien
9459024Sobrien/* If warn_on_bump and the needed architecture is higher than this
9559024Sobrien   architecture, issue a warning.  */
9659024Sobrienstatic enum sparc_opcode_arch_val warn_after_architecture;
9759024Sobrien
9860484Sobrien/* Non-zero if as should generate error if an undeclared g[23] register
9960484Sobrien   has been used in -64.  */
10060484Sobrienstatic int no_undeclared_regs;
10160484Sobrien
10277298Sobrien/* Non-zero if we should try to relax jumps and calls.  */
10377298Sobrienstatic int sparc_relax;
10477298Sobrien
10559024Sobrien/* Non-zero if we are generating PIC code.  */
10659024Sobrienint sparc_pic_code;
10759024Sobrien
10859024Sobrien/* Non-zero if we should give an error when misaligned data is seen.  */
10959024Sobrienstatic int enforce_aligned_data;
11059024Sobrien
11159024Sobrienextern int target_big_endian;
11259024Sobrien
11360484Sobrienstatic int target_little_endian_data;
11460484Sobrien
11560484Sobrien/* Symbols for global registers on v9.  */
11660484Sobrienstatic symbolS *globals[8];
11760484Sobrien
118130561Sobrien/* The dwarf2 data alignment, adjusted for 32 or 64 bit.  */
119130561Sobrienint sparc_cie_data_alignment;
120130561Sobrien
12160484Sobrien/* V9 and 86x have big and little endian data, but instructions are always big
12260484Sobrien   endian.  The sparclet has bi-endian support but both data and insns have
12360484Sobrien   the same endianness.  Global `target_big_endian' is used for data.
12460484Sobrien   The following macro is used for instructions.  */
12560484Sobrien#ifndef INSN_BIG_ENDIAN
12659024Sobrien#define INSN_BIG_ENDIAN (target_big_endian \
12760484Sobrien			 || default_arch_type == sparc86x \
12859024Sobrien			 || SPARC_OPCODE_ARCH_V9_P (max_architecture))
12960484Sobrien#endif
13059024Sobrien
13177298Sobrien/* Handle of the OPCODE hash table.  */
13259024Sobrienstatic struct hash_control *op_hash;
13359024Sobrien
134218822Sdimstatic int mylog2 PARAMS ((int));
13559024Sobrienstatic void s_data1 PARAMS ((void));
13659024Sobrienstatic void s_seg PARAMS ((int));
13759024Sobrienstatic void s_proc PARAMS ((int));
13859024Sobrienstatic void s_reserve PARAMS ((int));
13959024Sobrienstatic void s_common PARAMS ((int));
14059024Sobrienstatic void s_empty PARAMS ((int));
14159024Sobrienstatic void s_uacons PARAMS ((int));
14260484Sobrienstatic void s_ncons PARAMS ((int));
143130561Sobrien#ifdef OBJ_ELF
14460484Sobrienstatic void s_register PARAMS ((int));
145130561Sobrien#endif
14659024Sobrien
14759024Sobrienconst pseudo_typeS md_pseudo_table[] =
14859024Sobrien{
14977298Sobrien  {"align", s_align_bytes, 0},	/* Defaulting is invalid (0).  */
15059024Sobrien  {"common", s_common, 0},
15159024Sobrien  {"empty", s_empty, 0},
15259024Sobrien  {"global", s_globl, 0},
15359024Sobrien  {"half", cons, 2},
15460484Sobrien  {"nword", s_ncons, 0},
15559024Sobrien  {"optim", s_ignore, 0},
15659024Sobrien  {"proc", s_proc, 0},
15759024Sobrien  {"reserve", s_reserve, 0},
15859024Sobrien  {"seg", s_seg, 0},
15959024Sobrien  {"skip", s_space, 0},
16059024Sobrien  {"word", cons, 4},
16159024Sobrien  {"xword", cons, 8},
16259024Sobrien  {"uahalf", s_uacons, 2},
16359024Sobrien  {"uaword", s_uacons, 4},
16459024Sobrien  {"uaxword", s_uacons, 8},
16559024Sobrien#ifdef OBJ_ELF
16677298Sobrien  /* These are specific to sparc/svr4.  */
16759024Sobrien  {"2byte", s_uacons, 2},
16859024Sobrien  {"4byte", s_uacons, 4},
16959024Sobrien  {"8byte", s_uacons, 8},
17060484Sobrien  {"register", s_register, 0},
17159024Sobrien#endif
17259024Sobrien  {NULL, 0, 0},
17359024Sobrien};
17459024Sobrien
17559024Sobrien/* This array holds the chars that always start a comment.  If the
17677298Sobrien   pre-processor is disabled, these aren't very useful.  */
17777298Sobrienconst char comment_chars[] = "!";	/* JF removed '|' from
17877298Sobrien                                           comment_chars.  */
17959024Sobrien
18059024Sobrien/* This array holds the chars that only start a comment at the beginning of
18159024Sobrien   a line.  If the line seems to have the form '# 123 filename'
18277298Sobrien   .line and .file directives will appear in the pre-processed output.  */
18359024Sobrien/* Note that input_file.c hand checks for '#' at the beginning of the
18459024Sobrien   first line of the input file.  This is because the compiler outputs
18577298Sobrien   #NO_APP at the beginning of its output.  */
18659024Sobrien/* Also note that comments started like this one will always
18777298Sobrien   work if '/' isn't otherwise defined.  */
18859024Sobrienconst char line_comment_chars[] = "#";
18959024Sobrien
19077298Sobrienconst char line_separator_chars[] = ";";
19159024Sobrien
19277298Sobrien/* Chars that can be used to separate mant from exp in floating point
19377298Sobrien   nums.  */
19459024Sobrienconst char EXP_CHARS[] = "eE";
19559024Sobrien
19677298Sobrien/* Chars that mean this number is a floating point constant.
19777298Sobrien   As in 0f12.456
19877298Sobrien   or    0d1.2345e12  */
19959024Sobrienconst char FLT_CHARS[] = "rRsSfFdDxXpP";
20059024Sobrien
20159024Sobrien/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
20259024Sobrien   changed in read.c.  Ideally it shouldn't have to know about it at all,
20359024Sobrien   but nothing is ideal around here.  */
20459024Sobrien
205218822Sdim#define isoctal(c)  ((unsigned) ((c) - '0') < 8)
20659024Sobrien
20759024Sobrienstruct sparc_it
20859024Sobrien  {
20959024Sobrien    char *error;
21059024Sobrien    unsigned long opcode;
21159024Sobrien    struct nlist *nlistp;
21259024Sobrien    expressionS exp;
21360484Sobrien    expressionS exp2;
21459024Sobrien    int pcrel;
21559024Sobrien    bfd_reloc_code_real_type reloc;
21659024Sobrien  };
21759024Sobrien
21859024Sobrienstruct sparc_it the_insn, set_insn;
21959024Sobrien
22059024Sobrienstatic void output_insn
22159024Sobrien  PARAMS ((const struct sparc_opcode *, struct sparc_it *));
22259024Sobrien
22359024Sobrien/* Table of arguments to -A.
22459024Sobrien   The sparc_opcode_arch table in sparc-opc.c is insufficient and incorrect
22559024Sobrien   for this use.  That table is for opcodes only.  This table is for opcodes
22659024Sobrien   and file formats.  */
22759024Sobrien
22860484Sobrienenum sparc_arch_types {v6, v7, v8, sparclet, sparclite, sparc86x, v8plus,
22977298Sobrien		       v8plusa, v9, v9a, v9b, v9_64};
23060484Sobrien
23159024Sobrienstatic struct sparc_arch {
23259024Sobrien  char *name;
23359024Sobrien  char *opcode_arch;
23460484Sobrien  enum sparc_arch_types arch_type;
23559024Sobrien  /* Default word size, as specified during configuration.
23659024Sobrien     A value of zero means can't be used to specify default architecture.  */
23759024Sobrien  int default_arch_size;
23859024Sobrien  /* Allowable arg to -A?  */
23959024Sobrien  int user_option_p;
24059024Sobrien} sparc_arch_table[] = {
24160484Sobrien  { "v6", "v6", v6, 0, 1 },
24260484Sobrien  { "v7", "v7", v7, 0, 1 },
24360484Sobrien  { "v8", "v8", v8, 32, 1 },
24460484Sobrien  { "sparclet", "sparclet", sparclet, 32, 1 },
24560484Sobrien  { "sparclite", "sparclite", sparclite, 32, 1 },
24660484Sobrien  { "sparc86x", "sparclite", sparc86x, 32, 1 },
24760484Sobrien  { "v8plus", "v9", v9, 0, 1 },
24860484Sobrien  { "v8plusa", "v9a", v9, 0, 1 },
24977298Sobrien  { "v8plusb", "v9b", v9, 0, 1 },
25060484Sobrien  { "v9", "v9", v9, 0, 1 },
25160484Sobrien  { "v9a", "v9a", v9, 0, 1 },
25277298Sobrien  { "v9b", "v9b", v9, 0, 1 },
25359024Sobrien  /* This exists to allow configure.in/Makefile.in to pass one
25459024Sobrien     value to specify both the default machine and default word size.  */
25560484Sobrien  { "v9-64", "v9", v9, 64, 0 },
25660484Sobrien  { NULL, NULL, v8, 0, 0 }
25759024Sobrien};
25859024Sobrien
25960484Sobrien/* Variant of default_arch */
26060484Sobrienstatic enum sparc_arch_types default_arch_type;
26160484Sobrien
26259024Sobrienstatic struct sparc_arch *
26359024Sobrienlookup_arch (name)
26459024Sobrien     char *name;
26559024Sobrien{
26659024Sobrien  struct sparc_arch *sa;
26759024Sobrien
26859024Sobrien  for (sa = &sparc_arch_table[0]; sa->name != NULL; sa++)
26959024Sobrien    if (strcmp (sa->name, name) == 0)
27059024Sobrien      break;
27159024Sobrien  if (sa->name == NULL)
27259024Sobrien    return NULL;
27359024Sobrien  return sa;
27459024Sobrien}
27559024Sobrien
27659024Sobrien/* Initialize the default opcode arch and word size from the default
27759024Sobrien   architecture name.  */
27859024Sobrien
27959024Sobrienstatic void
28059024Sobrieninit_default_arch ()
28159024Sobrien{
28259024Sobrien  struct sparc_arch *sa = lookup_arch (default_arch);
28359024Sobrien
28459024Sobrien  if (sa == NULL
28559024Sobrien      || sa->default_arch_size == 0)
28660484Sobrien    as_fatal (_("Invalid default architecture, broken assembler."));
28759024Sobrien
28859024Sobrien  max_architecture = sparc_opcode_lookup_arch (sa->opcode_arch);
28959024Sobrien  if (max_architecture == SPARC_OPCODE_ARCH_BAD)
29060484Sobrien    as_fatal (_("Bad opcode table, broken assembler."));
29159024Sobrien  default_arch_size = sparc_arch_size = sa->default_arch_size;
29259024Sobrien  default_init_p = 1;
29360484Sobrien  default_arch_type = sa->arch_type;
29459024Sobrien}
29559024Sobrien
29659024Sobrien/* Called by TARGET_FORMAT.  */
29759024Sobrien
29859024Sobrienconst char *
29959024Sobriensparc_target_format ()
30059024Sobrien{
30159024Sobrien  /* We don't get a chance to initialize anything before we're called,
30259024Sobrien     so handle that now.  */
30359024Sobrien  if (! default_init_p)
30459024Sobrien    init_default_arch ();
30559024Sobrien
30659024Sobrien#ifdef OBJ_AOUT
30759024Sobrien#ifdef TE_NetBSD
30859024Sobrien  return "a.out-sparc-netbsd";
30959024Sobrien#else
31059024Sobrien#ifdef TE_SPARCAOUT
31160484Sobrien  if (target_big_endian)
31260484Sobrien    return "a.out-sunos-big";
31360484Sobrien  else if (default_arch_type == sparc86x && target_little_endian_data)
31460484Sobrien    return "a.out-sunos-big";
31577298Sobrien  else
31677298Sobrien    return "a.out-sparc-little";
31759024Sobrien#else
31859024Sobrien  return "a.out-sunos-big";
31959024Sobrien#endif
32059024Sobrien#endif
32159024Sobrien#endif
32259024Sobrien
32359024Sobrien#ifdef OBJ_BOUT
32459024Sobrien  return "b.out.big";
32559024Sobrien#endif
32659024Sobrien
32759024Sobrien#ifdef OBJ_COFF
32859024Sobrien#ifdef TE_LYNX
32959024Sobrien  return "coff-sparc-lynx";
33059024Sobrien#else
33159024Sobrien  return "coff-sparc";
33259024Sobrien#endif
33359024Sobrien#endif
33459024Sobrien
335218822Sdim#ifdef TE_VXWORKS
336218822Sdim  return "elf32-sparc-vxworks";
337218822Sdim#endif
338218822Sdim
33959024Sobrien#ifdef OBJ_ELF
340218822Sdim  return sparc_arch_size == 64 ? ELF64_TARGET_FORMAT : ELF_TARGET_FORMAT;
34159024Sobrien#endif
34259024Sobrien
34359024Sobrien  abort ();
34459024Sobrien}
34559024Sobrien
34677298Sobrien/* md_parse_option
34759024Sobrien *	Invocation line includes a switch not recognized by the base assembler.
34859024Sobrien *	See if it's a processor-specific option.  These are:
34959024Sobrien *
35059024Sobrien *	-bump
35159024Sobrien *		Warn on architecture bumps.  See also -A.
35259024Sobrien *
35359024Sobrien *	-Av6, -Av7, -Av8, -Asparclite, -Asparclet
35459024Sobrien *		Standard 32 bit architectures.
35577298Sobrien *	-Av9, -Av9a, -Av9b
35659024Sobrien *		Sparc64 in either a 32 or 64 bit world (-32/-64 says which).
35759024Sobrien *		This used to only mean 64 bits, but properly specifying it
35859024Sobrien *		complicated gcc's ASM_SPECs, so now opcode selection is
35959024Sobrien *		specified orthogonally to word size (except when specifying
36059024Sobrien *		the default, but that is an internal implementation detail).
36177298Sobrien *	-Av8plus, -Av8plusa, -Av8plusb
36277298Sobrien *		Same as -Av9{,a,b}.
36377298Sobrien *	-xarch=v8plus, -xarch=v8plusa, -xarch=v8plusb
36477298Sobrien *		Same as -Av8plus{,a,b} -32, for compatibility with Sun's
36577298Sobrien *		assembler.
36677298Sobrien *	-xarch=v9, -xarch=v9a, -xarch=v9b
36777298Sobrien *		Same as -Av9{,a,b} -64, for compatibility with Sun's
36877298Sobrien *		assembler.
36959024Sobrien *
37059024Sobrien *		Select the architecture and possibly the file format.
37159024Sobrien *		Instructions or features not supported by the selected
37259024Sobrien *		architecture cause fatal errors.
37359024Sobrien *
37459024Sobrien *		The default is to start at v6, and bump the architecture up
37559024Sobrien *		whenever an instruction is seen at a higher level.  In 32 bit
37659024Sobrien *		environments, v9 is not bumped up to, the user must pass
37777298Sobrien * 		-Av8plus{,a,b}.
37859024Sobrien *
37959024Sobrien *		If -bump is specified, a warning is printing when bumping to
38059024Sobrien *		higher levels.
38159024Sobrien *
38259024Sobrien *		If an architecture is specified, all instructions must match
38359024Sobrien *		that architecture.  Any higher level instructions are flagged
38459024Sobrien *		as errors.  Note that in the 32 bit environment specifying
38559024Sobrien *		-Av8plus does not automatically create a v8plus object file, a
38659024Sobrien *		v9 insn must be seen.
38759024Sobrien *
38859024Sobrien *		If both an architecture and -bump are specified, the
38959024Sobrien *		architecture starts at the specified level, but bumps are
39059024Sobrien *		warnings.  Note that we can't set `current_architecture' to
39159024Sobrien *		the requested level in this case: in the 32 bit environment,
39259024Sobrien *		we still must avoid creating v8plus object files unless v9
39359024Sobrien * 		insns are seen.
39459024Sobrien *
39559024Sobrien * Note:
39659024Sobrien *		Bumping between incompatible architectures is always an
39759024Sobrien *		error.  For example, from sparclite to v9.
39859024Sobrien */
39959024Sobrien
40059024Sobrien#ifdef OBJ_ELF
401104834Sobrienconst char *md_shortopts = "A:K:VQ:sq";
40259024Sobrien#else
40359024Sobrien#ifdef OBJ_AOUT
404104834Sobrienconst char *md_shortopts = "A:k";
40559024Sobrien#else
406104834Sobrienconst char *md_shortopts = "A:";
40759024Sobrien#endif
40859024Sobrien#endif
40959024Sobrienstruct option md_longopts[] = {
41059024Sobrien#define OPTION_BUMP (OPTION_MD_BASE)
41159024Sobrien  {"bump", no_argument, NULL, OPTION_BUMP},
41259024Sobrien#define OPTION_SPARC (OPTION_MD_BASE + 1)
41359024Sobrien  {"sparc", no_argument, NULL, OPTION_SPARC},
41459024Sobrien#define OPTION_XARCH (OPTION_MD_BASE + 2)
41559024Sobrien  {"xarch", required_argument, NULL, OPTION_XARCH},
41659024Sobrien#ifdef OBJ_ELF
41759024Sobrien#define OPTION_32 (OPTION_MD_BASE + 3)
41859024Sobrien  {"32", no_argument, NULL, OPTION_32},
41959024Sobrien#define OPTION_64 (OPTION_MD_BASE + 4)
42059024Sobrien  {"64", no_argument, NULL, OPTION_64},
42159024Sobrien#define OPTION_TSO (OPTION_MD_BASE + 5)
42259024Sobrien  {"TSO", no_argument, NULL, OPTION_TSO},
42359024Sobrien#define OPTION_PSO (OPTION_MD_BASE + 6)
42459024Sobrien  {"PSO", no_argument, NULL, OPTION_PSO},
42559024Sobrien#define OPTION_RMO (OPTION_MD_BASE + 7)
42659024Sobrien  {"RMO", no_argument, NULL, OPTION_RMO},
42759024Sobrien#endif
42859024Sobrien#ifdef SPARC_BIENDIAN
42959024Sobrien#define OPTION_LITTLE_ENDIAN (OPTION_MD_BASE + 8)
43059024Sobrien  {"EL", no_argument, NULL, OPTION_LITTLE_ENDIAN},
43159024Sobrien#define OPTION_BIG_ENDIAN (OPTION_MD_BASE + 9)
43259024Sobrien  {"EB", no_argument, NULL, OPTION_BIG_ENDIAN},
43359024Sobrien#endif
43459024Sobrien#define OPTION_ENFORCE_ALIGNED_DATA (OPTION_MD_BASE + 10)
43559024Sobrien  {"enforce-aligned-data", no_argument, NULL, OPTION_ENFORCE_ALIGNED_DATA},
43660484Sobrien#define OPTION_LITTLE_ENDIAN_DATA (OPTION_MD_BASE + 11)
43760484Sobrien  {"little-endian-data", no_argument, NULL, OPTION_LITTLE_ENDIAN_DATA},
43860484Sobrien#ifdef OBJ_ELF
43960484Sobrien#define OPTION_NO_UNDECLARED_REGS (OPTION_MD_BASE + 12)
44060484Sobrien  {"no-undeclared-regs", no_argument, NULL, OPTION_NO_UNDECLARED_REGS},
44160484Sobrien#define OPTION_UNDECLARED_REGS (OPTION_MD_BASE + 13)
44260484Sobrien  {"undeclared-regs", no_argument, NULL, OPTION_UNDECLARED_REGS},
44360484Sobrien#endif
44477298Sobrien#define OPTION_RELAX (OPTION_MD_BASE + 14)
44577298Sobrien  {"relax", no_argument, NULL, OPTION_RELAX},
44677298Sobrien#define OPTION_NO_RELAX (OPTION_MD_BASE + 15)
44777298Sobrien  {"no-relax", no_argument, NULL, OPTION_NO_RELAX},
44859024Sobrien  {NULL, no_argument, NULL, 0}
44959024Sobrien};
45059024Sobrien
45177298Sobriensize_t md_longopts_size = sizeof (md_longopts);
45277298Sobrien
45359024Sobrienint
45459024Sobrienmd_parse_option (c, arg)
45559024Sobrien     int c;
45659024Sobrien     char *arg;
45759024Sobrien{
45859024Sobrien  /* We don't get a chance to initialize anything before we're called,
45959024Sobrien     so handle that now.  */
46059024Sobrien  if (! default_init_p)
46159024Sobrien    init_default_arch ();
46259024Sobrien
46359024Sobrien  switch (c)
46459024Sobrien    {
46559024Sobrien    case OPTION_BUMP:
46659024Sobrien      warn_on_bump = 1;
46759024Sobrien      warn_after_architecture = SPARC_OPCODE_ARCH_V6;
46859024Sobrien      break;
46959024Sobrien
47059024Sobrien    case OPTION_XARCH:
47177298Sobrien#ifdef OBJ_ELF
47277298Sobrien      if (strncmp (arg, "v9", 2) != 0)
47377298Sobrien	md_parse_option (OPTION_32, NULL);
47477298Sobrien      else
47577298Sobrien	md_parse_option (OPTION_64, NULL);
47677298Sobrien#endif
47777298Sobrien      /* Fall through.  */
47859024Sobrien
47959024Sobrien    case 'A':
48059024Sobrien      {
48159024Sobrien	struct sparc_arch *sa;
48259024Sobrien	enum sparc_opcode_arch_val opcode_arch;
48359024Sobrien
48459024Sobrien	sa = lookup_arch (arg);
48559024Sobrien	if (sa == NULL
48659024Sobrien	    || ! sa->user_option_p)
48759024Sobrien	  {
48877298Sobrien	    if (c == OPTION_XARCH)
48977298Sobrien	      as_bad (_("invalid architecture -xarch=%s"), arg);
49077298Sobrien	    else
49177298Sobrien	      as_bad (_("invalid architecture -A%s"), arg);
49259024Sobrien	    return 0;
49359024Sobrien	  }
49459024Sobrien
49559024Sobrien	opcode_arch = sparc_opcode_lookup_arch (sa->opcode_arch);
49659024Sobrien	if (opcode_arch == SPARC_OPCODE_ARCH_BAD)
49760484Sobrien	  as_fatal (_("Bad opcode table, broken assembler."));
49859024Sobrien
49959024Sobrien	max_architecture = opcode_arch;
50059024Sobrien	architecture_requested = 1;
50159024Sobrien      }
50259024Sobrien      break;
50359024Sobrien
50459024Sobrien    case OPTION_SPARC:
50559024Sobrien      /* Ignore -sparc, used by SunOS make default .s.o rule.  */
50659024Sobrien      break;
50759024Sobrien
50859024Sobrien    case OPTION_ENFORCE_ALIGNED_DATA:
50959024Sobrien      enforce_aligned_data = 1;
51059024Sobrien      break;
51159024Sobrien
51259024Sobrien#ifdef SPARC_BIENDIAN
51359024Sobrien    case OPTION_LITTLE_ENDIAN:
51459024Sobrien      target_big_endian = 0;
51560484Sobrien      if (default_arch_type != sparclet)
51660484Sobrien	as_fatal ("This target does not support -EL");
51759024Sobrien      break;
51860484Sobrien    case OPTION_LITTLE_ENDIAN_DATA:
51960484Sobrien      target_little_endian_data = 1;
52060484Sobrien      target_big_endian = 0;
52160484Sobrien      if (default_arch_type != sparc86x
52260484Sobrien	  && default_arch_type != v9)
52360484Sobrien	as_fatal ("This target does not support --little-endian-data");
52460484Sobrien      break;
52559024Sobrien    case OPTION_BIG_ENDIAN:
52659024Sobrien      target_big_endian = 1;
52759024Sobrien      break;
52859024Sobrien#endif
52959024Sobrien
53059024Sobrien#ifdef OBJ_AOUT
53159024Sobrien    case 'k':
53259024Sobrien      sparc_pic_code = 1;
53359024Sobrien      break;
53459024Sobrien#endif
53559024Sobrien
53659024Sobrien#ifdef OBJ_ELF
53759024Sobrien    case OPTION_32:
53859024Sobrien    case OPTION_64:
53959024Sobrien      {
54059024Sobrien	const char **list, **l;
54159024Sobrien
54259024Sobrien	sparc_arch_size = c == OPTION_32 ? 32 : 64;
54359024Sobrien	list = bfd_target_list ();
54459024Sobrien	for (l = list; *l != NULL; l++)
54559024Sobrien	  {
54659024Sobrien	    if (sparc_arch_size == 32)
54759024Sobrien	      {
548218822Sdim		if (CONST_STRNEQ (*l, "elf32-sparc"))
54959024Sobrien		  break;
55059024Sobrien	      }
55159024Sobrien	    else
55259024Sobrien	      {
553218822Sdim		if (CONST_STRNEQ (*l, "elf64-sparc"))
55459024Sobrien		  break;
55559024Sobrien	      }
55659024Sobrien	  }
55759024Sobrien	if (*l == NULL)
55860484Sobrien	  as_fatal (_("No compiled in support for %d bit object file format"),
55959024Sobrien		    sparc_arch_size);
56059024Sobrien	free (list);
56159024Sobrien      }
56259024Sobrien      break;
56359024Sobrien
56459024Sobrien    case OPTION_TSO:
56559024Sobrien      sparc_memory_model = MM_TSO;
56659024Sobrien      break;
56759024Sobrien
56859024Sobrien    case OPTION_PSO:
56959024Sobrien      sparc_memory_model = MM_PSO;
57059024Sobrien      break;
57159024Sobrien
57259024Sobrien    case OPTION_RMO:
57359024Sobrien      sparc_memory_model = MM_RMO;
57459024Sobrien      break;
57559024Sobrien
57659024Sobrien    case 'V':
57759024Sobrien      print_version_id ();
57859024Sobrien      break;
57959024Sobrien
58059024Sobrien    case 'Q':
58159024Sobrien      /* Qy - do emit .comment
58277298Sobrien	 Qn - do not emit .comment.  */
58359024Sobrien      break;
58459024Sobrien
58559024Sobrien    case 's':
58677298Sobrien      /* Use .stab instead of .stab.excl.  */
58759024Sobrien      break;
58859024Sobrien
58959024Sobrien    case 'q':
59077298Sobrien      /* quick -- Native assembler does fewer checks.  */
59159024Sobrien      break;
59259024Sobrien
59359024Sobrien    case 'K':
59459024Sobrien      if (strcmp (arg, "PIC") != 0)
59560484Sobrien	as_warn (_("Unrecognized option following -K"));
59659024Sobrien      else
59759024Sobrien	sparc_pic_code = 1;
59859024Sobrien      break;
59960484Sobrien
60060484Sobrien    case OPTION_NO_UNDECLARED_REGS:
60160484Sobrien      no_undeclared_regs = 1;
60260484Sobrien      break;
60360484Sobrien
60460484Sobrien    case OPTION_UNDECLARED_REGS:
60560484Sobrien      no_undeclared_regs = 0;
60660484Sobrien      break;
60759024Sobrien#endif
60859024Sobrien
60977298Sobrien    case OPTION_RELAX:
61077298Sobrien      sparc_relax = 1;
61177298Sobrien      break;
61277298Sobrien
61377298Sobrien    case OPTION_NO_RELAX:
61477298Sobrien      sparc_relax = 0;
61577298Sobrien      break;
61677298Sobrien
61759024Sobrien    default:
61859024Sobrien      return 0;
61959024Sobrien    }
62059024Sobrien
62159024Sobrien  return 1;
62259024Sobrien}
62359024Sobrien
62459024Sobrienvoid
62559024Sobrienmd_show_usage (stream)
62659024Sobrien     FILE *stream;
62759024Sobrien{
62859024Sobrien  const struct sparc_arch *arch;
62977298Sobrien  int column;
63059024Sobrien
63159024Sobrien  /* We don't get a chance to initialize anything before we're called,
63259024Sobrien     so handle that now.  */
63359024Sobrien  if (! default_init_p)
63459024Sobrien    init_default_arch ();
63559024Sobrien
63677298Sobrien  fprintf (stream, _("SPARC options:\n"));
63777298Sobrien  column = 0;
63859024Sobrien  for (arch = &sparc_arch_table[0]; arch->name; arch++)
63959024Sobrien    {
64077298Sobrien      if (!arch->user_option_p)
64177298Sobrien	continue;
64259024Sobrien      if (arch != &sparc_arch_table[0])
64359024Sobrien	fprintf (stream, " | ");
64489857Sobrien      if (column + strlen (arch->name) > 70)
64577298Sobrien	{
64677298Sobrien	  column = 0;
64777298Sobrien	  fputc ('\n', stream);
64877298Sobrien	}
64989857Sobrien      column += 5 + 2 + strlen (arch->name);
65077298Sobrien      fprintf (stream, "-A%s", arch->name);
65159024Sobrien    }
65277298Sobrien  for (arch = &sparc_arch_table[0]; arch->name; arch++)
65377298Sobrien    {
65477298Sobrien      if (!arch->user_option_p)
65577298Sobrien	continue;
65677298Sobrien      fprintf (stream, " | ");
65789857Sobrien      if (column + strlen (arch->name) > 65)
65877298Sobrien	{
65977298Sobrien	  column = 0;
66077298Sobrien	  fputc ('\n', stream);
66177298Sobrien	}
66289857Sobrien      column += 5 + 7 + strlen (arch->name);
66377298Sobrien      fprintf (stream, "-xarch=%s", arch->name);
66477298Sobrien    }
66577298Sobrien  fprintf (stream, _("\n\
66659024Sobrien			specify variant of SPARC architecture\n\
66759024Sobrien-bump			warn when assembler switches architectures\n\
66859024Sobrien-sparc			ignored\n\
66977298Sobrien--enforce-aligned-data	force .long, etc., to be aligned correctly\n\
67077298Sobrien-relax			relax jumps and branches (default)\n\
67177298Sobrien-no-relax		avoid changing any jumps and branches\n"));
67259024Sobrien#ifdef OBJ_AOUT
67360484Sobrien  fprintf (stream, _("\
67460484Sobrien-k			generate PIC\n"));
67559024Sobrien#endif
67659024Sobrien#ifdef OBJ_ELF
67760484Sobrien  fprintf (stream, _("\
67859024Sobrien-32			create 32 bit object file\n\
67960484Sobrien-64			create 64 bit object file\n"));
68060484Sobrien  fprintf (stream, _("\
68160484Sobrien			[default is %d]\n"), default_arch_size);
68260484Sobrien  fprintf (stream, _("\
68359024Sobrien-TSO			use Total Store Ordering\n\
68459024Sobrien-PSO			use Partial Store Ordering\n\
68560484Sobrien-RMO			use Relaxed Memory Ordering\n"));
68660484Sobrien  fprintf (stream, _("\
68760484Sobrien			[default is %s]\n"), (default_arch_size == 64) ? "RMO" : "TSO");
68860484Sobrien  fprintf (stream, _("\
68959024Sobrien-KPIC			generate PIC\n\
69059024Sobrien-V			print assembler version number\n\
69160484Sobrien-undeclared-regs	ignore application global register usage without\n\
69260484Sobrien			appropriate .register directive (default)\n\
69360484Sobrien-no-undeclared-regs	force error on application global register usage\n\
69460484Sobrien			without appropriate .register directive\n\
69559024Sobrien-q			ignored\n\
69659024Sobrien-Qy, -Qn		ignored\n\
69760484Sobrien-s			ignored\n"));
69859024Sobrien#endif
69959024Sobrien#ifdef SPARC_BIENDIAN
70060484Sobrien  fprintf (stream, _("\
70159024Sobrien-EL			generate code for a little endian machine\n\
70260484Sobrien-EB			generate code for a big endian machine\n\
70360484Sobrien--little-endian-data	generate code for a machine having big endian\n\
70460484Sobrien                        instructions and little endian data.\n"));
70559024Sobrien#endif
70659024Sobrien}
70759024Sobrien
70877298Sobrien/* Native operand size opcode translation.  */
70960484Sobrienstruct
71060484Sobrien  {
71160484Sobrien    char *name;
71260484Sobrien    char *name32;
71360484Sobrien    char *name64;
71460484Sobrien  } native_op_table[] =
71560484Sobrien{
71660484Sobrien  {"ldn", "ld", "ldx"},
71760484Sobrien  {"ldna", "lda", "ldxa"},
71860484Sobrien  {"stn", "st", "stx"},
71960484Sobrien  {"stna", "sta", "stxa"},
72060484Sobrien  {"slln", "sll", "sllx"},
72160484Sobrien  {"srln", "srl", "srlx"},
72260484Sobrien  {"sran", "sra", "srax"},
72360484Sobrien  {"casn", "cas", "casx"},
72460484Sobrien  {"casna", "casa", "casxa"},
72560484Sobrien  {"clrn", "clr", "clrx"},
72660484Sobrien  {NULL, NULL, NULL},
72760484Sobrien};
72860484Sobrien
729218822Sdim/* sparc64 privileged and hyperprivileged registers.  */
73059024Sobrien
73159024Sobrienstruct priv_reg_entry
73277298Sobrien{
73377298Sobrien  char *name;
73477298Sobrien  int regnum;
73577298Sobrien};
73659024Sobrien
73759024Sobrienstruct priv_reg_entry priv_reg_table[] =
73859024Sobrien{
73959024Sobrien  {"tpc", 0},
74059024Sobrien  {"tnpc", 1},
74159024Sobrien  {"tstate", 2},
74259024Sobrien  {"tt", 3},
74359024Sobrien  {"tick", 4},
74459024Sobrien  {"tba", 5},
74559024Sobrien  {"pstate", 6},
74659024Sobrien  {"tl", 7},
74759024Sobrien  {"pil", 8},
74859024Sobrien  {"cwp", 9},
74959024Sobrien  {"cansave", 10},
75059024Sobrien  {"canrestore", 11},
75159024Sobrien  {"cleanwin", 12},
75259024Sobrien  {"otherwin", 13},
75359024Sobrien  {"wstate", 14},
75459024Sobrien  {"fq", 15},
755218822Sdim  {"gl", 16},
75659024Sobrien  {"ver", 31},
75777298Sobrien  {"", -1},			/* End marker.  */
75859024Sobrien};
75959024Sobrien
760218822Sdimstruct priv_reg_entry hpriv_reg_table[] =
761218822Sdim{
762218822Sdim  {"hpstate", 0},
763218822Sdim  {"htstate", 1},
764218822Sdim  {"hintp", 3},
765218822Sdim  {"htba", 5},
766218822Sdim  {"hver", 6},
767218822Sdim  {"hstick_cmpr", 31},
768218822Sdim  {"", -1},			/* End marker.  */
769218822Sdim};
770218822Sdim
77177298Sobrien/* v9a specific asrs.  */
77259024Sobrien
77359024Sobrienstruct priv_reg_entry v9a_asr_table[] =
77459024Sobrien{
77559024Sobrien  {"tick_cmpr", 23},
77677298Sobrien  {"sys_tick_cmpr", 25},
77777298Sobrien  {"sys_tick", 24},
77859024Sobrien  {"softint", 22},
77959024Sobrien  {"set_softint", 20},
78059024Sobrien  {"pic", 17},
78159024Sobrien  {"pcr", 16},
78259024Sobrien  {"gsr", 19},
78359024Sobrien  {"dcr", 18},
78459024Sobrien  {"clear_softint", 21},
78577298Sobrien  {"", -1},			/* End marker.  */
78659024Sobrien};
78759024Sobrien
78859024Sobrienstatic int
78959024Sobriencmp_reg_entry (parg, qarg)
79059024Sobrien     const PTR parg;
79159024Sobrien     const PTR qarg;
79259024Sobrien{
79359024Sobrien  const struct priv_reg_entry *p = (const struct priv_reg_entry *) parg;
79459024Sobrien  const struct priv_reg_entry *q = (const struct priv_reg_entry *) qarg;
79559024Sobrien
79659024Sobrien  return strcmp (q->name, p->name);
79759024Sobrien}
79859024Sobrien
79959024Sobrien/* This function is called once, at assembler startup time.  It should
80077298Sobrien   set up all the tables, etc. that the MD part of the assembler will
80177298Sobrien   need.  */
80259024Sobrien
80359024Sobrienvoid
80459024Sobrienmd_begin ()
80559024Sobrien{
80659024Sobrien  register const char *retval = NULL;
80759024Sobrien  int lose = 0;
80859024Sobrien  register unsigned int i = 0;
80959024Sobrien
81059024Sobrien  /* We don't get a chance to initialize anything before md_parse_option
81159024Sobrien     is called, and it may not be called, so handle default initialization
81259024Sobrien     now if not already done.  */
81359024Sobrien  if (! default_init_p)
81459024Sobrien    init_default_arch ();
81559024Sobrien
816130561Sobrien  sparc_cie_data_alignment = sparc_arch_size == 64 ? -8 : -4;
81759024Sobrien  op_hash = hash_new ();
81859024Sobrien
81959024Sobrien  while (i < (unsigned int) sparc_num_opcodes)
82059024Sobrien    {
82159024Sobrien      const char *name = sparc_opcodes[i].name;
82259024Sobrien      retval = hash_insert (op_hash, name, (PTR) &sparc_opcodes[i]);
82359024Sobrien      if (retval != NULL)
82459024Sobrien	{
82560484Sobrien	  as_bad (_("Internal error: can't hash `%s': %s\n"),
82660484Sobrien		  sparc_opcodes[i].name, retval);
82759024Sobrien	  lose = 1;
82859024Sobrien	}
82959024Sobrien      do
83059024Sobrien	{
83159024Sobrien	  if (sparc_opcodes[i].match & sparc_opcodes[i].lose)
83259024Sobrien	    {
83360484Sobrien	      as_bad (_("Internal error: losing opcode: `%s' \"%s\"\n"),
83460484Sobrien		      sparc_opcodes[i].name, sparc_opcodes[i].args);
83559024Sobrien	      lose = 1;
83659024Sobrien	    }
83759024Sobrien	  ++i;
83859024Sobrien	}
83959024Sobrien      while (i < (unsigned int) sparc_num_opcodes
84059024Sobrien	     && !strcmp (sparc_opcodes[i].name, name));
84159024Sobrien    }
84259024Sobrien
84360484Sobrien  for (i = 0; native_op_table[i].name; i++)
84460484Sobrien    {
84560484Sobrien      const struct sparc_opcode *insn;
84677298Sobrien      char *name = ((sparc_arch_size == 32)
84777298Sobrien		    ? native_op_table[i].name32
84877298Sobrien		    : native_op_table[i].name64);
84977298Sobrien      insn = (struct sparc_opcode *) hash_find (op_hash, name);
85060484Sobrien      if (insn == NULL)
85177298Sobrien	{
85277298Sobrien	  as_bad (_("Internal error: can't find opcode `%s' for `%s'\n"),
85377298Sobrien		  name, native_op_table[i].name);
85477298Sobrien	  lose = 1;
85577298Sobrien	}
85660484Sobrien      else
85760484Sobrien	{
85860484Sobrien	  retval = hash_insert (op_hash, native_op_table[i].name, (PTR) insn);
85960484Sobrien	  if (retval != NULL)
86060484Sobrien	    {
86160484Sobrien	      as_bad (_("Internal error: can't hash `%s': %s\n"),
86260484Sobrien		      sparc_opcodes[i].name, retval);
86360484Sobrien	      lose = 1;
86460484Sobrien	    }
86560484Sobrien	}
86660484Sobrien    }
86760484Sobrien
86859024Sobrien  if (lose)
86960484Sobrien    as_fatal (_("Broken assembler.  No assembly attempted."));
87059024Sobrien
87159024Sobrien  qsort (priv_reg_table, sizeof (priv_reg_table) / sizeof (priv_reg_table[0]),
87259024Sobrien	 sizeof (priv_reg_table[0]), cmp_reg_entry);
87359024Sobrien
87459024Sobrien  /* If -bump, record the architecture level at which we start issuing
87559024Sobrien     warnings.  The behaviour is different depending upon whether an
87659024Sobrien     architecture was explicitly specified.  If it wasn't, we issue warnings
87759024Sobrien     for all upwards bumps.  If it was, we don't start issuing warnings until
87859024Sobrien     we need to bump beyond the requested architecture or when we bump between
87959024Sobrien     conflicting architectures.  */
88059024Sobrien
88159024Sobrien  if (warn_on_bump
88259024Sobrien      && architecture_requested)
88359024Sobrien    {
88459024Sobrien      /* `max_architecture' records the requested architecture.
88559024Sobrien	 Issue warnings if we go above it.  */
88659024Sobrien      warn_after_architecture = max_architecture;
88759024Sobrien
88859024Sobrien      /* Find the highest architecture level that doesn't conflict with
88959024Sobrien	 the requested one.  */
89059024Sobrien      for (max_architecture = SPARC_OPCODE_ARCH_MAX;
89159024Sobrien	   max_architecture > warn_after_architecture;
89259024Sobrien	   --max_architecture)
89359024Sobrien	if (! SPARC_OPCODE_CONFLICT_P (max_architecture,
89459024Sobrien				       warn_after_architecture))
89559024Sobrien	  break;
89659024Sobrien    }
89759024Sobrien}
89859024Sobrien
89959024Sobrien/* Called after all assembly has been done.  */
90059024Sobrien
90159024Sobrienvoid
90259024Sobriensparc_md_end ()
90359024Sobrien{
90477298Sobrien  unsigned long mach = bfd_mach_sparc;
90577298Sobrien
90659024Sobrien  if (sparc_arch_size == 64)
90777298Sobrien    switch (current_architecture)
90877298Sobrien      {
90977298Sobrien      case SPARC_OPCODE_ARCH_V9A: mach = bfd_mach_sparc_v9a; break;
91077298Sobrien      case SPARC_OPCODE_ARCH_V9B: mach = bfd_mach_sparc_v9b; break;
91177298Sobrien      default: mach = bfd_mach_sparc_v9; break;
91277298Sobrien      }
91359024Sobrien  else
91477298Sobrien    switch (current_architecture)
91577298Sobrien      {
91677298Sobrien      case SPARC_OPCODE_ARCH_SPARCLET: mach = bfd_mach_sparc_sparclet; break;
91777298Sobrien      case SPARC_OPCODE_ARCH_V9: mach = bfd_mach_sparc_v8plus; break;
91877298Sobrien      case SPARC_OPCODE_ARCH_V9A: mach = bfd_mach_sparc_v8plusa; break;
91977298Sobrien      case SPARC_OPCODE_ARCH_V9B: mach = bfd_mach_sparc_v8plusb; break;
92077298Sobrien      /* The sparclite is treated like a normal sparc.  Perhaps it shouldn't
92177298Sobrien	 be but for now it is (since that's the way it's always been
92277298Sobrien	 treated).  */
92377298Sobrien      default: break;
92477298Sobrien      }
92577298Sobrien  bfd_set_arch_mach (stdoutput, bfd_arch_sparc, mach);
92659024Sobrien}
92759024Sobrien
92859024Sobrien/* Return non-zero if VAL is in the range -(MAX+1) to MAX.  */
92959024Sobrien
93059024Sobrienstatic INLINE int
93159024Sobrienin_signed_range (val, max)
93259024Sobrien     bfd_signed_vma val, max;
93359024Sobrien{
93459024Sobrien  if (max <= 0)
93559024Sobrien    abort ();
93660484Sobrien  /* Sign-extend the value from the architecture word size, so that
93760484Sobrien     0xffffffff is always considered -1 on sparc32.  */
93860484Sobrien  if (sparc_arch_size == 32)
93960484Sobrien    {
94077298Sobrien      bfd_signed_vma sign = (bfd_signed_vma) 1 << 31;
94191041Sobrien      val = ((val & U0xffffffff) ^ sign) - sign;
94260484Sobrien    }
94359024Sobrien  if (val > max)
94459024Sobrien    return 0;
94559024Sobrien  if (val < ~max)
94659024Sobrien    return 0;
94759024Sobrien  return 1;
94859024Sobrien}
94959024Sobrien
95059024Sobrien/* Return non-zero if VAL is in the range 0 to MAX.  */
95159024Sobrien
95259024Sobrienstatic INLINE int
95359024Sobrienin_unsigned_range (val, max)
95459024Sobrien     bfd_vma val, max;
95559024Sobrien{
95659024Sobrien  if (val > max)
95759024Sobrien    return 0;
95859024Sobrien  return 1;
95959024Sobrien}
96059024Sobrien
96159024Sobrien/* Return non-zero if VAL is in the range -(MAX/2+1) to MAX.
96259024Sobrien   (e.g. -15 to +31).  */
96359024Sobrien
96459024Sobrienstatic INLINE int
96559024Sobrienin_bitfield_range (val, max)
96659024Sobrien     bfd_signed_vma val, max;
96759024Sobrien{
96859024Sobrien  if (max <= 0)
96959024Sobrien    abort ();
97059024Sobrien  if (val > max)
97159024Sobrien    return 0;
97259024Sobrien  if (val < ~(max >> 1))
97359024Sobrien    return 0;
97459024Sobrien  return 1;
97559024Sobrien}
97659024Sobrien
97759024Sobrienstatic int
97859024Sobriensparc_ffs (mask)
97959024Sobrien     unsigned int mask;
98059024Sobrien{
98159024Sobrien  int i;
98259024Sobrien
98359024Sobrien  if (mask == 0)
98459024Sobrien    return -1;
98559024Sobrien
98659024Sobrien  for (i = 0; (mask & 1) == 0; ++i)
98759024Sobrien    mask >>= 1;
98859024Sobrien  return i;
98959024Sobrien}
99059024Sobrien
99159024Sobrien/* Implement big shift right.  */
99259024Sobrienstatic bfd_vma
99359024SobrienBSR (val, amount)
99459024Sobrien     bfd_vma val;
99559024Sobrien     int amount;
99659024Sobrien{
99759024Sobrien  if (sizeof (bfd_vma) <= 4 && amount >= 32)
99860484Sobrien    as_fatal (_("Support for 64-bit arithmetic not compiled in."));
99959024Sobrien  return val >> amount;
100059024Sobrien}
100159024Sobrien
100259024Sobrien/* For communication between sparc_ip and get_expression.  */
100359024Sobrienstatic char *expr_end;
100459024Sobrien
100559024Sobrien/* Values for `special_case'.
100659024Sobrien   Instructions that require wierd handling because they're longer than
100759024Sobrien   4 bytes.  */
100859024Sobrien#define SPECIAL_CASE_NONE	0
100959024Sobrien#define	SPECIAL_CASE_SET	1
101059024Sobrien#define SPECIAL_CASE_SETSW	2
101159024Sobrien#define SPECIAL_CASE_SETX	3
101259024Sobrien/* FIXME: sparc-opc.c doesn't have necessary "S" trigger to enable this.  */
101359024Sobrien#define	SPECIAL_CASE_FDIV	4
101459024Sobrien
101559024Sobrien/* Bit masks of various insns.  */
101659024Sobrien#define NOP_INSN 0x01000000
101759024Sobrien#define OR_INSN 0x80100000
101860484Sobrien#define XOR_INSN 0x80180000
101959024Sobrien#define FMOVS_INSN 0x81A00020
102059024Sobrien#define SETHI_INSN 0x01000000
102159024Sobrien#define SLLX_INSN 0x81281000
102259024Sobrien#define SRA_INSN 0x81380000
102359024Sobrien
102459024Sobrien/* The last instruction to be assembled.  */
102559024Sobrienstatic const struct sparc_opcode *last_insn;
102659024Sobrien/* The assembled opcode of `last_insn'.  */
102759024Sobrienstatic unsigned long last_opcode;
102859024Sobrien
102960484Sobrien/* Handle the set and setuw synthetic instructions.  */
103077298Sobrien
103160484Sobrienstatic void
103260484Sobriensynthetize_setuw (insn)
103360484Sobrien     const struct sparc_opcode *insn;
103460484Sobrien{
103560484Sobrien  int need_hi22_p = 0;
103660484Sobrien  int rd = (the_insn.opcode & RD (~0)) >> 25;
103760484Sobrien
103860484Sobrien  if (the_insn.exp.X_op == O_constant)
103960484Sobrien    {
104060484Sobrien      if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
104160484Sobrien	{
104277298Sobrien	  if (sizeof (offsetT) > 4
104360484Sobrien	      && (the_insn.exp.X_add_number < 0
104491041Sobrien		  || the_insn.exp.X_add_number > (offsetT) U0xffffffff))
104560484Sobrien	    as_warn (_("set: number not in 0..4294967295 range"));
104660484Sobrien	}
104760484Sobrien      else
104860484Sobrien	{
104977298Sobrien	  if (sizeof (offsetT) > 4
105091041Sobrien	      && (the_insn.exp.X_add_number < -(offsetT) U0x80000000
105191041Sobrien		  || the_insn.exp.X_add_number > (offsetT) U0xffffffff))
105260484Sobrien	    as_warn (_("set: number not in -2147483648..4294967295 range"));
105377298Sobrien	  the_insn.exp.X_add_number = (int) the_insn.exp.X_add_number;
105460484Sobrien	}
105560484Sobrien    }
105660484Sobrien
105760484Sobrien  /* See if operand is absolute and small; skip sethi if so.  */
105860484Sobrien  if (the_insn.exp.X_op != O_constant
105960484Sobrien      || the_insn.exp.X_add_number >= (1 << 12)
106060484Sobrien      || the_insn.exp.X_add_number < -(1 << 12))
106160484Sobrien    {
106260484Sobrien      the_insn.opcode = (SETHI_INSN | RD (rd)
106360484Sobrien			 | ((the_insn.exp.X_add_number >> 10)
106477298Sobrien			    & (the_insn.exp.X_op == O_constant
106577298Sobrien			       ? 0x3fffff : 0)));
106660484Sobrien      the_insn.reloc = (the_insn.exp.X_op != O_constant
106777298Sobrien			? BFD_RELOC_HI22 : BFD_RELOC_NONE);
106860484Sobrien      output_insn (insn, &the_insn);
106960484Sobrien      need_hi22_p = 1;
107060484Sobrien    }
107160484Sobrien
107260484Sobrien  /* See if operand has no low-order bits; skip OR if so.  */
107360484Sobrien  if (the_insn.exp.X_op != O_constant
107460484Sobrien      || (need_hi22_p && (the_insn.exp.X_add_number & 0x3FF) != 0)
107560484Sobrien      || ! need_hi22_p)
107660484Sobrien    {
107760484Sobrien      the_insn.opcode = (OR_INSN | (need_hi22_p ? RS1 (rd) : 0)
107860484Sobrien			 | RD (rd) | IMMED
107960484Sobrien			 | (the_insn.exp.X_add_number
108077298Sobrien			    & (the_insn.exp.X_op != O_constant
108177298Sobrien			       ? 0 : need_hi22_p ? 0x3ff : 0x1fff)));
108260484Sobrien      the_insn.reloc = (the_insn.exp.X_op != O_constant
108377298Sobrien			? BFD_RELOC_LO10 : BFD_RELOC_NONE);
108460484Sobrien      output_insn (insn, &the_insn);
108560484Sobrien    }
108660484Sobrien}
108777298Sobrien
108860484Sobrien/* Handle the setsw synthetic instruction.  */
108977298Sobrien
109060484Sobrienstatic void
109160484Sobriensynthetize_setsw (insn)
109260484Sobrien     const struct sparc_opcode *insn;
109360484Sobrien{
109460484Sobrien  int low32, rd, opc;
109560484Sobrien
109660484Sobrien  rd = (the_insn.opcode & RD (~0)) >> 25;
109760484Sobrien
109860484Sobrien  if (the_insn.exp.X_op != O_constant)
109960484Sobrien    {
110060484Sobrien      synthetize_setuw (insn);
110160484Sobrien
110260484Sobrien      /* Need to sign extend it.  */
110360484Sobrien      the_insn.opcode = (SRA_INSN | RS1 (rd) | RD (rd));
110460484Sobrien      the_insn.reloc = BFD_RELOC_NONE;
110560484Sobrien      output_insn (insn, &the_insn);
110660484Sobrien      return;
110760484Sobrien    }
110860484Sobrien
110977298Sobrien  if (sizeof (offsetT) > 4
111091041Sobrien      && (the_insn.exp.X_add_number < -(offsetT) U0x80000000
111191041Sobrien	  || the_insn.exp.X_add_number > (offsetT) U0xffffffff))
111260484Sobrien    as_warn (_("setsw: number not in -2147483648..4294967295 range"));
111360484Sobrien
111477298Sobrien  low32 = the_insn.exp.X_add_number;
111577298Sobrien
111660484Sobrien  if (low32 >= 0)
111760484Sobrien    {
111860484Sobrien      synthetize_setuw (insn);
111960484Sobrien      return;
112060484Sobrien    }
112160484Sobrien
112260484Sobrien  opc = OR_INSN;
112377298Sobrien
112460484Sobrien  the_insn.reloc = BFD_RELOC_NONE;
112560484Sobrien  /* See if operand is absolute and small; skip sethi if so.  */
112660484Sobrien  if (low32 < -(1 << 12))
112760484Sobrien    {
112860484Sobrien      the_insn.opcode = (SETHI_INSN | RD (rd)
112960484Sobrien			 | (((~the_insn.exp.X_add_number) >> 10) & 0x3fffff));
113060484Sobrien      output_insn (insn, &the_insn);
113160484Sobrien      low32 = 0x1c00 | (low32 & 0x3ff);
113260484Sobrien      opc = RS1 (rd) | XOR_INSN;
113360484Sobrien    }
113460484Sobrien
113560484Sobrien  the_insn.opcode = (opc | RD (rd) | IMMED
113660484Sobrien		     | (low32 & 0x1fff));
113760484Sobrien  output_insn (insn, &the_insn);
113860484Sobrien}
113960484Sobrien
114060484Sobrien/* Handle the setsw synthetic instruction.  */
114177298Sobrien
114260484Sobrienstatic void
114360484Sobriensynthetize_setx (insn)
114460484Sobrien     const struct sparc_opcode *insn;
114560484Sobrien{
114660484Sobrien  int upper32, lower32;
114760484Sobrien  int tmpreg = (the_insn.opcode & RS1 (~0)) >> 14;
114860484Sobrien  int dstreg = (the_insn.opcode & RD (~0)) >> 25;
114960484Sobrien  int upper_dstreg;
115060484Sobrien  int need_hh22_p = 0, need_hm10_p = 0, need_hi22_p = 0, need_lo10_p = 0;
115160484Sobrien  int need_xor10_p = 0;
115277298Sobrien
115391041Sobrien#define SIGNEXT32(x) ((((x) & U0xffffffff) ^ U0x80000000) - U0x80000000)
115460484Sobrien  lower32 = SIGNEXT32 (the_insn.exp.X_add_number);
115560484Sobrien  upper32 = SIGNEXT32 (BSR (the_insn.exp.X_add_number, 32));
115660484Sobrien#undef SIGNEXT32
115760484Sobrien
115860484Sobrien  upper_dstreg = tmpreg;
115960484Sobrien  /* The tmp reg should not be the dst reg.  */
116060484Sobrien  if (tmpreg == dstreg)
116160484Sobrien    as_warn (_("setx: temporary register same as destination register"));
116260484Sobrien
116360484Sobrien  /* ??? Obviously there are other optimizations we can do
116460484Sobrien     (e.g. sethi+shift for 0x1f0000000) and perhaps we shouldn't be
116560484Sobrien     doing some of these.  Later.  If you do change things, try to
116660484Sobrien     change all of this to be table driven as well.  */
116760484Sobrien  /* What to output depends on the number if it's constant.
116860484Sobrien     Compute that first, then output what we've decided upon.  */
116960484Sobrien  if (the_insn.exp.X_op != O_constant)
117060484Sobrien    {
117160484Sobrien      if (sparc_arch_size == 32)
117260484Sobrien	{
117360484Sobrien	  /* When arch size is 32, we want setx to be equivalent
117460484Sobrien	     to setuw for anything but constants.  */
117560484Sobrien	  the_insn.exp.X_add_number &= 0xffffffff;
117660484Sobrien	  synthetize_setuw (insn);
117760484Sobrien	  return;
117860484Sobrien	}
117960484Sobrien      need_hh22_p = need_hm10_p = need_hi22_p = need_lo10_p = 1;
118077298Sobrien      lower32 = 0;
118177298Sobrien      upper32 = 0;
118260484Sobrien    }
118360484Sobrien  else
118460484Sobrien    {
118560484Sobrien      /* Reset X_add_number, we've extracted it as upper32/lower32.
118660484Sobrien	 Otherwise fixup_segment will complain about not being able to
118760484Sobrien	 write an 8 byte number in a 4 byte field.  */
118860484Sobrien      the_insn.exp.X_add_number = 0;
118977298Sobrien
119060484Sobrien      /* Only need hh22 if `or' insn can't handle constant.  */
119160484Sobrien      if (upper32 < -(1 << 12) || upper32 >= (1 << 12))
119260484Sobrien	need_hh22_p = 1;
119377298Sobrien
119460484Sobrien      /* Does bottom part (after sethi) have bits?  */
119560484Sobrien      if ((need_hh22_p && (upper32 & 0x3ff) != 0)
119660484Sobrien	  /* No hh22, but does upper32 still have bits we can't set
119760484Sobrien	     from lower32?  */
119860484Sobrien	  || (! need_hh22_p && upper32 != 0 && upper32 != -1))
119960484Sobrien	need_hm10_p = 1;
120077298Sobrien
120160484Sobrien      /* If the lower half is all zero, we build the upper half directly
120260484Sobrien	 into the dst reg.  */
120360484Sobrien      if (lower32 != 0
120460484Sobrien	  /* Need lower half if number is zero or 0xffffffff00000000.  */
120560484Sobrien	  || (! need_hh22_p && ! need_hm10_p))
120660484Sobrien	{
120760484Sobrien	  /* No need for sethi if `or' insn can handle constant.  */
120860484Sobrien	  if (lower32 < -(1 << 12) || lower32 >= (1 << 12)
120960484Sobrien	      /* Note that we can't use a negative constant in the `or'
121060484Sobrien		 insn unless the upper 32 bits are all ones.  */
121160484Sobrien	      || (lower32 < 0 && upper32 != -1)
121260484Sobrien	      || (lower32 >= 0 && upper32 == -1))
121360484Sobrien	    need_hi22_p = 1;
121477298Sobrien
121560484Sobrien	  if (need_hi22_p && upper32 == -1)
121660484Sobrien	    need_xor10_p = 1;
121760484Sobrien
121860484Sobrien	  /* Does bottom part (after sethi) have bits?  */
121960484Sobrien	  else if ((need_hi22_p && (lower32 & 0x3ff) != 0)
122060484Sobrien		   /* No sethi.  */
122160484Sobrien		   || (! need_hi22_p && (lower32 & 0x1fff) != 0)
122260484Sobrien		   /* Need `or' if we didn't set anything else.  */
122360484Sobrien		   || (! need_hi22_p && ! need_hh22_p && ! need_hm10_p))
122460484Sobrien	    need_lo10_p = 1;
122560484Sobrien	}
122660484Sobrien      else
122760484Sobrien	/* Output directly to dst reg if lower 32 bits are all zero.  */
122860484Sobrien	upper_dstreg = dstreg;
122960484Sobrien    }
123077298Sobrien
123160484Sobrien  if (!upper_dstreg && dstreg)
123260484Sobrien    as_warn (_("setx: illegal temporary register g0"));
123360484Sobrien
123460484Sobrien  if (need_hh22_p)
123560484Sobrien    {
123660484Sobrien      the_insn.opcode = (SETHI_INSN | RD (upper_dstreg)
123760484Sobrien			 | ((upper32 >> 10) & 0x3fffff));
123860484Sobrien      the_insn.reloc = (the_insn.exp.X_op != O_constant
123960484Sobrien			? BFD_RELOC_SPARC_HH22 : BFD_RELOC_NONE);
124060484Sobrien      output_insn (insn, &the_insn);
124160484Sobrien    }
124277298Sobrien
124360484Sobrien  if (need_hi22_p)
124460484Sobrien    {
124560484Sobrien      the_insn.opcode = (SETHI_INSN | RD (dstreg)
124660484Sobrien			 | (((need_xor10_p ? ~lower32 : lower32)
124777298Sobrien			     >> 10) & 0x3fffff));
124860484Sobrien      the_insn.reloc = (the_insn.exp.X_op != O_constant
124960484Sobrien			? BFD_RELOC_SPARC_LM22 : BFD_RELOC_NONE);
125060484Sobrien      output_insn (insn, &the_insn);
125160484Sobrien    }
125260484Sobrien
125360484Sobrien  if (need_hm10_p)
125460484Sobrien    {
125560484Sobrien      the_insn.opcode = (OR_INSN
125660484Sobrien			 | (need_hh22_p ? RS1 (upper_dstreg) : 0)
125760484Sobrien			 | RD (upper_dstreg)
125860484Sobrien			 | IMMED
125960484Sobrien			 | (upper32 & (need_hh22_p ? 0x3ff : 0x1fff)));
126060484Sobrien      the_insn.reloc = (the_insn.exp.X_op != O_constant
126160484Sobrien			? BFD_RELOC_SPARC_HM10 : BFD_RELOC_NONE);
126260484Sobrien      output_insn (insn, &the_insn);
126360484Sobrien    }
126477298Sobrien
126560484Sobrien  if (need_lo10_p)
126660484Sobrien    {
126760484Sobrien      /* FIXME: One nice optimization to do here is to OR the low part
126860484Sobrien	 with the highpart if hi22 isn't needed and the low part is
126960484Sobrien	 positive.  */
127060484Sobrien      the_insn.opcode = (OR_INSN | (need_hi22_p ? RS1 (dstreg) : 0)
127160484Sobrien			 | RD (dstreg)
127260484Sobrien			 | IMMED
127360484Sobrien			 | (lower32 & (need_hi22_p ? 0x3ff : 0x1fff)));
127460484Sobrien      the_insn.reloc = (the_insn.exp.X_op != O_constant
127560484Sobrien			? BFD_RELOC_LO10 : BFD_RELOC_NONE);
127660484Sobrien      output_insn (insn, &the_insn);
127760484Sobrien    }
127877298Sobrien
127960484Sobrien  /* If we needed to build the upper part, shift it into place.  */
128060484Sobrien  if (need_hh22_p || need_hm10_p)
128160484Sobrien    {
128260484Sobrien      the_insn.opcode = (SLLX_INSN | RS1 (upper_dstreg) | RD (upper_dstreg)
128360484Sobrien			 | IMMED | 32);
128460484Sobrien      the_insn.reloc = BFD_RELOC_NONE;
128560484Sobrien      output_insn (insn, &the_insn);
128660484Sobrien    }
128777298Sobrien
128860484Sobrien  /* To get -1 in upper32, we do sethi %hi(~x), r; xor r, -0x400 | x, r.  */
128960484Sobrien  if (need_xor10_p)
129060484Sobrien    {
129160484Sobrien      the_insn.opcode = (XOR_INSN | RS1 (dstreg) | RD (dstreg) | IMMED
129260484Sobrien			 | 0x1c00 | (lower32 & 0x3ff));
129360484Sobrien      the_insn.reloc = BFD_RELOC_NONE;
129460484Sobrien      output_insn (insn, &the_insn);
129560484Sobrien    }
129660484Sobrien
129760484Sobrien  /* If we needed to build both upper and lower parts, OR them together.  */
129860484Sobrien  else if ((need_hh22_p || need_hm10_p) && (need_hi22_p || need_lo10_p))
129960484Sobrien    {
130060484Sobrien      the_insn.opcode = (OR_INSN | RS1 (dstreg) | RS2 (upper_dstreg)
130160484Sobrien			 | RD (dstreg));
130260484Sobrien      the_insn.reloc = BFD_RELOC_NONE;
130360484Sobrien      output_insn (insn, &the_insn);
130460484Sobrien    }
130560484Sobrien}
130660484Sobrien
130759024Sobrien/* Main entry point to assemble one instruction.  */
130859024Sobrien
130959024Sobrienvoid
131059024Sobrienmd_assemble (str)
131159024Sobrien     char *str;
131259024Sobrien{
131359024Sobrien  const struct sparc_opcode *insn;
131460484Sobrien  int special_case;
131559024Sobrien
131659024Sobrien  know (str);
131760484Sobrien  special_case = sparc_ip (str, &insn);
1318218822Sdim  if (insn == NULL)
1319218822Sdim    return;
132059024Sobrien
132159024Sobrien  /* We warn about attempts to put a floating point branch in a delay slot,
132259024Sobrien     unless the delay slot has been annulled.  */
1323218822Sdim  if (last_insn != NULL
132459024Sobrien      && (insn->flags & F_FBR) != 0
132559024Sobrien      && (last_insn->flags & F_DELAYED) != 0
132659024Sobrien      /* ??? This test isn't completely accurate.  We assume anything with
132759024Sobrien	 F_{UNBR,CONDBR,FBR} set is annullable.  */
132859024Sobrien      && ((last_insn->flags & (F_UNBR | F_CONDBR | F_FBR)) == 0
132959024Sobrien	  || (last_opcode & ANNUL) == 0))
133060484Sobrien    as_warn (_("FP branch in delay slot"));
133159024Sobrien
133259024Sobrien  /* SPARC before v9 requires a nop instruction between a floating
133359024Sobrien     point instruction and a floating point branch.  We insert one
133459024Sobrien     automatically, with a warning.  */
133559024Sobrien  if (max_architecture < SPARC_OPCODE_ARCH_V9
133659024Sobrien      && last_insn != NULL
133759024Sobrien      && (insn->flags & F_FBR) != 0
133859024Sobrien      && (last_insn->flags & F_FLOAT) != 0)
133959024Sobrien    {
134059024Sobrien      struct sparc_it nop_insn;
134159024Sobrien
134259024Sobrien      nop_insn.opcode = NOP_INSN;
134359024Sobrien      nop_insn.reloc = BFD_RELOC_NONE;
134459024Sobrien      output_insn (insn, &nop_insn);
134560484Sobrien      as_warn (_("FP branch preceded by FP instruction; NOP inserted"));
134659024Sobrien    }
134759024Sobrien
134859024Sobrien  switch (special_case)
134959024Sobrien    {
135059024Sobrien    case SPECIAL_CASE_NONE:
135177298Sobrien      /* Normal insn.  */
135259024Sobrien      output_insn (insn, &the_insn);
135359024Sobrien      break;
135459024Sobrien
135560484Sobrien    case SPECIAL_CASE_SETSW:
135660484Sobrien      synthetize_setsw (insn);
135760484Sobrien      break;
135877298Sobrien
135959024Sobrien    case SPECIAL_CASE_SET:
136060484Sobrien      synthetize_setuw (insn);
136160484Sobrien      break;
136259024Sobrien
136359024Sobrien    case SPECIAL_CASE_SETX:
136460484Sobrien      synthetize_setx (insn);
136560484Sobrien      break;
136677298Sobrien
136759024Sobrien    case SPECIAL_CASE_FDIV:
136859024Sobrien      {
136959024Sobrien	int rd = (the_insn.opcode >> 25) & 0x1f;
137077298Sobrien
137159024Sobrien	output_insn (insn, &the_insn);
137277298Sobrien
137359024Sobrien	/* According to information leaked from Sun, the "fdiv" instructions
137459024Sobrien	   on early SPARC machines would produce incorrect results sometimes.
137559024Sobrien	   The workaround is to add an fmovs of the destination register to
137659024Sobrien	   itself just after the instruction.  This was true on machines
137777298Sobrien	   with Weitek 1165 float chips, such as the Sun-4/260 and /280.  */
137859024Sobrien	assert (the_insn.reloc == BFD_RELOC_NONE);
137959024Sobrien	the_insn.opcode = FMOVS_INSN | rd | RD (rd);
138059024Sobrien	output_insn (insn, &the_insn);
138160484Sobrien	return;
138259024Sobrien      }
138377298Sobrien
138459024Sobrien    default:
138560484Sobrien      as_fatal (_("failed special case insn sanity check"));
138659024Sobrien    }
138759024Sobrien}
138859024Sobrien
138959024Sobrien/* Subroutine of md_assemble to do the actual parsing.  */
139059024Sobrien
139160484Sobrienstatic int
139259024Sobriensparc_ip (str, pinsn)
139359024Sobrien     char *str;
139459024Sobrien     const struct sparc_opcode **pinsn;
139559024Sobrien{
139659024Sobrien  char *error_message = "";
139759024Sobrien  char *s;
139859024Sobrien  const char *args;
139959024Sobrien  char c;
140059024Sobrien  const struct sparc_opcode *insn;
140159024Sobrien  char *argsStart;
140259024Sobrien  unsigned long opcode;
140359024Sobrien  unsigned int mask = 0;
140459024Sobrien  int match = 0;
140559024Sobrien  int comma = 0;
140659024Sobrien  int v9_arg_p;
140760484Sobrien  int special_case = SPECIAL_CASE_NONE;
140859024Sobrien
140960484Sobrien  s = str;
141089857Sobrien  if (ISLOWER (*s))
141160484Sobrien    {
141260484Sobrien      do
141360484Sobrien	++s;
141489857Sobrien      while (ISLOWER (*s) || ISDIGIT (*s));
141560484Sobrien    }
141659024Sobrien
141759024Sobrien  switch (*s)
141859024Sobrien    {
141959024Sobrien    case '\0':
142059024Sobrien      break;
142159024Sobrien
142259024Sobrien    case ',':
142359024Sobrien      comma = 1;
142477298Sobrien      /* Fall through.  */
142559024Sobrien
142659024Sobrien    case ' ':
142759024Sobrien      *s++ = '\0';
142859024Sobrien      break;
142959024Sobrien
143059024Sobrien    default:
1431218822Sdim      as_bad (_("Unknown opcode: `%s'"), str);
1432218822Sdim      *pinsn = NULL;
1433218822Sdim      return special_case;
143459024Sobrien    }
143559024Sobrien  insn = (struct sparc_opcode *) hash_find (op_hash, str);
143659024Sobrien  *pinsn = insn;
143759024Sobrien  if (insn == NULL)
143859024Sobrien    {
143960484Sobrien      as_bad (_("Unknown opcode: `%s'"), str);
144060484Sobrien      return special_case;
144159024Sobrien    }
144259024Sobrien  if (comma)
144359024Sobrien    {
144459024Sobrien      *--s = ',';
144559024Sobrien    }
144659024Sobrien
144759024Sobrien  argsStart = s;
144859024Sobrien  for (;;)
144959024Sobrien    {
145059024Sobrien      opcode = insn->match;
145159024Sobrien      memset (&the_insn, '\0', sizeof (the_insn));
145259024Sobrien      the_insn.reloc = BFD_RELOC_NONE;
145359024Sobrien      v9_arg_p = 0;
145459024Sobrien
145577298Sobrien      /* Build the opcode, checking as we go to make sure that the
145677298Sobrien         operands match.  */
145759024Sobrien      for (args = insn->args;; ++args)
145859024Sobrien	{
145959024Sobrien	  switch (*args)
146059024Sobrien	    {
146159024Sobrien	    case 'K':
146259024Sobrien	      {
146359024Sobrien		int kmask = 0;
146459024Sobrien
146559024Sobrien		/* Parse a series of masks.  */
146659024Sobrien		if (*s == '#')
146759024Sobrien		  {
146859024Sobrien		    while (*s == '#')
146959024Sobrien		      {
147059024Sobrien			int mask;
147159024Sobrien
147259024Sobrien			if (! parse_keyword_arg (sparc_encode_membar, &s,
147359024Sobrien						 &mask))
147459024Sobrien			  {
147560484Sobrien			    error_message = _(": invalid membar mask name");
147659024Sobrien			    goto error;
147759024Sobrien			  }
147859024Sobrien			kmask |= mask;
147977298Sobrien			while (*s == ' ')
148077298Sobrien			  ++s;
148159024Sobrien			if (*s == '|' || *s == '+')
148259024Sobrien			  ++s;
148377298Sobrien			while (*s == ' ')
148477298Sobrien			  ++s;
148559024Sobrien		      }
148659024Sobrien		  }
148759024Sobrien		else
148859024Sobrien		  {
148959024Sobrien		    if (! parse_const_expr_arg (&s, &kmask))
149059024Sobrien		      {
149160484Sobrien			error_message = _(": invalid membar mask expression");
149259024Sobrien			goto error;
149359024Sobrien		      }
149459024Sobrien		    if (kmask < 0 || kmask > 127)
149559024Sobrien		      {
149660484Sobrien			error_message = _(": invalid membar mask number");
149759024Sobrien			goto error;
149859024Sobrien		      }
149959024Sobrien		  }
150059024Sobrien
150159024Sobrien		opcode |= MEMBAR (kmask);
150259024Sobrien		continue;
150359024Sobrien	      }
150459024Sobrien
150577298Sobrien	    case '3':
150677298Sobrien	      {
150777298Sobrien		int smask = 0;
150877298Sobrien
150977298Sobrien		if (! parse_const_expr_arg (&s, &smask))
151077298Sobrien		  {
151177298Sobrien		    error_message = _(": invalid siam mode expression");
151277298Sobrien		    goto error;
151377298Sobrien		  }
151477298Sobrien		if (smask < 0 || smask > 7)
151577298Sobrien		  {
151677298Sobrien		    error_message = _(": invalid siam mode number");
151777298Sobrien		    goto error;
151877298Sobrien		  }
151977298Sobrien		opcode |= smask;
152077298Sobrien		continue;
152177298Sobrien	      }
152277298Sobrien
152359024Sobrien	    case '*':
152459024Sobrien	      {
152559024Sobrien		int fcn = 0;
152659024Sobrien
152759024Sobrien		/* Parse a prefetch function.  */
152859024Sobrien		if (*s == '#')
152959024Sobrien		  {
153059024Sobrien		    if (! parse_keyword_arg (sparc_encode_prefetch, &s, &fcn))
153159024Sobrien		      {
153260484Sobrien			error_message = _(": invalid prefetch function name");
153359024Sobrien			goto error;
153459024Sobrien		      }
153559024Sobrien		  }
153659024Sobrien		else
153759024Sobrien		  {
153859024Sobrien		    if (! parse_const_expr_arg (&s, &fcn))
153959024Sobrien		      {
154060484Sobrien			error_message = _(": invalid prefetch function expression");
154159024Sobrien			goto error;
154259024Sobrien		      }
154359024Sobrien		    if (fcn < 0 || fcn > 31)
154459024Sobrien		      {
154560484Sobrien			error_message = _(": invalid prefetch function number");
154659024Sobrien			goto error;
154759024Sobrien		      }
154859024Sobrien		  }
154959024Sobrien		opcode |= RD (fcn);
155059024Sobrien		continue;
155159024Sobrien	      }
155259024Sobrien
155359024Sobrien	    case '!':
155459024Sobrien	    case '?':
155559024Sobrien	      /* Parse a sparc64 privileged register.  */
155659024Sobrien	      if (*s == '%')
155759024Sobrien		{
155859024Sobrien		  struct priv_reg_entry *p = priv_reg_table;
155977298Sobrien		  unsigned int len = 9999999; /* Init to make gcc happy.  */
156059024Sobrien
156159024Sobrien		  s += 1;
156259024Sobrien		  while (p->name[0] > s[0])
156359024Sobrien		    p++;
156459024Sobrien		  while (p->name[0] == s[0])
156559024Sobrien		    {
156659024Sobrien		      len = strlen (p->name);
156759024Sobrien		      if (strncmp (p->name, s, len) == 0)
156859024Sobrien			break;
156959024Sobrien		      p++;
157059024Sobrien		    }
157159024Sobrien		  if (p->name[0] != s[0])
157259024Sobrien		    {
157360484Sobrien		      error_message = _(": unrecognizable privileged register");
157459024Sobrien		      goto error;
157559024Sobrien		    }
157659024Sobrien		  if (*args == '?')
157759024Sobrien		    opcode |= (p->regnum << 14);
157859024Sobrien		  else
157959024Sobrien		    opcode |= (p->regnum << 25);
158059024Sobrien		  s += len;
158159024Sobrien		  continue;
158259024Sobrien		}
158359024Sobrien	      else
158459024Sobrien		{
158560484Sobrien		  error_message = _(": unrecognizable privileged register");
158659024Sobrien		  goto error;
158759024Sobrien		}
158859024Sobrien
1589218822Sdim	    case '$':
1590218822Sdim	    case '%':
1591218822Sdim	      /* Parse a sparc64 hyperprivileged register.  */
1592218822Sdim	      if (*s == '%')
1593218822Sdim		{
1594218822Sdim		  struct priv_reg_entry *p = hpriv_reg_table;
1595218822Sdim		  unsigned int len = 9999999; /* Init to make gcc happy.  */
1596218822Sdim
1597218822Sdim		  s += 1;
1598218822Sdim		  while (p->name[0] > s[0])
1599218822Sdim		    p++;
1600218822Sdim		  while (p->name[0] == s[0])
1601218822Sdim		    {
1602218822Sdim		      len = strlen (p->name);
1603218822Sdim		      if (strncmp (p->name, s, len) == 0)
1604218822Sdim			break;
1605218822Sdim		      p++;
1606218822Sdim		    }
1607218822Sdim		  if (p->name[0] != s[0])
1608218822Sdim		    {
1609218822Sdim		      error_message = _(": unrecognizable hyperprivileged register");
1610218822Sdim		      goto error;
1611218822Sdim		    }
1612218822Sdim		  if (*args == '$')
1613218822Sdim		    opcode |= (p->regnum << 14);
1614218822Sdim		  else
1615218822Sdim		    opcode |= (p->regnum << 25);
1616218822Sdim		  s += len;
1617218822Sdim		  continue;
1618218822Sdim		}
1619218822Sdim	      else
1620218822Sdim		{
1621218822Sdim		  error_message = _(": unrecognizable hyperprivileged register");
1622218822Sdim		  goto error;
1623218822Sdim		}
1624218822Sdim
162559024Sobrien	    case '_':
162659024Sobrien	    case '/':
162777298Sobrien	      /* Parse a v9a/v9b ancillary state register.  */
162859024Sobrien	      if (*s == '%')
162959024Sobrien		{
163059024Sobrien		  struct priv_reg_entry *p = v9a_asr_table;
163177298Sobrien		  unsigned int len = 9999999; /* Init to make gcc happy.  */
163259024Sobrien
163359024Sobrien		  s += 1;
163459024Sobrien		  while (p->name[0] > s[0])
163559024Sobrien		    p++;
163659024Sobrien		  while (p->name[0] == s[0])
163759024Sobrien		    {
163859024Sobrien		      len = strlen (p->name);
163959024Sobrien		      if (strncmp (p->name, s, len) == 0)
164059024Sobrien			break;
164159024Sobrien		      p++;
164259024Sobrien		    }
164359024Sobrien		  if (p->name[0] != s[0])
164459024Sobrien		    {
164577298Sobrien		      error_message = _(": unrecognizable v9a or v9b ancillary state register");
164659024Sobrien		      goto error;
164759024Sobrien		    }
164859024Sobrien		  if (*args == '/' && (p->regnum == 20 || p->regnum == 21))
164959024Sobrien		    {
165060484Sobrien		      error_message = _(": rd on write only ancillary state register");
165159024Sobrien		      goto error;
165277298Sobrien		    }
165377298Sobrien		  if (p->regnum >= 24
165477298Sobrien		      && (insn->architecture
165577298Sobrien			  & SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9A)))
165677298Sobrien		    {
165777298Sobrien		      /* %sys_tick and %sys_tick_cmpr are v9bnotv9a */
165877298Sobrien		      error_message = _(": unrecognizable v9a ancillary state register");
165977298Sobrien		      goto error;
166077298Sobrien		    }
166159024Sobrien		  if (*args == '/')
166259024Sobrien		    opcode |= (p->regnum << 14);
166359024Sobrien		  else
166459024Sobrien		    opcode |= (p->regnum << 25);
166559024Sobrien		  s += len;
166659024Sobrien		  continue;
166759024Sobrien		}
166859024Sobrien	      else
166959024Sobrien		{
167077298Sobrien		  error_message = _(": unrecognizable v9a or v9b ancillary state register");
167159024Sobrien		  goto error;
167259024Sobrien		}
167359024Sobrien
167459024Sobrien	    case 'M':
167559024Sobrien	    case 'm':
167659024Sobrien	      if (strncmp (s, "%asr", 4) == 0)
167759024Sobrien		{
167859024Sobrien		  s += 4;
167959024Sobrien
168089857Sobrien		  if (ISDIGIT (*s))
168159024Sobrien		    {
168259024Sobrien		      long num = 0;
168359024Sobrien
168489857Sobrien		      while (ISDIGIT (*s))
168559024Sobrien			{
168659024Sobrien			  num = num * 10 + *s - '0';
168759024Sobrien			  ++s;
168859024Sobrien			}
168959024Sobrien
169059024Sobrien		      if (current_architecture >= SPARC_OPCODE_ARCH_V9)
169159024Sobrien			{
169259024Sobrien			  if (num < 16 || 31 < num)
169359024Sobrien			    {
169460484Sobrien			      error_message = _(": asr number must be between 16 and 31");
169559024Sobrien			      goto error;
169659024Sobrien			    }
169759024Sobrien			}
169859024Sobrien		      else
169959024Sobrien			{
170059024Sobrien			  if (num < 0 || 31 < num)
170159024Sobrien			    {
170260484Sobrien			      error_message = _(": asr number must be between 0 and 31");
170359024Sobrien			      goto error;
170459024Sobrien			    }
170559024Sobrien			}
170659024Sobrien
170759024Sobrien		      opcode |= (*args == 'M' ? RS1 (num) : RD (num));
170859024Sobrien		      continue;
170959024Sobrien		    }
171059024Sobrien		  else
171159024Sobrien		    {
171260484Sobrien		      error_message = _(": expecting %asrN");
171359024Sobrien		      goto error;
171459024Sobrien		    }
171577298Sobrien		} /* if %asr  */
171659024Sobrien	      break;
171759024Sobrien
171859024Sobrien	    case 'I':
171959024Sobrien	      the_insn.reloc = BFD_RELOC_SPARC_11;
172059024Sobrien	      goto immediate;
172159024Sobrien
172259024Sobrien	    case 'j':
172359024Sobrien	      the_insn.reloc = BFD_RELOC_SPARC_10;
172459024Sobrien	      goto immediate;
172559024Sobrien
172659024Sobrien	    case 'X':
172759024Sobrien	      /* V8 systems don't understand BFD_RELOC_SPARC_5.  */
172859024Sobrien	      if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
172959024Sobrien		the_insn.reloc = BFD_RELOC_SPARC_5;
173059024Sobrien	      else
173159024Sobrien		the_insn.reloc = BFD_RELOC_SPARC13;
173259024Sobrien	      /* These fields are unsigned, but for upward compatibility,
173359024Sobrien		 allow negative values as well.  */
173459024Sobrien	      goto immediate;
173559024Sobrien
173659024Sobrien	    case 'Y':
173759024Sobrien	      /* V8 systems don't understand BFD_RELOC_SPARC_6.  */
173859024Sobrien	      if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
173959024Sobrien		the_insn.reloc = BFD_RELOC_SPARC_6;
174059024Sobrien	      else
174159024Sobrien		the_insn.reloc = BFD_RELOC_SPARC13;
174259024Sobrien	      /* These fields are unsigned, but for upward compatibility,
174359024Sobrien		 allow negative values as well.  */
174459024Sobrien	      goto immediate;
174559024Sobrien
174659024Sobrien	    case 'k':
174759024Sobrien	      the_insn.reloc = /* RELOC_WDISP2_14 */ BFD_RELOC_SPARC_WDISP16;
174859024Sobrien	      the_insn.pcrel = 1;
174959024Sobrien	      goto immediate;
175059024Sobrien
175159024Sobrien	    case 'G':
175259024Sobrien	      the_insn.reloc = BFD_RELOC_SPARC_WDISP19;
175359024Sobrien	      the_insn.pcrel = 1;
175459024Sobrien	      goto immediate;
175559024Sobrien
175659024Sobrien	    case 'N':
175759024Sobrien	      if (*s == 'p' && s[1] == 'n')
175859024Sobrien		{
175959024Sobrien		  s += 2;
176059024Sobrien		  continue;
176159024Sobrien		}
176259024Sobrien	      break;
176359024Sobrien
176459024Sobrien	    case 'T':
176559024Sobrien	      if (*s == 'p' && s[1] == 't')
176659024Sobrien		{
176759024Sobrien		  s += 2;
176859024Sobrien		  continue;
176959024Sobrien		}
177059024Sobrien	      break;
177159024Sobrien
177259024Sobrien	    case 'z':
177359024Sobrien	      if (*s == ' ')
177459024Sobrien		{
177559024Sobrien		  ++s;
177659024Sobrien		}
177759024Sobrien	      if (strncmp (s, "%icc", 4) == 0)
177859024Sobrien		{
177959024Sobrien		  s += 4;
178059024Sobrien		  continue;
178159024Sobrien		}
178259024Sobrien	      break;
178359024Sobrien
178459024Sobrien	    case 'Z':
178559024Sobrien	      if (*s == ' ')
178659024Sobrien		{
178759024Sobrien		  ++s;
178859024Sobrien		}
178959024Sobrien	      if (strncmp (s, "%xcc", 4) == 0)
179059024Sobrien		{
179159024Sobrien		  s += 4;
179259024Sobrien		  continue;
179359024Sobrien		}
179459024Sobrien	      break;
179559024Sobrien
179659024Sobrien	    case '6':
179759024Sobrien	      if (*s == ' ')
179859024Sobrien		{
179959024Sobrien		  ++s;
180059024Sobrien		}
180159024Sobrien	      if (strncmp (s, "%fcc0", 5) == 0)
180259024Sobrien		{
180359024Sobrien		  s += 5;
180459024Sobrien		  continue;
180559024Sobrien		}
180659024Sobrien	      break;
180759024Sobrien
180859024Sobrien	    case '7':
180959024Sobrien	      if (*s == ' ')
181059024Sobrien		{
181159024Sobrien		  ++s;
181259024Sobrien		}
181359024Sobrien	      if (strncmp (s, "%fcc1", 5) == 0)
181459024Sobrien		{
181559024Sobrien		  s += 5;
181659024Sobrien		  continue;
181759024Sobrien		}
181859024Sobrien	      break;
181959024Sobrien
182059024Sobrien	    case '8':
182159024Sobrien	      if (*s == ' ')
182259024Sobrien		{
182359024Sobrien		  ++s;
182459024Sobrien		}
182559024Sobrien	      if (strncmp (s, "%fcc2", 5) == 0)
182659024Sobrien		{
182759024Sobrien		  s += 5;
182859024Sobrien		  continue;
182959024Sobrien		}
183059024Sobrien	      break;
183159024Sobrien
183259024Sobrien	    case '9':
183359024Sobrien	      if (*s == ' ')
183459024Sobrien		{
183559024Sobrien		  ++s;
183659024Sobrien		}
183759024Sobrien	      if (strncmp (s, "%fcc3", 5) == 0)
183859024Sobrien		{
183959024Sobrien		  s += 5;
184059024Sobrien		  continue;
184159024Sobrien		}
184259024Sobrien	      break;
184359024Sobrien
184459024Sobrien	    case 'P':
184559024Sobrien	      if (strncmp (s, "%pc", 3) == 0)
184659024Sobrien		{
184759024Sobrien		  s += 3;
184859024Sobrien		  continue;
184959024Sobrien		}
185059024Sobrien	      break;
185159024Sobrien
185259024Sobrien	    case 'W':
185359024Sobrien	      if (strncmp (s, "%tick", 5) == 0)
185459024Sobrien		{
185559024Sobrien		  s += 5;
185659024Sobrien		  continue;
185759024Sobrien		}
185859024Sobrien	      break;
185959024Sobrien
186077298Sobrien	    case '\0':		/* End of args.  */
1861130561Sobrien	      if (s[0] == ',' && s[1] == '%')
186259024Sobrien		{
1863218822Sdim		  static const struct tls_ops
1864218822Sdim		  {
1865130561Sobrien		    /* The name as it appears in assembler.  */
1866130561Sobrien		    char *name;
1867130561Sobrien		    /* strlen (name), precomputed for speed */
1868130561Sobrien		    int len;
1869130561Sobrien		    /* The reloc this pseudo-op translates to.  */
1870130561Sobrien		    int reloc;
1871130561Sobrien		    /* 1 if call.  */
1872130561Sobrien		    int call;
1873218822Sdim		  }
1874218822Sdim		  tls_ops[] =
1875218822Sdim		  {
1876130561Sobrien		    { "tgd_add", 7, BFD_RELOC_SPARC_TLS_GD_ADD, 0 },
1877130561Sobrien		    { "tgd_call", 8, BFD_RELOC_SPARC_TLS_GD_CALL, 1 },
1878130561Sobrien		    { "tldm_add", 8, BFD_RELOC_SPARC_TLS_LDM_ADD, 0 },
1879130561Sobrien		    { "tldm_call", 9, BFD_RELOC_SPARC_TLS_LDM_CALL, 1 },
1880130561Sobrien		    { "tldo_add", 8, BFD_RELOC_SPARC_TLS_LDO_ADD, 0 },
1881130561Sobrien		    { "tie_ldx", 7, BFD_RELOC_SPARC_TLS_IE_LDX, 0 },
1882130561Sobrien		    { "tie_ld", 6, BFD_RELOC_SPARC_TLS_IE_LD, 0 },
1883218822Sdim		    { "tie_add", 7, BFD_RELOC_SPARC_TLS_IE_ADD, 0 },
1884218822Sdim		    { NULL, 0, 0, 0 }
1885130561Sobrien		  };
1886130561Sobrien		  const struct tls_ops *o;
1887130561Sobrien		  char *s1;
1888130561Sobrien		  int npar = 0;
1889130561Sobrien
1890130561Sobrien		  for (o = tls_ops; o->name; o++)
1891130561Sobrien		    if (strncmp (s + 2, o->name, o->len) == 0)
1892130561Sobrien		      break;
1893130561Sobrien		  if (o->name == NULL)
1894130561Sobrien		    break;
1895130561Sobrien
1896130561Sobrien		  if (s[o->len + 2] != '(')
1897130561Sobrien		    {
1898130561Sobrien		      as_bad (_("Illegal operands: %%%s requires arguments in ()"), o->name);
1899130561Sobrien		      return special_case;
1900130561Sobrien		    }
1901130561Sobrien
1902130561Sobrien		  if (! o->call && the_insn.reloc != BFD_RELOC_NONE)
1903130561Sobrien		    {
1904130561Sobrien		      as_bad (_("Illegal operands: %%%s cannot be used together with other relocs in the insn ()"),
1905130561Sobrien			      o->name);
1906130561Sobrien		      return special_case;
1907130561Sobrien		    }
1908130561Sobrien
1909130561Sobrien		  if (o->call
1910130561Sobrien		      && (the_insn.reloc != BFD_RELOC_32_PCREL_S2
1911130561Sobrien			  || the_insn.exp.X_add_number != 0
1912130561Sobrien			  || the_insn.exp.X_add_symbol
1913130561Sobrien			     != symbol_find_or_make ("__tls_get_addr")))
1914130561Sobrien		    {
1915130561Sobrien		      as_bad (_("Illegal operands: %%%s can be only used with call __tls_get_addr"),
1916130561Sobrien			      o->name);
1917130561Sobrien		      return special_case;
1918130561Sobrien		    }
1919130561Sobrien
1920130561Sobrien		  the_insn.reloc = o->reloc;
1921130561Sobrien		  memset (&the_insn.exp, 0, sizeof (the_insn.exp));
1922130561Sobrien		  s += o->len + 3;
1923130561Sobrien
1924130561Sobrien		  for (s1 = s; *s1 && *s1 != ',' && *s1 != ']'; s1++)
1925130561Sobrien		    if (*s1 == '(')
1926130561Sobrien		      npar++;
1927130561Sobrien		    else if (*s1 == ')')
1928130561Sobrien		      {
1929130561Sobrien			if (!npar)
1930130561Sobrien			  break;
1931130561Sobrien			npar--;
1932130561Sobrien		      }
1933130561Sobrien
1934130561Sobrien		  if (*s1 != ')')
1935130561Sobrien		    {
1936130561Sobrien		      as_bad (_("Illegal operands: %%%s requires arguments in ()"), o->name);
1937130561Sobrien		      return special_case;
1938130561Sobrien		    }
1939130561Sobrien
1940130561Sobrien		  *s1 = '\0';
1941130561Sobrien		  (void) get_expression (s);
1942130561Sobrien		  *s1 = ')';
1943130561Sobrien		  s = s1 + 1;
194459024Sobrien		}
1945130561Sobrien	      if (*s == '\0')
1946130561Sobrien		match = 1;
194759024Sobrien	      break;
194859024Sobrien
194959024Sobrien	    case '+':
195059024Sobrien	      if (*s == '+')
195159024Sobrien		{
195259024Sobrien		  ++s;
195359024Sobrien		  continue;
195459024Sobrien		}
195559024Sobrien	      if (*s == '-')
195659024Sobrien		{
195759024Sobrien		  continue;
195859024Sobrien		}
195959024Sobrien	      break;
196059024Sobrien
196177298Sobrien	    case '[':		/* These must match exactly.  */
196259024Sobrien	    case ']':
196359024Sobrien	    case ',':
196459024Sobrien	    case ' ':
196559024Sobrien	      if (*s++ == *args)
196659024Sobrien		continue;
196759024Sobrien	      break;
196859024Sobrien
196977298Sobrien	    case '#':		/* Must be at least one digit.  */
197089857Sobrien	      if (ISDIGIT (*s++))
197159024Sobrien		{
197289857Sobrien		  while (ISDIGIT (*s))
197359024Sobrien		    {
197459024Sobrien		      ++s;
197559024Sobrien		    }
197659024Sobrien		  continue;
197759024Sobrien		}
197859024Sobrien	      break;
197959024Sobrien
198077298Sobrien	    case 'C':		/* Coprocessor state register.  */
198159024Sobrien	      if (strncmp (s, "%csr", 4) == 0)
198259024Sobrien		{
198359024Sobrien		  s += 4;
198459024Sobrien		  continue;
198559024Sobrien		}
198659024Sobrien	      break;
198759024Sobrien
198877298Sobrien	    case 'b':		/* Next operand is a coprocessor register.  */
198959024Sobrien	    case 'c':
199059024Sobrien	    case 'D':
199189857Sobrien	      if (*s++ == '%' && *s++ == 'c' && ISDIGIT (*s))
199259024Sobrien		{
199359024Sobrien		  mask = *s++;
199489857Sobrien		  if (ISDIGIT (*s))
199559024Sobrien		    {
199659024Sobrien		      mask = 10 * (mask - '0') + (*s++ - '0');
199759024Sobrien		      if (mask >= 32)
199859024Sobrien			{
199959024Sobrien			  break;
200059024Sobrien			}
200159024Sobrien		    }
200259024Sobrien		  else
200359024Sobrien		    {
200459024Sobrien		      mask -= '0';
200559024Sobrien		    }
200659024Sobrien		  switch (*args)
200759024Sobrien		    {
200859024Sobrien
200959024Sobrien		    case 'b':
201059024Sobrien		      opcode |= mask << 14;
201159024Sobrien		      continue;
201259024Sobrien
201359024Sobrien		    case 'c':
201459024Sobrien		      opcode |= mask;
201559024Sobrien		      continue;
201659024Sobrien
201759024Sobrien		    case 'D':
201859024Sobrien		      opcode |= mask << 25;
201959024Sobrien		      continue;
202059024Sobrien		    }
202159024Sobrien		}
202259024Sobrien	      break;
202359024Sobrien
202459024Sobrien	    case 'r':		/* next operand must be a register */
202559024Sobrien	    case 'O':
202659024Sobrien	    case '1':
202759024Sobrien	    case '2':
202859024Sobrien	    case 'd':
202959024Sobrien	      if (*s++ == '%')
203059024Sobrien		{
203159024Sobrien		  switch (c = *s++)
203259024Sobrien		    {
203359024Sobrien
203459024Sobrien		    case 'f':	/* frame pointer */
203559024Sobrien		      if (*s++ == 'p')
203659024Sobrien			{
203759024Sobrien			  mask = 0x1e;
203859024Sobrien			  break;
203959024Sobrien			}
204059024Sobrien		      goto error;
204159024Sobrien
204259024Sobrien		    case 'g':	/* global register */
204360484Sobrien		      c = *s++;
204460484Sobrien		      if (isoctal (c))
204559024Sobrien			{
204659024Sobrien			  mask = c - '0';
204759024Sobrien			  break;
204859024Sobrien			}
204959024Sobrien		      goto error;
205059024Sobrien
205159024Sobrien		    case 'i':	/* in register */
205260484Sobrien		      c = *s++;
205360484Sobrien		      if (isoctal (c))
205459024Sobrien			{
205559024Sobrien			  mask = c - '0' + 24;
205659024Sobrien			  break;
205759024Sobrien			}
205859024Sobrien		      goto error;
205959024Sobrien
206059024Sobrien		    case 'l':	/* local register */
206160484Sobrien		      c = *s++;
206260484Sobrien		      if (isoctal (c))
206359024Sobrien			{
206459024Sobrien			  mask = (c - '0' + 16);
206559024Sobrien			  break;
206659024Sobrien			}
206759024Sobrien		      goto error;
206859024Sobrien
206959024Sobrien		    case 'o':	/* out register */
207060484Sobrien		      c = *s++;
207160484Sobrien		      if (isoctal (c))
207259024Sobrien			{
207359024Sobrien			  mask = (c - '0' + 8);
207459024Sobrien			  break;
207559024Sobrien			}
207659024Sobrien		      goto error;
207759024Sobrien
207859024Sobrien		    case 's':	/* stack pointer */
207959024Sobrien		      if (*s++ == 'p')
208059024Sobrien			{
208159024Sobrien			  mask = 0xe;
208259024Sobrien			  break;
208359024Sobrien			}
208459024Sobrien		      goto error;
208559024Sobrien
208659024Sobrien		    case 'r':	/* any register */
208789857Sobrien		      if (!ISDIGIT ((c = *s++)))
208859024Sobrien			{
208959024Sobrien			  goto error;
209059024Sobrien			}
209159024Sobrien		      /* FALLTHROUGH */
209259024Sobrien		    case '0':
209359024Sobrien		    case '1':
209459024Sobrien		    case '2':
209559024Sobrien		    case '3':
209659024Sobrien		    case '4':
209759024Sobrien		    case '5':
209859024Sobrien		    case '6':
209959024Sobrien		    case '7':
210059024Sobrien		    case '8':
210159024Sobrien		    case '9':
210289857Sobrien		      if (ISDIGIT (*s))
210359024Sobrien			{
210459024Sobrien			  if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32)
210559024Sobrien			    {
210659024Sobrien			      goto error;
210759024Sobrien			    }
210859024Sobrien			}
210959024Sobrien		      else
211059024Sobrien			{
211159024Sobrien			  c -= '0';
211259024Sobrien			}
211359024Sobrien		      mask = c;
211459024Sobrien		      break;
211559024Sobrien
211659024Sobrien		    default:
211759024Sobrien		      goto error;
211859024Sobrien		    }
211959024Sobrien
212060484Sobrien		  if ((mask & ~1) == 2 && sparc_arch_size == 64
212177298Sobrien		      && no_undeclared_regs && ! globals[mask])
212260484Sobrien		    as_bad (_("detected global register use not covered by .register pseudo-op"));
212360484Sobrien
212459024Sobrien		  /* Got the register, now figure out where
212559024Sobrien		     it goes in the opcode.  */
212659024Sobrien		  switch (*args)
212759024Sobrien		    {
212859024Sobrien		    case '1':
212959024Sobrien		      opcode |= mask << 14;
213059024Sobrien		      continue;
213159024Sobrien
213259024Sobrien		    case '2':
213359024Sobrien		      opcode |= mask;
213459024Sobrien		      continue;
213559024Sobrien
213659024Sobrien		    case 'd':
213759024Sobrien		      opcode |= mask << 25;
213859024Sobrien		      continue;
213959024Sobrien
214059024Sobrien		    case 'r':
214159024Sobrien		      opcode |= (mask << 25) | (mask << 14);
214259024Sobrien		      continue;
214359024Sobrien
214459024Sobrien		    case 'O':
214559024Sobrien		      opcode |= (mask << 25) | (mask << 0);
214659024Sobrien		      continue;
214759024Sobrien		    }
214859024Sobrien		}
214959024Sobrien	      break;
215059024Sobrien
215159024Sobrien	    case 'e':		/* next operand is a floating point register */
215259024Sobrien	    case 'v':
215359024Sobrien	    case 'V':
215459024Sobrien
215559024Sobrien	    case 'f':
215659024Sobrien	    case 'B':
215759024Sobrien	    case 'R':
215859024Sobrien
215959024Sobrien	    case 'g':
216059024Sobrien	    case 'H':
216159024Sobrien	    case 'J':
216259024Sobrien	      {
216359024Sobrien		char format;
216459024Sobrien
216559024Sobrien		if (*s++ == '%'
216659024Sobrien		    && ((format = *s) == 'f')
216789857Sobrien		    && ISDIGIT (*++s))
216859024Sobrien		  {
216989857Sobrien		    for (mask = 0; ISDIGIT (*s); ++s)
217059024Sobrien		      {
217159024Sobrien			mask = 10 * mask + (*s - '0');
217259024Sobrien		      }		/* read the number */
217359024Sobrien
217459024Sobrien		    if ((*args == 'v'
217559024Sobrien			 || *args == 'B'
217659024Sobrien			 || *args == 'H')
217759024Sobrien			&& (mask & 1))
217859024Sobrien		      {
217959024Sobrien			break;
218059024Sobrien		      }		/* register must be even numbered */
218159024Sobrien
218259024Sobrien		    if ((*args == 'V'
218359024Sobrien			 || *args == 'R'
218459024Sobrien			 || *args == 'J')
218559024Sobrien			&& (mask & 3))
218659024Sobrien		      {
218759024Sobrien			break;
218859024Sobrien		      }		/* register must be multiple of 4 */
218959024Sobrien
219059024Sobrien		    if (mask >= 64)
219159024Sobrien		      {
219259024Sobrien			if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
219360484Sobrien			  error_message = _(": There are only 64 f registers; [0-63]");
219459024Sobrien			else
219560484Sobrien			  error_message = _(": There are only 32 f registers; [0-31]");
219659024Sobrien			goto error;
219759024Sobrien		      }	/* on error */
219859024Sobrien		    else if (mask >= 32)
219959024Sobrien		      {
220059024Sobrien			if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
220159024Sobrien			  {
2202130561Sobrien			    if (*args == 'e' || *args == 'f' || *args == 'g')
2203130561Sobrien			      {
2204130561Sobrien				error_message
2205130561Sobrien				  = _(": There are only 32 single precision f registers; [0-31]");
2206130561Sobrien				goto error;
2207130561Sobrien			      }
220859024Sobrien			    v9_arg_p = 1;
220959024Sobrien			    mask -= 31;	/* wrap high bit */
221059024Sobrien			  }
221159024Sobrien			else
221259024Sobrien			  {
221360484Sobrien			    error_message = _(": There are only 32 f registers; [0-31]");
221459024Sobrien			    goto error;
221559024Sobrien			  }
221659024Sobrien		      }
221759024Sobrien		  }
221859024Sobrien		else
221959024Sobrien		  {
222059024Sobrien		    break;
222177298Sobrien		  }	/* if not an 'f' register.  */
222259024Sobrien
222359024Sobrien		switch (*args)
222459024Sobrien		  {
222559024Sobrien		  case 'v':
222659024Sobrien		  case 'V':
222759024Sobrien		  case 'e':
222859024Sobrien		    opcode |= RS1 (mask);
222959024Sobrien		    continue;
223059024Sobrien
223159024Sobrien		  case 'f':
223259024Sobrien		  case 'B':
223359024Sobrien		  case 'R':
223459024Sobrien		    opcode |= RS2 (mask);
223559024Sobrien		    continue;
223659024Sobrien
223759024Sobrien		  case 'g':
223859024Sobrien		  case 'H':
223959024Sobrien		  case 'J':
224059024Sobrien		    opcode |= RD (mask);
224159024Sobrien		    continue;
224277298Sobrien		  }		/* Pack it in.  */
224359024Sobrien
224459024Sobrien		know (0);
224559024Sobrien		break;
224677298Sobrien	      }			/* float arg  */
224759024Sobrien
224859024Sobrien	    case 'F':
224959024Sobrien	      if (strncmp (s, "%fsr", 4) == 0)
225059024Sobrien		{
225159024Sobrien		  s += 4;
225259024Sobrien		  continue;
225359024Sobrien		}
225459024Sobrien	      break;
225559024Sobrien
225677298Sobrien	    case '0':		/* 64 bit immediate (set, setsw, setx insn)  */
225777298Sobrien	      the_insn.reloc = BFD_RELOC_NONE; /* reloc handled elsewhere  */
225859024Sobrien	      goto immediate;
225959024Sobrien
226077298Sobrien	    case 'l':		/* 22 bit PC relative immediate  */
226159024Sobrien	      the_insn.reloc = BFD_RELOC_SPARC_WDISP22;
226259024Sobrien	      the_insn.pcrel = 1;
226359024Sobrien	      goto immediate;
226459024Sobrien
226577298Sobrien	    case 'L':		/* 30 bit immediate  */
226659024Sobrien	      the_insn.reloc = BFD_RELOC_32_PCREL_S2;
226759024Sobrien	      the_insn.pcrel = 1;
226859024Sobrien	      goto immediate;
226959024Sobrien
227060484Sobrien	    case 'h':
227177298Sobrien	    case 'n':		/* 22 bit immediate  */
227259024Sobrien	      the_insn.reloc = BFD_RELOC_SPARC22;
227359024Sobrien	      goto immediate;
227459024Sobrien
227577298Sobrien	    case 'i':		/* 13 bit immediate  */
227659024Sobrien	      the_insn.reloc = BFD_RELOC_SPARC13;
227759024Sobrien
227859024Sobrien	      /* fallthrough */
227959024Sobrien
228059024Sobrien	    immediate:
228159024Sobrien	      if (*s == ' ')
228259024Sobrien		s++;
228359024Sobrien
228460484Sobrien	      {
228560484Sobrien		char *s1;
228660484Sobrien		char *op_arg = NULL;
2287218822Sdim		static expressionS op_exp;
228860484Sobrien		bfd_reloc_code_real_type old_reloc = the_insn.reloc;
228959024Sobrien
229060484Sobrien		/* Check for %hi, etc.  */
229160484Sobrien		if (*s == '%')
229260484Sobrien		  {
229360484Sobrien		    static const struct ops {
229460484Sobrien		      /* The name as it appears in assembler.  */
229560484Sobrien		      char *name;
229660484Sobrien		      /* strlen (name), precomputed for speed */
229760484Sobrien		      int len;
229860484Sobrien		      /* The reloc this pseudo-op translates to.  */
229960484Sobrien		      int reloc;
230060484Sobrien		      /* Non-zero if for v9 only.  */
230160484Sobrien		      int v9_p;
230260484Sobrien		      /* Non-zero if can be used in pc-relative contexts.  */
230360484Sobrien		      int pcrel_p;/*FIXME:wip*/
230460484Sobrien		    } ops[] = {
230560484Sobrien		      /* hix/lox must appear before hi/lo so %hix won't be
230660484Sobrien			 mistaken for %hi.  */
230760484Sobrien		      { "hix", 3, BFD_RELOC_SPARC_HIX22, 1, 0 },
230860484Sobrien		      { "lox", 3, BFD_RELOC_SPARC_LOX10, 1, 0 },
230960484Sobrien		      { "hi", 2, BFD_RELOC_HI22, 0, 1 },
231060484Sobrien		      { "lo", 2, BFD_RELOC_LO10, 0, 1 },
231160484Sobrien		      { "hh", 2, BFD_RELOC_SPARC_HH22, 1, 1 },
231260484Sobrien		      { "hm", 2, BFD_RELOC_SPARC_HM10, 1, 1 },
231360484Sobrien		      { "lm", 2, BFD_RELOC_SPARC_LM22, 1, 1 },
231460484Sobrien		      { "h44", 3, BFD_RELOC_SPARC_H44, 1, 0 },
231560484Sobrien		      { "m44", 3, BFD_RELOC_SPARC_M44, 1, 0 },
231660484Sobrien		      { "l44", 3, BFD_RELOC_SPARC_L44, 1, 0 },
231760484Sobrien		      { "uhi", 3, BFD_RELOC_SPARC_HH22, 1, 0 },
231860484Sobrien		      { "ulo", 3, BFD_RELOC_SPARC_HM10, 1, 0 },
2319130561Sobrien		      { "tgd_hi22", 8, BFD_RELOC_SPARC_TLS_GD_HI22, 0, 0 },
2320130561Sobrien		      { "tgd_lo10", 8, BFD_RELOC_SPARC_TLS_GD_LO10, 0, 0 },
2321130561Sobrien		      { "tldm_hi22", 9, BFD_RELOC_SPARC_TLS_LDM_HI22, 0, 0 },
2322130561Sobrien		      { "tldm_lo10", 9, BFD_RELOC_SPARC_TLS_LDM_LO10, 0, 0 },
2323130561Sobrien		      { "tldo_hix22", 10, BFD_RELOC_SPARC_TLS_LDO_HIX22, 0,
2324130561Sobrien									 0 },
2325130561Sobrien		      { "tldo_lox10", 10, BFD_RELOC_SPARC_TLS_LDO_LOX10, 0,
2326130561Sobrien									 0 },
2327130561Sobrien		      { "tie_hi22", 8, BFD_RELOC_SPARC_TLS_IE_HI22, 0, 0 },
2328130561Sobrien		      { "tie_lo10", 8, BFD_RELOC_SPARC_TLS_IE_LO10, 0, 0 },
2329130561Sobrien		      { "tle_hix22", 9, BFD_RELOC_SPARC_TLS_LE_HIX22, 0, 0 },
2330130561Sobrien		      { "tle_lox10", 9, BFD_RELOC_SPARC_TLS_LE_LOX10, 0, 0 },
233177298Sobrien		      { NULL, 0, 0, 0, 0 }
233260484Sobrien		    };
233360484Sobrien		    const struct ops *o;
233477298Sobrien
233560484Sobrien		    for (o = ops; o->name; o++)
233660484Sobrien		      if (strncmp (s + 1, o->name, o->len) == 0)
233760484Sobrien			break;
233860484Sobrien		    if (o->name == NULL)
233959024Sobrien		      break;
234077298Sobrien
234160484Sobrien		    if (s[o->len + 1] != '(')
234260484Sobrien		      {
234360484Sobrien			as_bad (_("Illegal operands: %%%s requires arguments in ()"), o->name);
234460484Sobrien			return special_case;
234560484Sobrien		      }
234659024Sobrien
234760484Sobrien		    op_arg = o->name;
234860484Sobrien		    the_insn.reloc = o->reloc;
234960484Sobrien		    s += o->len + 2;
235060484Sobrien		    v9_arg_p = o->v9_p;
235160484Sobrien		  }
235259024Sobrien
235360484Sobrien		/* Note that if the get_expression() fails, we will still
235460484Sobrien		   have created U entries in the symbol table for the
235560484Sobrien		   'symbols' in the input string.  Try not to create U
235660484Sobrien		   symbols for registers, etc.  */
235760484Sobrien
235859024Sobrien		/* This stuff checks to see if the expression ends in
235959024Sobrien		   +%reg.  If it does, it removes the register from
236059024Sobrien		   the expression, and re-sets 's' to point to the
236159024Sobrien		   right place.  */
236259024Sobrien
236360484Sobrien		if (op_arg)
236460484Sobrien		  {
236560484Sobrien		    int npar = 0;
236659024Sobrien
236760484Sobrien		    for (s1 = s; *s1 && *s1 != ',' && *s1 != ']'; s1++)
236860484Sobrien		      if (*s1 == '(')
236960484Sobrien			npar++;
237060484Sobrien		      else if (*s1 == ')')
237160484Sobrien			{
237260484Sobrien			  if (!npar)
237360484Sobrien			    break;
237460484Sobrien			  npar--;
237560484Sobrien			}
237660484Sobrien
237760484Sobrien		    if (*s1 != ')')
237860484Sobrien		      {
237960484Sobrien			as_bad (_("Illegal operands: %%%s requires arguments in ()"), op_arg);
238060484Sobrien			return special_case;
238160484Sobrien		      }
238277298Sobrien
238360484Sobrien		    *s1 = '\0';
238460484Sobrien		    (void) get_expression (s);
238560484Sobrien		    *s1 = ')';
238660484Sobrien		    s = s1 + 1;
238760484Sobrien		    if (*s == ',' || *s == ']' || !*s)
238860484Sobrien		      continue;
238960484Sobrien		    if (*s != '+' && *s != '-')
239060484Sobrien		      {
239160484Sobrien			as_bad (_("Illegal operands: Can't do arithmetics other than + and - involving %%%s()"), op_arg);
239260484Sobrien			return special_case;
239360484Sobrien		      }
239460484Sobrien		    *s1 = '0';
239560484Sobrien		    s = s1;
239660484Sobrien		    op_exp = the_insn.exp;
239777298Sobrien		    memset (&the_insn.exp, 0, sizeof (the_insn.exp));
239860484Sobrien		  }
239960484Sobrien
240077298Sobrien		for (s1 = s; *s1 && *s1 != ',' && *s1 != ']'; s1++)
240177298Sobrien		  ;
240259024Sobrien
240389857Sobrien		if (s1 != s && ISDIGIT (s1[-1]))
240459024Sobrien		  {
240559024Sobrien		    if (s1[-2] == '%' && s1[-3] == '+')
240660484Sobrien		      s1 -= 3;
240760484Sobrien		    else if (strchr ("goli0123456789", s1[-2]) && s1[-3] == '%' && s1[-4] == '+')
240860484Sobrien		      s1 -= 4;
240960484Sobrien		    else
241060484Sobrien		      s1 = NULL;
241160484Sobrien		    if (s1)
241259024Sobrien		      {
241359024Sobrien			*s1 = '\0';
241460484Sobrien			if (op_arg && s1 == s + 1)
241560484Sobrien			  the_insn.exp.X_op = O_absent;
241660484Sobrien			else
241760484Sobrien			  (void) get_expression (s);
241859024Sobrien			*s1 = '+';
241960484Sobrien			if (op_arg)
242060484Sobrien			  *s = ')';
242159024Sobrien			s = s1;
242259024Sobrien		      }
242360484Sobrien		  }
242460484Sobrien		else
242560484Sobrien		  s1 = NULL;
242660484Sobrien
242760484Sobrien		if (!s1)
242860484Sobrien		  {
242960484Sobrien		    (void) get_expression (s);
243060484Sobrien		    if (op_arg)
243160484Sobrien		      *s = ')';
243260484Sobrien		    s = expr_end;
243360484Sobrien		  }
243460484Sobrien
243560484Sobrien		if (op_arg)
243660484Sobrien		  {
243760484Sobrien		    the_insn.exp2 = the_insn.exp;
243860484Sobrien		    the_insn.exp = op_exp;
243960484Sobrien		    if (the_insn.exp2.X_op == O_absent)
244060484Sobrien		      the_insn.exp2.X_op = O_illegal;
244160484Sobrien		    else if (the_insn.exp.X_op == O_absent)
244259024Sobrien		      {
244360484Sobrien			the_insn.exp = the_insn.exp2;
244460484Sobrien			the_insn.exp2.X_op = O_illegal;
244559024Sobrien		      }
244660484Sobrien		    else if (the_insn.exp.X_op == O_constant)
244760484Sobrien		      {
244860484Sobrien			valueT val = the_insn.exp.X_add_number;
244960484Sobrien			switch (the_insn.reloc)
245060484Sobrien			  {
245160484Sobrien			  default:
245260484Sobrien			    break;
245360484Sobrien
245460484Sobrien			  case BFD_RELOC_SPARC_HH22:
245560484Sobrien			    val = BSR (val, 32);
245677298Sobrien			    /* Fall through.  */
245760484Sobrien
245860484Sobrien			  case BFD_RELOC_SPARC_LM22:
245960484Sobrien			  case BFD_RELOC_HI22:
246060484Sobrien			    val = (val >> 10) & 0x3fffff;
246160484Sobrien			    break;
246260484Sobrien
246360484Sobrien			  case BFD_RELOC_SPARC_HM10:
246460484Sobrien			    val = BSR (val, 32);
246577298Sobrien			    /* Fall through.  */
246660484Sobrien
246760484Sobrien			  case BFD_RELOC_LO10:
246860484Sobrien			    val &= 0x3ff;
246960484Sobrien			    break;
247060484Sobrien
247160484Sobrien			  case BFD_RELOC_SPARC_H44:
247260484Sobrien			    val >>= 22;
247360484Sobrien			    val &= 0x3fffff;
247460484Sobrien			    break;
247560484Sobrien
247660484Sobrien			  case BFD_RELOC_SPARC_M44:
247760484Sobrien			    val >>= 12;
247860484Sobrien			    val &= 0x3ff;
247960484Sobrien			    break;
248060484Sobrien
248160484Sobrien			  case BFD_RELOC_SPARC_L44:
248260484Sobrien			    val &= 0xfff;
248360484Sobrien			    break;
248460484Sobrien
248560484Sobrien			  case BFD_RELOC_SPARC_HIX22:
248677298Sobrien			    val = ~val;
248760484Sobrien			    val = (val >> 10) & 0x3fffff;
248860484Sobrien			    break;
248960484Sobrien
249060484Sobrien			  case BFD_RELOC_SPARC_LOX10:
249160484Sobrien			    val = (val & 0x3ff) | 0x1c00;
249260484Sobrien			    break;
249360484Sobrien			  }
249460484Sobrien			the_insn.exp = the_insn.exp2;
249560484Sobrien			the_insn.exp.X_add_number += val;
249660484Sobrien			the_insn.exp2.X_op = O_illegal;
249760484Sobrien			the_insn.reloc = old_reloc;
249860484Sobrien		      }
249960484Sobrien		    else if (the_insn.exp2.X_op != O_constant)
250060484Sobrien		      {
250160484Sobrien			as_bad (_("Illegal operands: Can't add non-constant expression to %%%s()"), op_arg);
250260484Sobrien			return special_case;
250360484Sobrien		      }
250460484Sobrien		    else
250560484Sobrien		      {
250660484Sobrien			if (old_reloc != BFD_RELOC_SPARC13
250760484Sobrien			    || the_insn.reloc != BFD_RELOC_LO10
250860484Sobrien			    || sparc_arch_size != 64
250960484Sobrien			    || sparc_pic_code)
251060484Sobrien			  {
251160484Sobrien			    as_bad (_("Illegal operands: Can't do arithmetics involving %%%s() of a relocatable symbol"), op_arg);
251260484Sobrien			    return special_case;
251360484Sobrien			  }
251460484Sobrien			the_insn.reloc = BFD_RELOC_SPARC_OLO10;
251560484Sobrien		      }
251659024Sobrien		  }
251759024Sobrien	      }
251859024Sobrien	      /* Check for constants that don't require emitting a reloc.  */
251959024Sobrien	      if (the_insn.exp.X_op == O_constant
252059024Sobrien		  && the_insn.exp.X_add_symbol == 0
252159024Sobrien		  && the_insn.exp.X_op_symbol == 0)
252259024Sobrien		{
252359024Sobrien		  /* For pc-relative call instructions, we reject
252459024Sobrien		     constants to get better code.  */
252559024Sobrien		  if (the_insn.pcrel
252659024Sobrien		      && the_insn.reloc == BFD_RELOC_32_PCREL_S2
252759024Sobrien		      && in_signed_range (the_insn.exp.X_add_number, 0x3fff))
252859024Sobrien		    {
252960484Sobrien		      error_message = _(": PC-relative operand can't be a constant");
253059024Sobrien		      goto error;
253159024Sobrien		    }
253259024Sobrien
2533130561Sobrien		  if (the_insn.reloc >= BFD_RELOC_SPARC_TLS_GD_HI22
2534130561Sobrien		      && the_insn.reloc <= BFD_RELOC_SPARC_TLS_TPOFF64)
2535130561Sobrien		    {
2536130561Sobrien		      error_message = _(": TLS operand can't be a constant");
2537130561Sobrien		      goto error;
2538130561Sobrien		    }
2539130561Sobrien
2540218822Sdim		  /* Constants that won't fit are checked in md_apply_fix
254159024Sobrien		     and bfd_install_relocation.
254259024Sobrien		     ??? It would be preferable to install the constants
254359024Sobrien		     into the insn here and save having to create a fixS
254459024Sobrien		     for each one.  There already exists code to handle
2545218822Sdim		     all the various cases (e.g. in md_apply_fix and
254659024Sobrien		     bfd_install_relocation) so duplicating all that code
254759024Sobrien		     here isn't right.  */
254859024Sobrien		}
254959024Sobrien
255059024Sobrien	      continue;
255159024Sobrien
255259024Sobrien	    case 'a':
255359024Sobrien	      if (*s++ == 'a')
255459024Sobrien		{
255559024Sobrien		  opcode |= ANNUL;
255659024Sobrien		  continue;
255759024Sobrien		}
255859024Sobrien	      break;
255959024Sobrien
256059024Sobrien	    case 'A':
256159024Sobrien	      {
256259024Sobrien		int asi = 0;
256359024Sobrien
256459024Sobrien		/* Parse an asi.  */
256559024Sobrien		if (*s == '#')
256659024Sobrien		  {
256759024Sobrien		    if (! parse_keyword_arg (sparc_encode_asi, &s, &asi))
256859024Sobrien		      {
256960484Sobrien			error_message = _(": invalid ASI name");
257059024Sobrien			goto error;
257159024Sobrien		      }
257259024Sobrien		  }
257359024Sobrien		else
257459024Sobrien		  {
257559024Sobrien		    if (! parse_const_expr_arg (&s, &asi))
257659024Sobrien		      {
257760484Sobrien			error_message = _(": invalid ASI expression");
257859024Sobrien			goto error;
257959024Sobrien		      }
258059024Sobrien		    if (asi < 0 || asi > 255)
258159024Sobrien		      {
258260484Sobrien			error_message = _(": invalid ASI number");
258359024Sobrien			goto error;
258459024Sobrien		      }
258559024Sobrien		  }
258659024Sobrien		opcode |= ASI (asi);
258759024Sobrien		continue;
258877298Sobrien	      }			/* Alternate space.  */
258959024Sobrien
259059024Sobrien	    case 'p':
259159024Sobrien	      if (strncmp (s, "%psr", 4) == 0)
259259024Sobrien		{
259359024Sobrien		  s += 4;
259459024Sobrien		  continue;
259559024Sobrien		}
259659024Sobrien	      break;
259759024Sobrien
259877298Sobrien	    case 'q':		/* Floating point queue.  */
259959024Sobrien	      if (strncmp (s, "%fq", 3) == 0)
260059024Sobrien		{
260159024Sobrien		  s += 3;
260259024Sobrien		  continue;
260359024Sobrien		}
260459024Sobrien	      break;
260559024Sobrien
260677298Sobrien	    case 'Q':		/* Coprocessor queue.  */
260759024Sobrien	      if (strncmp (s, "%cq", 3) == 0)
260859024Sobrien		{
260959024Sobrien		  s += 3;
261059024Sobrien		  continue;
261159024Sobrien		}
261259024Sobrien	      break;
261359024Sobrien
261459024Sobrien	    case 'S':
261559024Sobrien	      if (strcmp (str, "set") == 0
261659024Sobrien		  || strcmp (str, "setuw") == 0)
261759024Sobrien		{
261859024Sobrien		  special_case = SPECIAL_CASE_SET;
261959024Sobrien		  continue;
262059024Sobrien		}
262159024Sobrien	      else if (strcmp (str, "setsw") == 0)
262259024Sobrien		{
262359024Sobrien		  special_case = SPECIAL_CASE_SETSW;
262459024Sobrien		  continue;
262559024Sobrien		}
262659024Sobrien	      else if (strcmp (str, "setx") == 0)
262759024Sobrien		{
262859024Sobrien		  special_case = SPECIAL_CASE_SETX;
262959024Sobrien		  continue;
263059024Sobrien		}
263159024Sobrien	      else if (strncmp (str, "fdiv", 4) == 0)
263259024Sobrien		{
263359024Sobrien		  special_case = SPECIAL_CASE_FDIV;
263459024Sobrien		  continue;
263559024Sobrien		}
263659024Sobrien	      break;
263759024Sobrien
263859024Sobrien	    case 'o':
263959024Sobrien	      if (strncmp (s, "%asi", 4) != 0)
264059024Sobrien		break;
264159024Sobrien	      s += 4;
264259024Sobrien	      continue;
264359024Sobrien
264459024Sobrien	    case 's':
264559024Sobrien	      if (strncmp (s, "%fprs", 5) != 0)
264659024Sobrien		break;
264759024Sobrien	      s += 5;
264859024Sobrien	      continue;
264959024Sobrien
265059024Sobrien	    case 'E':
265159024Sobrien	      if (strncmp (s, "%ccr", 4) != 0)
265259024Sobrien		break;
265359024Sobrien	      s += 4;
265459024Sobrien	      continue;
265559024Sobrien
265659024Sobrien	    case 't':
265759024Sobrien	      if (strncmp (s, "%tbr", 4) != 0)
265859024Sobrien		break;
265959024Sobrien	      s += 4;
266059024Sobrien	      continue;
266159024Sobrien
266259024Sobrien	    case 'w':
266359024Sobrien	      if (strncmp (s, "%wim", 4) != 0)
266459024Sobrien		break;
266559024Sobrien	      s += 4;
266659024Sobrien	      continue;
266759024Sobrien
266859024Sobrien	    case 'x':
266959024Sobrien	      {
267059024Sobrien		char *push = input_line_pointer;
267159024Sobrien		expressionS e;
267259024Sobrien
267359024Sobrien		input_line_pointer = s;
267459024Sobrien		expression (&e);
267559024Sobrien		if (e.X_op == O_constant)
267659024Sobrien		  {
267759024Sobrien		    int n = e.X_add_number;
267859024Sobrien		    if (n != e.X_add_number || (n & ~0x1ff) != 0)
267960484Sobrien		      as_bad (_("OPF immediate operand out of range (0-0x1ff)"));
268059024Sobrien		    else
268159024Sobrien		      opcode |= e.X_add_number << 5;
268259024Sobrien		  }
268359024Sobrien		else
268460484Sobrien		  as_bad (_("non-immediate OPF operand, ignored"));
268559024Sobrien		s = input_line_pointer;
268659024Sobrien		input_line_pointer = push;
268759024Sobrien		continue;
268859024Sobrien	      }
268959024Sobrien
269059024Sobrien	    case 'y':
269159024Sobrien	      if (strncmp (s, "%y", 2) != 0)
269259024Sobrien		break;
269359024Sobrien	      s += 2;
269459024Sobrien	      continue;
269559024Sobrien
269659024Sobrien	    case 'u':
269759024Sobrien	    case 'U':
269859024Sobrien	      {
269959024Sobrien		/* Parse a sparclet cpreg.  */
270059024Sobrien		int cpreg;
270159024Sobrien		if (! parse_keyword_arg (sparc_encode_sparclet_cpreg, &s, &cpreg))
270259024Sobrien		  {
270360484Sobrien		    error_message = _(": invalid cpreg name");
270459024Sobrien		    goto error;
270559024Sobrien		  }
270659024Sobrien		opcode |= (*args == 'U' ? RS1 (cpreg) : RD (cpreg));
270759024Sobrien		continue;
270859024Sobrien	      }
270959024Sobrien
271059024Sobrien	    default:
271160484Sobrien	      as_fatal (_("failed sanity check."));
271277298Sobrien	    }			/* switch on arg code.  */
271359024Sobrien
271459024Sobrien	  /* Break out of for() loop.  */
271559024Sobrien	  break;
271677298Sobrien	}			/* For each arg that we expect.  */
271759024Sobrien
271859024Sobrien    error:
271959024Sobrien      if (match == 0)
272059024Sobrien	{
272177298Sobrien	  /* Args don't match.  */
272259024Sobrien	  if (&insn[1] - sparc_opcodes < sparc_num_opcodes
272359024Sobrien	      && (insn->name == insn[1].name
272459024Sobrien		  || !strcmp (insn->name, insn[1].name)))
272559024Sobrien	    {
272659024Sobrien	      ++insn;
272759024Sobrien	      s = argsStart;
272859024Sobrien	      continue;
272959024Sobrien	    }
273059024Sobrien	  else
273159024Sobrien	    {
273260484Sobrien	      as_bad (_("Illegal operands%s"), error_message);
273360484Sobrien	      return special_case;
273459024Sobrien	    }
273559024Sobrien	}
273659024Sobrien      else
273759024Sobrien	{
273877298Sobrien	  /* We have a match.  Now see if the architecture is OK.  */
273959024Sobrien	  int needed_arch_mask = insn->architecture;
274059024Sobrien
274159024Sobrien	  if (v9_arg_p)
274259024Sobrien	    {
274377298Sobrien	      needed_arch_mask &=
274477298Sobrien		~(SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9) - 1);
274577298Sobrien	      if (! needed_arch_mask)
274677298Sobrien		needed_arch_mask =
274777298Sobrien		  SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9);
274859024Sobrien	    }
274959024Sobrien
275077298Sobrien	  if (needed_arch_mask
275177298Sobrien	      & SPARC_OPCODE_SUPPORTED (current_architecture))
275277298Sobrien	    /* OK.  */
275377298Sobrien	    ;
275459024Sobrien	  /* Can we bump up the architecture?  */
275577298Sobrien	  else if (needed_arch_mask
275677298Sobrien		   & SPARC_OPCODE_SUPPORTED (max_architecture))
275759024Sobrien	    {
275859024Sobrien	      enum sparc_opcode_arch_val needed_architecture =
275959024Sobrien		sparc_ffs (SPARC_OPCODE_SUPPORTED (max_architecture)
276059024Sobrien			   & needed_arch_mask);
276159024Sobrien
276259024Sobrien	      assert (needed_architecture <= SPARC_OPCODE_ARCH_MAX);
276359024Sobrien	      if (warn_on_bump
276459024Sobrien		  && needed_architecture > warn_after_architecture)
276559024Sobrien		{
276660484Sobrien		  as_warn (_("architecture bumped from \"%s\" to \"%s\" on \"%s\""),
276759024Sobrien			   sparc_opcode_archs[current_architecture].name,
276859024Sobrien			   sparc_opcode_archs[needed_architecture].name,
276959024Sobrien			   str);
277059024Sobrien		  warn_after_architecture = needed_architecture;
277159024Sobrien		}
277259024Sobrien	      current_architecture = needed_architecture;
277359024Sobrien	    }
277459024Sobrien	  /* Conflict.  */
277559024Sobrien	  /* ??? This seems to be a bit fragile.  What if the next entry in
277659024Sobrien	     the opcode table is the one we want and it is supported?
277759024Sobrien	     It is possible to arrange the table today so that this can't
277859024Sobrien	     happen but what about tomorrow?  */
277959024Sobrien	  else
278059024Sobrien	    {
278177298Sobrien	      int arch, printed_one_p = 0;
278259024Sobrien	      char *p;
278359024Sobrien	      char required_archs[SPARC_OPCODE_ARCH_MAX * 16];
278459024Sobrien
278559024Sobrien	      /* Create a list of the architectures that support the insn.  */
278677298Sobrien	      needed_arch_mask &= ~SPARC_OPCODE_SUPPORTED (max_architecture);
278759024Sobrien	      p = required_archs;
278859024Sobrien	      arch = sparc_ffs (needed_arch_mask);
278959024Sobrien	      while ((1 << arch) <= needed_arch_mask)
279059024Sobrien		{
279159024Sobrien		  if ((1 << arch) & needed_arch_mask)
279259024Sobrien		    {
279359024Sobrien		      if (printed_one_p)
279459024Sobrien			*p++ = '|';
279559024Sobrien		      strcpy (p, sparc_opcode_archs[arch].name);
279659024Sobrien		      p += strlen (p);
279759024Sobrien		      printed_one_p = 1;
279859024Sobrien		    }
279959024Sobrien		  ++arch;
280059024Sobrien		}
280159024Sobrien
280260484Sobrien	      as_bad (_("Architecture mismatch on \"%s\"."), str);
280360484Sobrien	      as_tsktsk (_(" (Requires %s; requested architecture is %s.)"),
280459024Sobrien			 required_archs,
280559024Sobrien			 sparc_opcode_archs[max_architecture].name);
280660484Sobrien	      return special_case;
280759024Sobrien	    }
280877298Sobrien	} /* If no match.  */
280959024Sobrien
281059024Sobrien      break;
281177298Sobrien    } /* Forever looking for a match.  */
281259024Sobrien
281359024Sobrien  the_insn.opcode = opcode;
281460484Sobrien  return special_case;
281559024Sobrien}
281659024Sobrien
281759024Sobrien/* Parse an argument that can be expressed as a keyword.
281859024Sobrien   (eg: #StoreStore or %ccfr).
281959024Sobrien   The result is a boolean indicating success.
282059024Sobrien   If successful, INPUT_POINTER is updated.  */
282159024Sobrien
282259024Sobrienstatic int
282359024Sobrienparse_keyword_arg (lookup_fn, input_pointerP, valueP)
282459024Sobrien     int (*lookup_fn) PARAMS ((const char *));
282559024Sobrien     char **input_pointerP;
282659024Sobrien     int *valueP;
282759024Sobrien{
282859024Sobrien  int value;
282959024Sobrien  char c, *p, *q;
283059024Sobrien
283159024Sobrien  p = *input_pointerP;
283259024Sobrien  for (q = p + (*p == '#' || *p == '%');
283389857Sobrien       ISALNUM (*q) || *q == '_';
283459024Sobrien       ++q)
283559024Sobrien    continue;
283659024Sobrien  c = *q;
283759024Sobrien  *q = 0;
283859024Sobrien  value = (*lookup_fn) (p);
283959024Sobrien  *q = c;
284059024Sobrien  if (value == -1)
284159024Sobrien    return 0;
284259024Sobrien  *valueP = value;
284359024Sobrien  *input_pointerP = q;
284459024Sobrien  return 1;
284559024Sobrien}
284659024Sobrien
284759024Sobrien/* Parse an argument that is a constant expression.
284859024Sobrien   The result is a boolean indicating success.  */
284959024Sobrien
285059024Sobrienstatic int
285159024Sobrienparse_const_expr_arg (input_pointerP, valueP)
285259024Sobrien     char **input_pointerP;
285359024Sobrien     int *valueP;
285459024Sobrien{
285559024Sobrien  char *save = input_line_pointer;
285659024Sobrien  expressionS exp;
285759024Sobrien
285859024Sobrien  input_line_pointer = *input_pointerP;
285959024Sobrien  /* The next expression may be something other than a constant
286059024Sobrien     (say if we're not processing the right variant of the insn).
286159024Sobrien     Don't call expression unless we're sure it will succeed as it will
286259024Sobrien     signal an error (which we want to defer until later).  */
286359024Sobrien  /* FIXME: It might be better to define md_operand and have it recognize
286459024Sobrien     things like %asi, etc. but continuing that route through to the end
286559024Sobrien     is a lot of work.  */
286659024Sobrien  if (*input_line_pointer == '%')
286759024Sobrien    {
286859024Sobrien      input_line_pointer = save;
286959024Sobrien      return 0;
287059024Sobrien    }
287159024Sobrien  expression (&exp);
287259024Sobrien  *input_pointerP = input_line_pointer;
287359024Sobrien  input_line_pointer = save;
287459024Sobrien  if (exp.X_op != O_constant)
287559024Sobrien    return 0;
287659024Sobrien  *valueP = exp.X_add_number;
287759024Sobrien  return 1;
287859024Sobrien}
287959024Sobrien
288059024Sobrien/* Subroutine of sparc_ip to parse an expression.  */
288159024Sobrien
288259024Sobrienstatic int
288359024Sobrienget_expression (str)
288459024Sobrien     char *str;
288559024Sobrien{
288659024Sobrien  char *save_in;
288759024Sobrien  segT seg;
288859024Sobrien
288959024Sobrien  save_in = input_line_pointer;
289059024Sobrien  input_line_pointer = str;
289159024Sobrien  seg = expression (&the_insn.exp);
289259024Sobrien  if (seg != absolute_section
289359024Sobrien      && seg != text_section
289459024Sobrien      && seg != data_section
289559024Sobrien      && seg != bss_section
289659024Sobrien      && seg != undefined_section)
289759024Sobrien    {
289860484Sobrien      the_insn.error = _("bad segment");
289959024Sobrien      expr_end = input_line_pointer;
290059024Sobrien      input_line_pointer = save_in;
290159024Sobrien      return 1;
290259024Sobrien    }
290359024Sobrien  expr_end = input_line_pointer;
290459024Sobrien  input_line_pointer = save_in;
290559024Sobrien  return 0;
290659024Sobrien}
290759024Sobrien
290859024Sobrien/* Subroutine of md_assemble to output one insn.  */
290959024Sobrien
291059024Sobrienstatic void
291159024Sobrienoutput_insn (insn, the_insn)
291259024Sobrien     const struct sparc_opcode *insn;
291359024Sobrien     struct sparc_it *the_insn;
291459024Sobrien{
291559024Sobrien  char *toP = frag_more (4);
291659024Sobrien
291777298Sobrien  /* Put out the opcode.  */
291859024Sobrien  if (INSN_BIG_ENDIAN)
291959024Sobrien    number_to_chars_bigendian (toP, (valueT) the_insn->opcode, 4);
292059024Sobrien  else
292159024Sobrien    number_to_chars_littleendian (toP, (valueT) the_insn->opcode, 4);
292259024Sobrien
292377298Sobrien  /* Put out the symbol-dependent stuff.  */
292459024Sobrien  if (the_insn->reloc != BFD_RELOC_NONE)
292559024Sobrien    {
292677298Sobrien      fixS *fixP =  fix_new_exp (frag_now,	/* Which frag.  */
292777298Sobrien				 (toP - frag_now->fr_literal),	/* Where.  */
292877298Sobrien				 4,		/* Size.  */
292959024Sobrien				 &the_insn->exp,
293059024Sobrien				 the_insn->pcrel,
293159024Sobrien				 the_insn->reloc);
293259024Sobrien      /* Turn off overflow checking in fixup_segment.  We'll do our
2933218822Sdim	 own overflow checking in md_apply_fix.  This is necessary because
293459024Sobrien	 the insn size is 4 and fixup_segment will signal an overflow for
293559024Sobrien	 large 8 byte quantities.  */
293659024Sobrien      fixP->fx_no_overflow = 1;
293760484Sobrien      if (the_insn->reloc == BFD_RELOC_SPARC_OLO10)
293860484Sobrien	fixP->tc_fix_data = the_insn->exp2.X_add_number;
293959024Sobrien    }
294059024Sobrien
294159024Sobrien  last_insn = insn;
294259024Sobrien  last_opcode = the_insn->opcode;
294377298Sobrien
294477298Sobrien#ifdef OBJ_ELF
294577298Sobrien  dwarf2_emit_insn (4);
294677298Sobrien#endif
294759024Sobrien}
294859024Sobrien
294977298Sobrien/* This is identical to the md_atof in m68k.c.  I think this is right,
295077298Sobrien   but I'm not sure.
295159024Sobrien
295277298Sobrien   Turn a string in input_line_pointer into a floating point constant
295377298Sobrien   of type TYPE, and store the appropriate bytes in *LITP.  The number
295477298Sobrien   of LITTLENUMS emitted is stored in *SIZEP.  An error message is
295577298Sobrien   returned, or NULL on OK.  */
295659024Sobrien
295777298Sobrien/* Equal to MAX_PRECISION in atof-ieee.c.  */
295859024Sobrien#define MAX_LITTLENUMS 6
295959024Sobrien
296059024Sobrienchar *
296159024Sobrienmd_atof (type, litP, sizeP)
296259024Sobrien     char type;
296359024Sobrien     char *litP;
296459024Sobrien     int *sizeP;
296559024Sobrien{
296677298Sobrien  int i, prec;
296759024Sobrien  LITTLENUM_TYPE words[MAX_LITTLENUMS];
296859024Sobrien  char *t;
296959024Sobrien
297059024Sobrien  switch (type)
297159024Sobrien    {
297259024Sobrien    case 'f':
297359024Sobrien    case 'F':
297459024Sobrien    case 's':
297559024Sobrien    case 'S':
297659024Sobrien      prec = 2;
297759024Sobrien      break;
297859024Sobrien
297959024Sobrien    case 'd':
298059024Sobrien    case 'D':
298159024Sobrien    case 'r':
298259024Sobrien    case 'R':
298359024Sobrien      prec = 4;
298459024Sobrien      break;
298559024Sobrien
298659024Sobrien    case 'x':
298759024Sobrien    case 'X':
298859024Sobrien      prec = 6;
298959024Sobrien      break;
299059024Sobrien
299159024Sobrien    case 'p':
299259024Sobrien    case 'P':
299359024Sobrien      prec = 6;
299459024Sobrien      break;
299559024Sobrien
299659024Sobrien    default:
299759024Sobrien      *sizeP = 0;
299860484Sobrien      return _("Bad call to MD_ATOF()");
299959024Sobrien    }
300059024Sobrien
300159024Sobrien  t = atof_ieee (input_line_pointer, type, words);
300259024Sobrien  if (t)
300359024Sobrien    input_line_pointer = t;
300459024Sobrien  *sizeP = prec * sizeof (LITTLENUM_TYPE);
300559024Sobrien
300659024Sobrien  if (target_big_endian)
300759024Sobrien    {
300859024Sobrien      for (i = 0; i < prec; i++)
300959024Sobrien	{
301077298Sobrien	  md_number_to_chars (litP, (valueT) words[i],
301177298Sobrien			      sizeof (LITTLENUM_TYPE));
301259024Sobrien	  litP += sizeof (LITTLENUM_TYPE);
301359024Sobrien	}
301459024Sobrien    }
301559024Sobrien  else
301659024Sobrien    {
301759024Sobrien      for (i = prec - 1; i >= 0; i--)
301859024Sobrien	{
301977298Sobrien	  md_number_to_chars (litP, (valueT) words[i],
302077298Sobrien			      sizeof (LITTLENUM_TYPE));
302159024Sobrien	  litP += sizeof (LITTLENUM_TYPE);
302259024Sobrien	}
302359024Sobrien    }
302477298Sobrien
302559024Sobrien  return 0;
302659024Sobrien}
302759024Sobrien
302859024Sobrien/* Write a value out to the object file, using the appropriate
302959024Sobrien   endianness.  */
303059024Sobrien
303159024Sobrienvoid
303259024Sobrienmd_number_to_chars (buf, val, n)
303359024Sobrien     char *buf;
303459024Sobrien     valueT val;
303559024Sobrien     int n;
303659024Sobrien{
303759024Sobrien  if (target_big_endian)
303859024Sobrien    number_to_chars_bigendian (buf, val, n);
303960484Sobrien  else if (target_little_endian_data
304060484Sobrien	   && ((n == 4 || n == 2) && ~now_seg->flags & SEC_ALLOC))
304177298Sobrien    /* Output debug words, which are not in allocated sections, as big
304277298Sobrien       endian.  */
304360484Sobrien    number_to_chars_bigendian (buf, val, n);
304460484Sobrien  else if (target_little_endian_data || ! target_big_endian)
304559024Sobrien    number_to_chars_littleendian (buf, val, n);
304659024Sobrien}
304759024Sobrien
304859024Sobrien/* Apply a fixS to the frags, now that we know the value it ought to
304977298Sobrien   hold.  */
305059024Sobrien
305189857Sobrienvoid
3052218822Sdimmd_apply_fix (fixP, valP, segment)
305359024Sobrien     fixS *fixP;
305489857Sobrien     valueT *valP;
3055130561Sobrien     segT segment ATTRIBUTE_UNUSED;
305659024Sobrien{
305759024Sobrien  char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
305889857Sobrien  offsetT val = * (offsetT *) valP;
305959024Sobrien  long insn;
306059024Sobrien
306159024Sobrien  assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
306259024Sobrien
306377298Sobrien  fixP->fx_addnumber = val;	/* Remember value for emit_reloc.  */
306459024Sobrien
306559024Sobrien#ifdef OBJ_ELF
3066130561Sobrien  /* SPARC ELF relocations don't use an addend in the data field.  */
306759024Sobrien  if (fixP->fx_addsy != NULL)
3068218822Sdim    {
3069218822Sdim      switch (fixP->fx_r_type)
3070218822Sdim	{
3071218822Sdim	case BFD_RELOC_SPARC_TLS_GD_HI22:
3072218822Sdim	case BFD_RELOC_SPARC_TLS_GD_LO10:
3073218822Sdim	case BFD_RELOC_SPARC_TLS_GD_ADD:
3074218822Sdim	case BFD_RELOC_SPARC_TLS_GD_CALL:
3075218822Sdim	case BFD_RELOC_SPARC_TLS_LDM_HI22:
3076218822Sdim	case BFD_RELOC_SPARC_TLS_LDM_LO10:
3077218822Sdim	case BFD_RELOC_SPARC_TLS_LDM_ADD:
3078218822Sdim	case BFD_RELOC_SPARC_TLS_LDM_CALL:
3079218822Sdim	case BFD_RELOC_SPARC_TLS_LDO_HIX22:
3080218822Sdim	case BFD_RELOC_SPARC_TLS_LDO_LOX10:
3081218822Sdim	case BFD_RELOC_SPARC_TLS_LDO_ADD:
3082218822Sdim	case BFD_RELOC_SPARC_TLS_IE_HI22:
3083218822Sdim	case BFD_RELOC_SPARC_TLS_IE_LO10:
3084218822Sdim	case BFD_RELOC_SPARC_TLS_IE_LD:
3085218822Sdim	case BFD_RELOC_SPARC_TLS_IE_LDX:
3086218822Sdim	case BFD_RELOC_SPARC_TLS_IE_ADD:
3087218822Sdim	case BFD_RELOC_SPARC_TLS_LE_HIX22:
3088218822Sdim	case BFD_RELOC_SPARC_TLS_LE_LOX10:
3089218822Sdim	case BFD_RELOC_SPARC_TLS_DTPMOD32:
3090218822Sdim	case BFD_RELOC_SPARC_TLS_DTPMOD64:
3091218822Sdim	case BFD_RELOC_SPARC_TLS_DTPOFF32:
3092218822Sdim	case BFD_RELOC_SPARC_TLS_DTPOFF64:
3093218822Sdim	case BFD_RELOC_SPARC_TLS_TPOFF32:
3094218822Sdim	case BFD_RELOC_SPARC_TLS_TPOFF64:
3095218822Sdim	  S_SET_THREAD_LOCAL (fixP->fx_addsy);
3096218822Sdim
3097218822Sdim	default:
3098218822Sdim	  break;
3099218822Sdim	}
3100218822Sdim
3101218822Sdim      return;
3102218822Sdim    }
310359024Sobrien#endif
310459024Sobrien
310559024Sobrien  /* This is a hack.  There should be a better way to
310659024Sobrien     handle this.  Probably in terms of howto fields, once
310759024Sobrien     we can look at these fixups in terms of howtos.  */
310859024Sobrien  if (fixP->fx_r_type == BFD_RELOC_32_PCREL_S2 && fixP->fx_addsy)
310959024Sobrien    val += fixP->fx_where + fixP->fx_frag->fr_address;
311059024Sobrien
311159024Sobrien#ifdef OBJ_AOUT
311259024Sobrien  /* FIXME: More ridiculous gas reloc hacking.  If we are going to
311359024Sobrien     generate a reloc, then we just want to let the reloc addend set
311459024Sobrien     the value.  We do not want to also stuff the addend into the
311559024Sobrien     object file.  Including the addend in the object file works when
311659024Sobrien     doing a static link, because the linker will ignore the object
311759024Sobrien     file contents.  However, the dynamic linker does not ignore the
311859024Sobrien     object file contents.  */
311959024Sobrien  if (fixP->fx_addsy != NULL
312059024Sobrien      && fixP->fx_r_type != BFD_RELOC_32_PCREL_S2)
312159024Sobrien    val = 0;
312259024Sobrien
312359024Sobrien  /* When generating PIC code, we do not want an addend for a reloc
312459024Sobrien     against a local symbol.  We adjust fx_addnumber to cancel out the
312559024Sobrien     value already included in val, and to also cancel out the
312659024Sobrien     adjustment which bfd_install_relocation will create.  */
312759024Sobrien  if (sparc_pic_code
312859024Sobrien      && fixP->fx_r_type != BFD_RELOC_32_PCREL_S2
312959024Sobrien      && fixP->fx_addsy != NULL
313059024Sobrien      && ! S_IS_COMMON (fixP->fx_addsy)
313160484Sobrien      && symbol_section_p (fixP->fx_addsy))
313259024Sobrien    fixP->fx_addnumber -= 2 * S_GET_VALUE (fixP->fx_addsy);
313360484Sobrien
313460484Sobrien  /* When generating PIC code, we need to fiddle to get
313560484Sobrien     bfd_install_relocation to do the right thing for a PC relative
313660484Sobrien     reloc against a local symbol which we are going to keep.  */
313760484Sobrien  if (sparc_pic_code
313860484Sobrien      && fixP->fx_r_type == BFD_RELOC_32_PCREL_S2
313960484Sobrien      && fixP->fx_addsy != NULL
314060484Sobrien      && (S_IS_EXTERNAL (fixP->fx_addsy)
314160484Sobrien	  || S_IS_WEAK (fixP->fx_addsy))
314260484Sobrien      && S_IS_DEFINED (fixP->fx_addsy)
314360484Sobrien      && ! S_IS_COMMON (fixP->fx_addsy))
314460484Sobrien    {
314560484Sobrien      val = 0;
314660484Sobrien      fixP->fx_addnumber -= 2 * S_GET_VALUE (fixP->fx_addsy);
314760484Sobrien    }
314859024Sobrien#endif
314959024Sobrien
315059024Sobrien  /* If this is a data relocation, just output VAL.  */
315159024Sobrien
315278828Sobrien  if (fixP->fx_r_type == BFD_RELOC_16
315378828Sobrien      || fixP->fx_r_type == BFD_RELOC_SPARC_UA16)
315459024Sobrien    {
315559024Sobrien      md_number_to_chars (buf, val, 2);
315659024Sobrien    }
315760484Sobrien  else if (fixP->fx_r_type == BFD_RELOC_32
315878828Sobrien	   || fixP->fx_r_type == BFD_RELOC_SPARC_UA32
315960484Sobrien	   || fixP->fx_r_type == BFD_RELOC_SPARC_REV32)
316059024Sobrien    {
316159024Sobrien      md_number_to_chars (buf, val, 4);
316259024Sobrien    }
316378828Sobrien  else if (fixP->fx_r_type == BFD_RELOC_64
316478828Sobrien	   || fixP->fx_r_type == BFD_RELOC_SPARC_UA64)
316559024Sobrien    {
316659024Sobrien      md_number_to_chars (buf, val, 8);
316759024Sobrien    }
316877298Sobrien  else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
316960484Sobrien           || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
317060484Sobrien    {
317160484Sobrien      fixP->fx_done = 0;
317289857Sobrien      return;
317360484Sobrien    }
317459024Sobrien  else
317559024Sobrien    {
317659024Sobrien      /* It's a relocation against an instruction.  */
317759024Sobrien
317859024Sobrien      if (INSN_BIG_ENDIAN)
317959024Sobrien	insn = bfd_getb32 ((unsigned char *) buf);
318059024Sobrien      else
318159024Sobrien	insn = bfd_getl32 ((unsigned char *) buf);
318277298Sobrien
318359024Sobrien      switch (fixP->fx_r_type)
318459024Sobrien	{
318559024Sobrien	case BFD_RELOC_32_PCREL_S2:
318659024Sobrien	  val = val >> 2;
318759024Sobrien	  /* FIXME: This increment-by-one deserves a comment of why it's
318859024Sobrien	     being done!  */
318959024Sobrien	  if (! sparc_pic_code
319059024Sobrien	      || fixP->fx_addsy == NULL
319160484Sobrien	      || symbol_section_p (fixP->fx_addsy))
319259024Sobrien	    ++val;
319377298Sobrien
319459024Sobrien	  insn |= val & 0x3fffffff;
319577298Sobrien
319677298Sobrien	  /* See if we have a delay slot.  */
319777298Sobrien	  if (sparc_relax && fixP->fx_where + 8 <= fixP->fx_frag->fr_fix)
319877298Sobrien	    {
319977298Sobrien#define G0		0
320077298Sobrien#define O7		15
320177298Sobrien#define XCC		(2 << 20)
320277298Sobrien#define COND(x)		(((x)&0xf)<<25)
320377298Sobrien#define CONDA		COND(0x8)
320477298Sobrien#define INSN_BPA	(F2(0,1) | CONDA | BPRED | XCC)
320577298Sobrien#define INSN_BA		(F2(0,2) | CONDA)
320677298Sobrien#define INSN_OR		F3(2, 0x2, 0)
320777298Sobrien#define INSN_NOP	F2(0,4)
320877298Sobrien
320977298Sobrien	      long delay;
321077298Sobrien
321177298Sobrien	      /* If the instruction is a call with either:
321277298Sobrien		 restore
321377298Sobrien		 arithmetic instruction with rd == %o7
321477298Sobrien		 where rs1 != %o7 and rs2 if it is register != %o7
321577298Sobrien		 then we can optimize if the call destination is near
321677298Sobrien		 by changing the call into a branch always.  */
321777298Sobrien	      if (INSN_BIG_ENDIAN)
321877298Sobrien		delay = bfd_getb32 ((unsigned char *) buf + 4);
321977298Sobrien	      else
322077298Sobrien		delay = bfd_getl32 ((unsigned char *) buf + 4);
322177298Sobrien	      if ((insn & OP (~0)) != OP (1) || (delay & OP (~0)) != OP (2))
322277298Sobrien		break;
322377298Sobrien	      if ((delay & OP3 (~0)) != OP3 (0x3d) /* Restore.  */
322477298Sobrien		  && ((delay & OP3 (0x28)) != 0 /* Arithmetic.  */
322577298Sobrien		      || ((delay & RD (~0)) != RD (O7))))
322677298Sobrien		break;
322777298Sobrien	      if ((delay & RS1 (~0)) == RS1 (O7)
322877298Sobrien		  || ((delay & F3I (~0)) == 0
322977298Sobrien		      && (delay & RS2 (~0)) == RS2 (O7)))
323077298Sobrien		break;
323177298Sobrien	      /* Ensure the branch will fit into simm22.  */
323277298Sobrien	      if ((val & 0x3fe00000)
323377298Sobrien		  && (val & 0x3fe00000) != 0x3fe00000)
323477298Sobrien		break;
323577298Sobrien	      /* Check if the arch is v9 and branch will fit
323677298Sobrien		 into simm19.  */
323777298Sobrien	      if (((val & 0x3c0000) == 0
323877298Sobrien		   || (val & 0x3c0000) == 0x3c0000)
323977298Sobrien		  && (sparc_arch_size == 64
324077298Sobrien		      || current_architecture >= SPARC_OPCODE_ARCH_V9))
324177298Sobrien		/* ba,pt %xcc  */
324277298Sobrien		insn = INSN_BPA | (val & 0x7ffff);
324377298Sobrien	      else
324477298Sobrien		/* ba  */
324577298Sobrien		insn = INSN_BA | (val & 0x3fffff);
324677298Sobrien	      if (fixP->fx_where >= 4
324777298Sobrien		  && ((delay & (0xffffffff ^ RS1 (~0)))
324877298Sobrien		      == (INSN_OR | RD (O7) | RS2 (G0))))
324977298Sobrien		{
325077298Sobrien		  long setter;
325177298Sobrien		  int reg;
325277298Sobrien
325377298Sobrien		  if (INSN_BIG_ENDIAN)
325477298Sobrien		    setter = bfd_getb32 ((unsigned char *) buf - 4);
325577298Sobrien		  else
325677298Sobrien		    setter = bfd_getl32 ((unsigned char *) buf - 4);
325777298Sobrien		  if ((setter & (0xffffffff ^ RD (~0)))
325877298Sobrien		      != (INSN_OR | RS1 (O7) | RS2 (G0)))
325977298Sobrien		    break;
326077298Sobrien		  /* The sequence was
326177298Sobrien		     or %o7, %g0, %rN
326277298Sobrien		     call foo
326377298Sobrien		     or %rN, %g0, %o7
326477298Sobrien
326577298Sobrien		     If call foo was replaced with ba, replace
326677298Sobrien		     or %rN, %g0, %o7 with nop.  */
326777298Sobrien		  reg = (delay & RS1 (~0)) >> 14;
326877298Sobrien		  if (reg != ((setter & RD (~0)) >> 25)
326977298Sobrien		      || reg == G0 || reg == O7)
327077298Sobrien		    break;
327177298Sobrien
327277298Sobrien		  if (INSN_BIG_ENDIAN)
327377298Sobrien		    bfd_putb32 (INSN_NOP, (unsigned char *) buf + 4);
327477298Sobrien		  else
327577298Sobrien		    bfd_putl32 (INSN_NOP, (unsigned char *) buf + 4);
327677298Sobrien		}
327777298Sobrien	    }
327859024Sobrien	  break;
327959024Sobrien
328059024Sobrien	case BFD_RELOC_SPARC_11:
328159024Sobrien	  if (! in_signed_range (val, 0x7ff))
328260484Sobrien	    as_bad_where (fixP->fx_file, fixP->fx_line,
328360484Sobrien			  _("relocation overflow"));
328459024Sobrien	  insn |= val & 0x7ff;
328559024Sobrien	  break;
328659024Sobrien
328759024Sobrien	case BFD_RELOC_SPARC_10:
328859024Sobrien	  if (! in_signed_range (val, 0x3ff))
328960484Sobrien	    as_bad_where (fixP->fx_file, fixP->fx_line,
329060484Sobrien			  _("relocation overflow"));
329159024Sobrien	  insn |= val & 0x3ff;
329259024Sobrien	  break;
329359024Sobrien
329459024Sobrien	case BFD_RELOC_SPARC_7:
329559024Sobrien	  if (! in_bitfield_range (val, 0x7f))
329660484Sobrien	    as_bad_where (fixP->fx_file, fixP->fx_line,
329760484Sobrien			  _("relocation overflow"));
329859024Sobrien	  insn |= val & 0x7f;
329959024Sobrien	  break;
330059024Sobrien
330159024Sobrien	case BFD_RELOC_SPARC_6:
330259024Sobrien	  if (! in_bitfield_range (val, 0x3f))
330360484Sobrien	    as_bad_where (fixP->fx_file, fixP->fx_line,
330460484Sobrien			  _("relocation overflow"));
330559024Sobrien	  insn |= val & 0x3f;
330659024Sobrien	  break;
330759024Sobrien
330859024Sobrien	case BFD_RELOC_SPARC_5:
330959024Sobrien	  if (! in_bitfield_range (val, 0x1f))
331060484Sobrien	    as_bad_where (fixP->fx_file, fixP->fx_line,
331160484Sobrien			  _("relocation overflow"));
331259024Sobrien	  insn |= val & 0x1f;
331359024Sobrien	  break;
331459024Sobrien
331559024Sobrien	case BFD_RELOC_SPARC_WDISP16:
3316218822Sdim	  if ((val & 3)
3317218822Sdim	      || val >= 0x1fffc
3318218822Sdim	      || val <= -(offsetT) 0x20008)
331960484Sobrien	    as_bad_where (fixP->fx_file, fixP->fx_line,
332060484Sobrien			  _("relocation overflow"));
332159024Sobrien	  /* FIXME: The +1 deserves a comment.  */
332259024Sobrien	  val = (val >> 2) + 1;
332359024Sobrien	  insn |= ((val & 0xc000) << 6) | (val & 0x3fff);
332459024Sobrien	  break;
332559024Sobrien
332659024Sobrien	case BFD_RELOC_SPARC_WDISP19:
3327218822Sdim	  if ((val & 3)
3328218822Sdim	      || val >= 0xffffc
3329218822Sdim	      || val <= -(offsetT) 0x100008)
333060484Sobrien	    as_bad_where (fixP->fx_file, fixP->fx_line,
333160484Sobrien			  _("relocation overflow"));
333259024Sobrien	  /* FIXME: The +1 deserves a comment.  */
333359024Sobrien	  val = (val >> 2) + 1;
333459024Sobrien	  insn |= val & 0x7ffff;
333559024Sobrien	  break;
333659024Sobrien
333759024Sobrien	case BFD_RELOC_SPARC_HH22:
333859024Sobrien	  val = BSR (val, 32);
333977298Sobrien	  /* Fall through.  */
334059024Sobrien
334159024Sobrien	case BFD_RELOC_SPARC_LM22:
334259024Sobrien	case BFD_RELOC_HI22:
334359024Sobrien	  if (!fixP->fx_addsy)
334489857Sobrien	    insn |= (val >> 10) & 0x3fffff;
334559024Sobrien	  else
334689857Sobrien	    /* FIXME: Need comment explaining why we do this.  */
334789857Sobrien	    insn &= ~0xffff;
334859024Sobrien	  break;
334959024Sobrien
335059024Sobrien	case BFD_RELOC_SPARC22:
335159024Sobrien	  if (val & ~0x003fffff)
335260484Sobrien	    as_bad_where (fixP->fx_file, fixP->fx_line,
335360484Sobrien			  _("relocation overflow"));
335459024Sobrien	  insn |= (val & 0x3fffff);
335559024Sobrien	  break;
335659024Sobrien
335759024Sobrien	case BFD_RELOC_SPARC_HM10:
335859024Sobrien	  val = BSR (val, 32);
335977298Sobrien	  /* Fall through.  */
336059024Sobrien
336159024Sobrien	case BFD_RELOC_LO10:
336259024Sobrien	  if (!fixP->fx_addsy)
336389857Sobrien	    insn |= val & 0x3ff;
336459024Sobrien	  else
336589857Sobrien	    /* FIXME: Need comment explaining why we do this.  */
336689857Sobrien	    insn &= ~0xff;
336759024Sobrien	  break;
336859024Sobrien
336960484Sobrien	case BFD_RELOC_SPARC_OLO10:
337060484Sobrien	  val &= 0x3ff;
337160484Sobrien	  val += fixP->tc_fix_data;
337277298Sobrien	  /* Fall through.  */
337360484Sobrien
337459024Sobrien	case BFD_RELOC_SPARC13:
337559024Sobrien	  if (! in_signed_range (val, 0x1fff))
337660484Sobrien	    as_bad_where (fixP->fx_file, fixP->fx_line,
337760484Sobrien			  _("relocation overflow"));
337859024Sobrien	  insn |= val & 0x1fff;
337959024Sobrien	  break;
338059024Sobrien
338159024Sobrien	case BFD_RELOC_SPARC_WDISP22:
338259024Sobrien	  val = (val >> 2) + 1;
338377298Sobrien	  /* Fall through.  */
338459024Sobrien	case BFD_RELOC_SPARC_BASE22:
338559024Sobrien	  insn |= val & 0x3fffff;
338659024Sobrien	  break;
338759024Sobrien
338859024Sobrien	case BFD_RELOC_SPARC_H44:
338959024Sobrien	  if (!fixP->fx_addsy)
339059024Sobrien	    {
339159024Sobrien	      bfd_vma tval = val;
339259024Sobrien	      tval >>= 22;
339359024Sobrien	      insn |= tval & 0x3fffff;
339459024Sobrien	    }
339559024Sobrien	  break;
339659024Sobrien
339759024Sobrien	case BFD_RELOC_SPARC_M44:
339859024Sobrien	  if (!fixP->fx_addsy)
339959024Sobrien	    insn |= (val >> 12) & 0x3ff;
340059024Sobrien	  break;
340159024Sobrien
340259024Sobrien	case BFD_RELOC_SPARC_L44:
340359024Sobrien	  if (!fixP->fx_addsy)
340459024Sobrien	    insn |= val & 0xfff;
340559024Sobrien	  break;
340659024Sobrien
340759024Sobrien	case BFD_RELOC_SPARC_HIX22:
340859024Sobrien	  if (!fixP->fx_addsy)
340959024Sobrien	    {
341077298Sobrien	      val ^= ~(offsetT) 0;
341159024Sobrien	      insn |= (val >> 10) & 0x3fffff;
341259024Sobrien	    }
341359024Sobrien	  break;
341459024Sobrien
341559024Sobrien	case BFD_RELOC_SPARC_LOX10:
341659024Sobrien	  if (!fixP->fx_addsy)
341759024Sobrien	    insn |= 0x1c00 | (val & 0x3ff);
341859024Sobrien	  break;
341959024Sobrien
342059024Sobrien	case BFD_RELOC_NONE:
342159024Sobrien	default:
342259024Sobrien	  as_bad_where (fixP->fx_file, fixP->fx_line,
342360484Sobrien			_("bad or unhandled relocation type: 0x%02x"),
342459024Sobrien			fixP->fx_r_type);
342559024Sobrien	  break;
342659024Sobrien	}
342759024Sobrien
342859024Sobrien      if (INSN_BIG_ENDIAN)
342959024Sobrien	bfd_putb32 (insn, (unsigned char *) buf);
343059024Sobrien      else
343159024Sobrien	bfd_putl32 (insn, (unsigned char *) buf);
343259024Sobrien    }
343359024Sobrien
343459024Sobrien  /* Are we finished with this relocation now?  */
343559024Sobrien  if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
343659024Sobrien    fixP->fx_done = 1;
343759024Sobrien}
343859024Sobrien
343959024Sobrien/* Translate internal representation of relocation info to BFD target
344059024Sobrien   format.  */
344177298Sobrien
344260484Sobrienarelent **
344359024Sobrientc_gen_reloc (section, fixp)
3444218822Sdim     asection *section;
344559024Sobrien     fixS *fixp;
344659024Sobrien{
344760484Sobrien  static arelent *relocs[3];
344859024Sobrien  arelent *reloc;
344959024Sobrien  bfd_reloc_code_real_type code;
345059024Sobrien
345160484Sobrien  relocs[0] = reloc = (arelent *) xmalloc (sizeof (arelent));
345260484Sobrien  relocs[1] = NULL;
345359024Sobrien
345460484Sobrien  reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
345560484Sobrien  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
345659024Sobrien  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
345759024Sobrien
345859024Sobrien  switch (fixp->fx_r_type)
345959024Sobrien    {
346059024Sobrien    case BFD_RELOC_16:
346159024Sobrien    case BFD_RELOC_32:
346259024Sobrien    case BFD_RELOC_HI22:
346359024Sobrien    case BFD_RELOC_LO10:
346459024Sobrien    case BFD_RELOC_32_PCREL_S2:
346559024Sobrien    case BFD_RELOC_SPARC13:
346660484Sobrien    case BFD_RELOC_SPARC22:
346759024Sobrien    case BFD_RELOC_SPARC_BASE13:
346859024Sobrien    case BFD_RELOC_SPARC_WDISP16:
346959024Sobrien    case BFD_RELOC_SPARC_WDISP19:
347059024Sobrien    case BFD_RELOC_SPARC_WDISP22:
347159024Sobrien    case BFD_RELOC_64:
347259024Sobrien    case BFD_RELOC_SPARC_5:
347359024Sobrien    case BFD_RELOC_SPARC_6:
347459024Sobrien    case BFD_RELOC_SPARC_7:
347559024Sobrien    case BFD_RELOC_SPARC_10:
347659024Sobrien    case BFD_RELOC_SPARC_11:
347759024Sobrien    case BFD_RELOC_SPARC_HH22:
347859024Sobrien    case BFD_RELOC_SPARC_HM10:
347959024Sobrien    case BFD_RELOC_SPARC_LM22:
348059024Sobrien    case BFD_RELOC_SPARC_PC_HH22:
348159024Sobrien    case BFD_RELOC_SPARC_PC_HM10:
348259024Sobrien    case BFD_RELOC_SPARC_PC_LM22:
348359024Sobrien    case BFD_RELOC_SPARC_H44:
348459024Sobrien    case BFD_RELOC_SPARC_M44:
348559024Sobrien    case BFD_RELOC_SPARC_L44:
348659024Sobrien    case BFD_RELOC_SPARC_HIX22:
348759024Sobrien    case BFD_RELOC_SPARC_LOX10:
348860484Sobrien    case BFD_RELOC_SPARC_REV32:
348960484Sobrien    case BFD_RELOC_SPARC_OLO10:
349078828Sobrien    case BFD_RELOC_SPARC_UA16:
349178828Sobrien    case BFD_RELOC_SPARC_UA32:
349278828Sobrien    case BFD_RELOC_SPARC_UA64:
349389857Sobrien    case BFD_RELOC_8_PCREL:
349489857Sobrien    case BFD_RELOC_16_PCREL:
349589857Sobrien    case BFD_RELOC_32_PCREL:
349689857Sobrien    case BFD_RELOC_64_PCREL:
349789857Sobrien    case BFD_RELOC_SPARC_PLT32:
349889857Sobrien    case BFD_RELOC_SPARC_PLT64:
349960484Sobrien    case BFD_RELOC_VTABLE_ENTRY:
350060484Sobrien    case BFD_RELOC_VTABLE_INHERIT:
3501130561Sobrien    case BFD_RELOC_SPARC_TLS_GD_HI22:
3502130561Sobrien    case BFD_RELOC_SPARC_TLS_GD_LO10:
3503130561Sobrien    case BFD_RELOC_SPARC_TLS_GD_ADD:
3504130561Sobrien    case BFD_RELOC_SPARC_TLS_GD_CALL:
3505130561Sobrien    case BFD_RELOC_SPARC_TLS_LDM_HI22:
3506130561Sobrien    case BFD_RELOC_SPARC_TLS_LDM_LO10:
3507130561Sobrien    case BFD_RELOC_SPARC_TLS_LDM_ADD:
3508130561Sobrien    case BFD_RELOC_SPARC_TLS_LDM_CALL:
3509130561Sobrien    case BFD_RELOC_SPARC_TLS_LDO_HIX22:
3510130561Sobrien    case BFD_RELOC_SPARC_TLS_LDO_LOX10:
3511130561Sobrien    case BFD_RELOC_SPARC_TLS_LDO_ADD:
3512130561Sobrien    case BFD_RELOC_SPARC_TLS_IE_HI22:
3513130561Sobrien    case BFD_RELOC_SPARC_TLS_IE_LO10:
3514130561Sobrien    case BFD_RELOC_SPARC_TLS_IE_LD:
3515130561Sobrien    case BFD_RELOC_SPARC_TLS_IE_LDX:
3516130561Sobrien    case BFD_RELOC_SPARC_TLS_IE_ADD:
3517130561Sobrien    case BFD_RELOC_SPARC_TLS_LE_HIX22:
3518130561Sobrien    case BFD_RELOC_SPARC_TLS_LE_LOX10:
3519130561Sobrien    case BFD_RELOC_SPARC_TLS_DTPOFF32:
3520130561Sobrien    case BFD_RELOC_SPARC_TLS_DTPOFF64:
352159024Sobrien      code = fixp->fx_r_type;
352259024Sobrien      break;
352359024Sobrien    default:
352459024Sobrien      abort ();
352559024Sobrien      return NULL;
352659024Sobrien    }
352759024Sobrien
352859024Sobrien#if defined (OBJ_ELF) || defined (OBJ_AOUT)
352959024Sobrien  /* If we are generating PIC code, we need to generate a different
353059024Sobrien     set of relocs.  */
353159024Sobrien
353259024Sobrien#ifdef OBJ_ELF
353359024Sobrien#define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
353459024Sobrien#else
353559024Sobrien#define GOT_NAME "__GLOBAL_OFFSET_TABLE_"
353659024Sobrien#endif
3537218822Sdim#ifdef TE_VXWORKS
3538218822Sdim#define GOTT_BASE "__GOTT_BASE__"
3539218822Sdim#define GOTT_INDEX "__GOTT_INDEX__"
3540218822Sdim#endif
354159024Sobrien
354260484Sobrien  /* This code must be parallel to the OBJ_ELF tc_fix_adjustable.  */
354360484Sobrien
354459024Sobrien  if (sparc_pic_code)
354559024Sobrien    {
354659024Sobrien      switch (code)
354759024Sobrien	{
354859024Sobrien	case BFD_RELOC_32_PCREL_S2:
3549130561Sobrien	  if (generic_force_reloc (fixp))
355059024Sobrien	    code = BFD_RELOC_SPARC_WPLT30;
355159024Sobrien	  break;
355259024Sobrien	case BFD_RELOC_HI22:
3553218822Sdim	  code = BFD_RELOC_SPARC_GOT22;
3554218822Sdim	  if (fixp->fx_addsy != NULL)
3555218822Sdim	    {
3556218822Sdim	      if (strcmp (S_GET_NAME (fixp->fx_addsy), GOT_NAME) == 0)
3557218822Sdim		code = BFD_RELOC_SPARC_PC22;
3558218822Sdim#ifdef TE_VXWORKS
3559218822Sdim	      if (strcmp (S_GET_NAME (fixp->fx_addsy), GOTT_BASE) == 0
3560218822Sdim		  || strcmp (S_GET_NAME (fixp->fx_addsy), GOTT_INDEX) == 0)
3561218822Sdim		code = BFD_RELOC_HI22; /* Unchanged.  */
3562218822Sdim#endif
3563218822Sdim	    }
356459024Sobrien	  break;
356559024Sobrien	case BFD_RELOC_LO10:
3566218822Sdim	  code = BFD_RELOC_SPARC_GOT10;
3567218822Sdim	  if (fixp->fx_addsy != NULL)
3568218822Sdim	    {
3569218822Sdim	      if (strcmp (S_GET_NAME (fixp->fx_addsy), GOT_NAME) == 0)
3570218822Sdim		code = BFD_RELOC_SPARC_PC10;
3571218822Sdim#ifdef TE_VXWORKS
3572218822Sdim	      if (strcmp (S_GET_NAME (fixp->fx_addsy), GOTT_BASE) == 0
3573218822Sdim		  || strcmp (S_GET_NAME (fixp->fx_addsy), GOTT_INDEX) == 0)
3574218822Sdim		code = BFD_RELOC_LO10; /* Unchanged.  */
3575218822Sdim#endif
3576218822Sdim	    }
357759024Sobrien	  break;
357859024Sobrien	case BFD_RELOC_SPARC13:
357959024Sobrien	  code = BFD_RELOC_SPARC_GOT13;
358059024Sobrien	  break;
358159024Sobrien	default:
358259024Sobrien	  break;
358359024Sobrien	}
358459024Sobrien    }
358577298Sobrien#endif /* defined (OBJ_ELF) || defined (OBJ_AOUT)  */
358659024Sobrien
3587218822Sdim  /* Nothing is aligned in DWARF debugging sections.  */
3588218822Sdim  if (bfd_get_section_flags (stdoutput, section) & SEC_DEBUGGING)
3589218822Sdim    switch (code)
3590218822Sdim      {
3591218822Sdim      case BFD_RELOC_16: code = BFD_RELOC_SPARC_UA16; break;
3592218822Sdim      case BFD_RELOC_32: code = BFD_RELOC_SPARC_UA32; break;
3593218822Sdim      case BFD_RELOC_64: code = BFD_RELOC_SPARC_UA64; break;
3594218822Sdim      default: break;
3595218822Sdim      }
3596218822Sdim
359760484Sobrien  if (code == BFD_RELOC_SPARC_OLO10)
359860484Sobrien    reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO10);
359960484Sobrien  else
360060484Sobrien    reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
360159024Sobrien  if (reloc->howto == 0)
360259024Sobrien    {
360359024Sobrien      as_bad_where (fixp->fx_file, fixp->fx_line,
360460484Sobrien		    _("internal error: can't export reloc type %d (`%s')"),
360559024Sobrien		    fixp->fx_r_type, bfd_get_reloc_code_name (code));
360660484Sobrien      xfree (reloc);
360760484Sobrien      relocs[0] = NULL;
360860484Sobrien      return relocs;
360959024Sobrien    }
361059024Sobrien
361159024Sobrien  /* @@ Why fx_addnumber sometimes and fx_offset other times?  */
361259024Sobrien#ifdef OBJ_AOUT
361359024Sobrien
361459024Sobrien  if (reloc->howto->pc_relative == 0
361559024Sobrien      || code == BFD_RELOC_SPARC_PC10
361659024Sobrien      || code == BFD_RELOC_SPARC_PC22)
361759024Sobrien    reloc->addend = fixp->fx_addnumber;
361860484Sobrien  else if (sparc_pic_code
361960484Sobrien	   && fixp->fx_r_type == BFD_RELOC_32_PCREL_S2
362060484Sobrien	   && fixp->fx_addsy != NULL
362160484Sobrien	   && (S_IS_EXTERNAL (fixp->fx_addsy)
362260484Sobrien	       || S_IS_WEAK (fixp->fx_addsy))
362360484Sobrien	   && S_IS_DEFINED (fixp->fx_addsy)
362460484Sobrien	   && ! S_IS_COMMON (fixp->fx_addsy))
362560484Sobrien    reloc->addend = fixp->fx_addnumber;
362659024Sobrien  else
362759024Sobrien    reloc->addend = fixp->fx_offset - reloc->address;
362859024Sobrien
362977298Sobrien#else /* elf or coff  */
363059024Sobrien
363189857Sobrien  if (code != BFD_RELOC_32_PCREL_S2
363289857Sobrien      && code != BFD_RELOC_SPARC_WDISP22
363389857Sobrien      && code != BFD_RELOC_SPARC_WDISP16
363489857Sobrien      && code != BFD_RELOC_SPARC_WDISP19
3635130561Sobrien      && code != BFD_RELOC_SPARC_WPLT30
3636130561Sobrien      && code != BFD_RELOC_SPARC_TLS_GD_CALL
3637130561Sobrien      && code != BFD_RELOC_SPARC_TLS_LDM_CALL)
363859024Sobrien    reloc->addend = fixp->fx_addnumber;
363960484Sobrien  else if (symbol_section_p (fixp->fx_addsy))
364059024Sobrien    reloc->addend = (section->vma
364159024Sobrien		     + fixp->fx_addnumber
364259024Sobrien		     + md_pcrel_from (fixp));
364359024Sobrien  else
364459024Sobrien    reloc->addend = fixp->fx_offset;
364559024Sobrien#endif
364659024Sobrien
364760484Sobrien  /* We expand R_SPARC_OLO10 to R_SPARC_LO10 and R_SPARC_13
364860484Sobrien     on the same location.  */
364960484Sobrien  if (code == BFD_RELOC_SPARC_OLO10)
365060484Sobrien    {
365160484Sobrien      relocs[1] = reloc = (arelent *) xmalloc (sizeof (arelent));
365260484Sobrien      relocs[2] = NULL;
365360484Sobrien
365460484Sobrien      reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
365577298Sobrien      *reloc->sym_ptr_ptr
365677298Sobrien	= symbol_get_bfdsym (section_symbol (absolute_section));
365760484Sobrien      reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
365860484Sobrien      reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_SPARC13);
365960484Sobrien      reloc->addend = fixp->tc_fix_data;
366060484Sobrien    }
366160484Sobrien
366260484Sobrien  return relocs;
366359024Sobrien}
366459024Sobrien
366577298Sobrien/* We have no need to default values of symbols.  */
366659024Sobrien
366759024SobriensymbolS *
366859024Sobrienmd_undefined_symbol (name)
366977298Sobrien     char *name ATTRIBUTE_UNUSED;
367059024Sobrien{
367159024Sobrien  return 0;
367277298Sobrien}
367359024Sobrien
367477298Sobrien/* Round up a section size to the appropriate boundary.  */
367577298Sobrien
367659024SobrienvalueT
367759024Sobrienmd_section_align (segment, size)
367877298Sobrien     segT segment ATTRIBUTE_UNUSED;
367959024Sobrien     valueT size;
368059024Sobrien{
368159024Sobrien#ifndef OBJ_ELF
368259024Sobrien  /* This is not right for ELF; a.out wants it, and COFF will force
368359024Sobrien     the alignment anyways.  */
368459024Sobrien  valueT align = ((valueT) 1
368559024Sobrien		  << (valueT) bfd_get_section_alignment (stdoutput, segment));
368659024Sobrien  valueT newsize;
368777298Sobrien
368877298Sobrien  /* Turn alignment value into a mask.  */
368959024Sobrien  align--;
369059024Sobrien  newsize = (size + align) & ~align;
369159024Sobrien  return newsize;
369259024Sobrien#else
369359024Sobrien  return size;
369459024Sobrien#endif
369559024Sobrien}
369659024Sobrien
369759024Sobrien/* Exactly what point is a PC-relative offset relative TO?
369859024Sobrien   On the sparc, they're relative to the address of the offset, plus
369959024Sobrien   its size.  This gets us to the following instruction.
370077298Sobrien   (??? Is this right?  FIXME-SOON)  */
370177298Sobrienlong
370259024Sobrienmd_pcrel_from (fixP)
370359024Sobrien     fixS *fixP;
370459024Sobrien{
370559024Sobrien  long ret;
370659024Sobrien
370759024Sobrien  ret = fixP->fx_where + fixP->fx_frag->fr_address;
370859024Sobrien  if (! sparc_pic_code
370959024Sobrien      || fixP->fx_addsy == NULL
371060484Sobrien      || symbol_section_p (fixP->fx_addsy))
371159024Sobrien    ret += fixP->fx_size;
371259024Sobrien  return ret;
371359024Sobrien}
371459024Sobrien
371560484Sobrien/* Return log2 (VALUE), or -1 if VALUE is not an exact positive power
371660484Sobrien   of two.  */
371760484Sobrien
371860484Sobrienstatic int
3719218822Sdimmylog2 (value)
372060484Sobrien     int value;
372160484Sobrien{
372260484Sobrien  int shift;
372360484Sobrien
372460484Sobrien  if (value <= 0)
372560484Sobrien    return -1;
372660484Sobrien
372760484Sobrien  for (shift = 0; (value & 1) == 0; value >>= 1)
372860484Sobrien    ++shift;
372960484Sobrien
373060484Sobrien  return (value == 1) ? shift : -1;
373160484Sobrien}
373260484Sobrien
373377298Sobrien/* Sort of like s_lcomm.  */
373459024Sobrien
373559024Sobrien#ifndef OBJ_ELF
373659024Sobrienstatic int max_alignment = 15;
373759024Sobrien#endif
373859024Sobrien
373959024Sobrienstatic void
374059024Sobriens_reserve (ignore)
374177298Sobrien     int ignore ATTRIBUTE_UNUSED;
374259024Sobrien{
374359024Sobrien  char *name;
374459024Sobrien  char *p;
374559024Sobrien  char c;
374659024Sobrien  int align;
374759024Sobrien  int size;
374859024Sobrien  int temp;
374959024Sobrien  symbolS *symbolP;
375059024Sobrien
375159024Sobrien  name = input_line_pointer;
375259024Sobrien  c = get_symbol_end ();
375359024Sobrien  p = input_line_pointer;
375459024Sobrien  *p = c;
375559024Sobrien  SKIP_WHITESPACE ();
375659024Sobrien
375759024Sobrien  if (*input_line_pointer != ',')
375859024Sobrien    {
375960484Sobrien      as_bad (_("Expected comma after name"));
376059024Sobrien      ignore_rest_of_line ();
376159024Sobrien      return;
376259024Sobrien    }
376359024Sobrien
376459024Sobrien  ++input_line_pointer;
376559024Sobrien
376659024Sobrien  if ((size = get_absolute_expression ()) < 0)
376759024Sobrien    {
376860484Sobrien      as_bad (_("BSS length (%d.) <0! Ignored."), size);
376959024Sobrien      ignore_rest_of_line ();
377059024Sobrien      return;
377177298Sobrien    }				/* Bad length.  */
377259024Sobrien
377359024Sobrien  *p = 0;
377459024Sobrien  symbolP = symbol_find_or_make (name);
377559024Sobrien  *p = c;
377659024Sobrien
377759024Sobrien  if (strncmp (input_line_pointer, ",\"bss\"", 6) != 0
377859024Sobrien      && strncmp (input_line_pointer, ",\".bss\"", 7) != 0)
377959024Sobrien    {
378060484Sobrien      as_bad (_("bad .reserve segment -- expected BSS segment"));
378159024Sobrien      return;
378259024Sobrien    }
378359024Sobrien
378459024Sobrien  if (input_line_pointer[2] == '.')
378559024Sobrien    input_line_pointer += 7;
378659024Sobrien  else
378759024Sobrien    input_line_pointer += 6;
378859024Sobrien  SKIP_WHITESPACE ();
378959024Sobrien
379059024Sobrien  if (*input_line_pointer == ',')
379159024Sobrien    {
379259024Sobrien      ++input_line_pointer;
379359024Sobrien
379459024Sobrien      SKIP_WHITESPACE ();
379559024Sobrien      if (*input_line_pointer == '\n')
379659024Sobrien	{
379760484Sobrien	  as_bad (_("missing alignment"));
379860484Sobrien	  ignore_rest_of_line ();
379959024Sobrien	  return;
380059024Sobrien	}
380159024Sobrien
380260484Sobrien      align = (int) get_absolute_expression ();
380360484Sobrien
380459024Sobrien#ifndef OBJ_ELF
380559024Sobrien      if (align > max_alignment)
380659024Sobrien	{
380759024Sobrien	  align = max_alignment;
380860484Sobrien	  as_warn (_("alignment too large; assuming %d"), align);
380959024Sobrien	}
381059024Sobrien#endif
381160484Sobrien
381259024Sobrien      if (align < 0)
381359024Sobrien	{
381460484Sobrien	  as_bad (_("negative alignment"));
381560484Sobrien	  ignore_rest_of_line ();
381660484Sobrien	  return;
381759024Sobrien	}
381859024Sobrien
381960484Sobrien      if (align != 0)
382060484Sobrien	{
3821218822Sdim	  temp = mylog2 (align);
382260484Sobrien	  if (temp < 0)
382360484Sobrien	    {
382460484Sobrien	      as_bad (_("alignment not a power of 2"));
382560484Sobrien	      ignore_rest_of_line ();
382660484Sobrien	      return;
382760484Sobrien	    }
382859024Sobrien
382960484Sobrien	  align = temp;
383060484Sobrien	}
383159024Sobrien
383260484Sobrien      record_alignment (bss_section, align);
383360484Sobrien    }
383459024Sobrien  else
383559024Sobrien    align = 0;
383659024Sobrien
383759024Sobrien  if (!S_IS_DEFINED (symbolP)
383859024Sobrien#ifdef OBJ_AOUT
383959024Sobrien      && S_GET_OTHER (symbolP) == 0
384059024Sobrien      && S_GET_DESC (symbolP) == 0
384159024Sobrien#endif
384259024Sobrien      )
384359024Sobrien    {
384459024Sobrien      if (! need_pass_2)
384559024Sobrien	{
384659024Sobrien	  char *pfrag;
384759024Sobrien	  segT current_seg = now_seg;
384859024Sobrien	  subsegT current_subseg = now_subseg;
384959024Sobrien
385077298Sobrien	  /* Switch to bss.  */
385177298Sobrien	  subseg_set (bss_section, 1);
385259024Sobrien
385359024Sobrien	  if (align)
385477298Sobrien	    /* Do alignment.  */
385577298Sobrien	    frag_align (align, 0, 0);
385659024Sobrien
385777298Sobrien	  /* Detach from old frag.  */
385877298Sobrien	  if (S_GET_SEGMENT (symbolP) == bss_section)
385960484Sobrien	    symbol_get_frag (symbolP)->fr_symbol = NULL;
386059024Sobrien
386160484Sobrien	  symbol_set_frag (symbolP, frag_now);
386277298Sobrien	  pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
386377298Sobrien			    (offsetT) size, (char *) 0);
386459024Sobrien	  *pfrag = 0;
386559024Sobrien
386659024Sobrien	  S_SET_SEGMENT (symbolP, bss_section);
386759024Sobrien
386859024Sobrien	  subseg_set (current_seg, current_subseg);
386960484Sobrien
387060484Sobrien#ifdef OBJ_ELF
387160484Sobrien	  S_SET_SIZE (symbolP, size);
387260484Sobrien#endif
387359024Sobrien	}
387459024Sobrien    }
387559024Sobrien  else
387659024Sobrien    {
387777298Sobrien      as_warn ("Ignoring attempt to re-define symbol %s",
387877298Sobrien	       S_GET_NAME (symbolP));
387977298Sobrien    }				/* if not redefining.  */
388059024Sobrien
388159024Sobrien  demand_empty_rest_of_line ();
388259024Sobrien}
388359024Sobrien
388459024Sobrienstatic void
388559024Sobriens_common (ignore)
388677298Sobrien     int ignore ATTRIBUTE_UNUSED;
388759024Sobrien{
388859024Sobrien  char *name;
388959024Sobrien  char c;
389059024Sobrien  char *p;
3891130561Sobrien  offsetT temp, size;
389259024Sobrien  symbolS *symbolP;
389359024Sobrien
389459024Sobrien  name = input_line_pointer;
389559024Sobrien  c = get_symbol_end ();
389677298Sobrien  /* Just after name is now '\0'.  */
389759024Sobrien  p = input_line_pointer;
389859024Sobrien  *p = c;
389959024Sobrien  SKIP_WHITESPACE ();
390059024Sobrien  if (*input_line_pointer != ',')
390159024Sobrien    {
390260484Sobrien      as_bad (_("Expected comma after symbol-name"));
390359024Sobrien      ignore_rest_of_line ();
390459024Sobrien      return;
390559024Sobrien    }
390677298Sobrien
390777298Sobrien  /* Skip ','.  */
390877298Sobrien  input_line_pointer++;
390977298Sobrien
391059024Sobrien  if ((temp = get_absolute_expression ()) < 0)
391159024Sobrien    {
3912130561Sobrien      as_bad (_(".COMMon length (%lu) out of range ignored"),
3913130561Sobrien	      (unsigned long) temp);
391459024Sobrien      ignore_rest_of_line ();
391559024Sobrien      return;
391659024Sobrien    }
391759024Sobrien  size = temp;
391859024Sobrien  *p = 0;
391959024Sobrien  symbolP = symbol_find_or_make (name);
392059024Sobrien  *p = c;
392159024Sobrien  if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
392259024Sobrien    {
392360484Sobrien      as_bad (_("Ignoring attempt to re-define symbol"));
392459024Sobrien      ignore_rest_of_line ();
392559024Sobrien      return;
392659024Sobrien    }
392759024Sobrien  if (S_GET_VALUE (symbolP) != 0)
392859024Sobrien    {
392959024Sobrien      if (S_GET_VALUE (symbolP) != (valueT) size)
393059024Sobrien	{
3931130561Sobrien	  as_warn (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."),
3932130561Sobrien		   S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), (long) size);
393359024Sobrien	}
393459024Sobrien    }
393559024Sobrien  else
393659024Sobrien    {
393759024Sobrien#ifndef OBJ_ELF
393859024Sobrien      S_SET_VALUE (symbolP, (valueT) size);
393959024Sobrien      S_SET_EXTERNAL (symbolP);
394059024Sobrien#endif
394159024Sobrien    }
394260484Sobrien  know (symbol_get_frag (symbolP) == &zero_address_frag);
394359024Sobrien  if (*input_line_pointer != ',')
394459024Sobrien    {
394560484Sobrien      as_bad (_("Expected comma after common length"));
394659024Sobrien      ignore_rest_of_line ();
394759024Sobrien      return;
394859024Sobrien    }
394959024Sobrien  input_line_pointer++;
395059024Sobrien  SKIP_WHITESPACE ();
395159024Sobrien  if (*input_line_pointer != '"')
395259024Sobrien    {
395359024Sobrien      temp = get_absolute_expression ();
395460484Sobrien
395559024Sobrien#ifndef OBJ_ELF
395659024Sobrien      if (temp > max_alignment)
395759024Sobrien	{
395859024Sobrien	  temp = max_alignment;
3959218822Sdim	  as_warn (_("alignment too large; assuming %ld"), (long) temp);
396059024Sobrien	}
396159024Sobrien#endif
396260484Sobrien
396359024Sobrien      if (temp < 0)
396459024Sobrien	{
396560484Sobrien	  as_bad (_("negative alignment"));
396660484Sobrien	  ignore_rest_of_line ();
396760484Sobrien	  return;
396859024Sobrien	}
396960484Sobrien
397059024Sobrien#ifdef OBJ_ELF
397160484Sobrien      if (symbol_get_obj (symbolP)->local)
397259024Sobrien	{
397359024Sobrien	  segT old_sec;
397459024Sobrien	  int old_subsec;
397559024Sobrien	  char *p;
397659024Sobrien	  int align;
397759024Sobrien
397859024Sobrien	  old_sec = now_seg;
397959024Sobrien	  old_subsec = now_subseg;
398060484Sobrien
398160484Sobrien	  if (temp == 0)
398260484Sobrien	    align = 0;
398360484Sobrien	  else
3984218822Sdim	    align = mylog2 (temp);
398560484Sobrien
398660484Sobrien	  if (align < 0)
398760484Sobrien	    {
398860484Sobrien	      as_bad (_("alignment not a power of 2"));
398960484Sobrien	      ignore_rest_of_line ();
399060484Sobrien	      return;
399160484Sobrien	    }
399260484Sobrien
399359024Sobrien	  record_alignment (bss_section, align);
399459024Sobrien	  subseg_set (bss_section, 0);
399559024Sobrien	  if (align)
399659024Sobrien	    frag_align (align, 0, 0);
399759024Sobrien	  if (S_GET_SEGMENT (symbolP) == bss_section)
399860484Sobrien	    symbol_get_frag (symbolP)->fr_symbol = 0;
399960484Sobrien	  symbol_set_frag (symbolP, frag_now);
400059024Sobrien	  p = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
400159024Sobrien			(offsetT) size, (char *) 0);
400259024Sobrien	  *p = 0;
400359024Sobrien	  S_SET_SEGMENT (symbolP, bss_section);
400459024Sobrien	  S_CLEAR_EXTERNAL (symbolP);
400560484Sobrien	  S_SET_SIZE (symbolP, size);
400659024Sobrien	  subseg_set (old_sec, old_subsec);
400759024Sobrien	}
400859024Sobrien      else
400977298Sobrien#endif /* OBJ_ELF  */
401059024Sobrien	{
401159024Sobrien	allocate_common:
401259024Sobrien	  S_SET_VALUE (symbolP, (valueT) size);
401359024Sobrien#ifdef OBJ_ELF
401459024Sobrien	  S_SET_ALIGN (symbolP, temp);
401560484Sobrien	  S_SET_SIZE (symbolP, size);
401659024Sobrien#endif
401759024Sobrien	  S_SET_EXTERNAL (symbolP);
401859024Sobrien	  S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
401959024Sobrien	}
402059024Sobrien    }
402159024Sobrien  else
402259024Sobrien    {
402359024Sobrien      input_line_pointer++;
402459024Sobrien      /* @@ Some use the dot, some don't.  Can we get some consistency??  */
402559024Sobrien      if (*input_line_pointer == '.')
402659024Sobrien	input_line_pointer++;
402759024Sobrien      /* @@ Some say data, some say bss.  */
402859024Sobrien      if (strncmp (input_line_pointer, "bss\"", 4)
402959024Sobrien	  && strncmp (input_line_pointer, "data\"", 5))
403059024Sobrien	{
403159024Sobrien	  while (*--input_line_pointer != '"')
403259024Sobrien	    ;
403359024Sobrien	  input_line_pointer--;
403459024Sobrien	  goto bad_common_segment;
403559024Sobrien	}
403659024Sobrien      while (*input_line_pointer++ != '"')
403759024Sobrien	;
403859024Sobrien      goto allocate_common;
403959024Sobrien    }
404059024Sobrien
404160484Sobrien  symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
404259024Sobrien
404359024Sobrien  demand_empty_rest_of_line ();
404459024Sobrien  return;
404559024Sobrien
404659024Sobrien  {
404759024Sobrien  bad_common_segment:
404859024Sobrien    p = input_line_pointer;
404959024Sobrien    while (*p && *p != '\n')
405059024Sobrien      p++;
405159024Sobrien    c = *p;
405259024Sobrien    *p = '\0';
405360484Sobrien    as_bad (_("bad .common segment %s"), input_line_pointer + 1);
405459024Sobrien    *p = c;
405559024Sobrien    input_line_pointer = p;
405659024Sobrien    ignore_rest_of_line ();
405759024Sobrien    return;
405859024Sobrien  }
405959024Sobrien}
406059024Sobrien
4061130561Sobrien/* Handle the .empty pseudo-op.  This suppresses the warnings about
406259024Sobrien   invalid delay slot usage.  */
406359024Sobrien
406459024Sobrienstatic void
406559024Sobriens_empty (ignore)
406677298Sobrien     int ignore ATTRIBUTE_UNUSED;
406759024Sobrien{
406859024Sobrien  /* The easy way to implement is to just forget about the last
406959024Sobrien     instruction.  */
407059024Sobrien  last_insn = NULL;
407159024Sobrien}
407259024Sobrien
407359024Sobrienstatic void
407459024Sobriens_seg (ignore)
407577298Sobrien     int ignore ATTRIBUTE_UNUSED;
407659024Sobrien{
407759024Sobrien
407859024Sobrien  if (strncmp (input_line_pointer, "\"text\"", 6) == 0)
407959024Sobrien    {
408059024Sobrien      input_line_pointer += 6;
408159024Sobrien      s_text (0);
408259024Sobrien      return;
408359024Sobrien    }
408459024Sobrien  if (strncmp (input_line_pointer, "\"data\"", 6) == 0)
408559024Sobrien    {
408659024Sobrien      input_line_pointer += 6;
408759024Sobrien      s_data (0);
408859024Sobrien      return;
408959024Sobrien    }
409059024Sobrien  if (strncmp (input_line_pointer, "\"data1\"", 7) == 0)
409159024Sobrien    {
409259024Sobrien      input_line_pointer += 7;
409359024Sobrien      s_data1 ();
409459024Sobrien      return;
409559024Sobrien    }
409659024Sobrien  if (strncmp (input_line_pointer, "\"bss\"", 5) == 0)
409759024Sobrien    {
409859024Sobrien      input_line_pointer += 5;
409959024Sobrien      /* We only support 2 segments -- text and data -- for now, so
410059024Sobrien	 things in the "bss segment" will have to go into data for now.
410177298Sobrien	 You can still allocate SEG_BSS stuff with .lcomm or .reserve.  */
410277298Sobrien      subseg_set (data_section, 255);	/* FIXME-SOMEDAY.  */
410359024Sobrien      return;
410459024Sobrien    }
410560484Sobrien  as_bad (_("Unknown segment type"));
410659024Sobrien  demand_empty_rest_of_line ();
410759024Sobrien}
410859024Sobrien
410959024Sobrienstatic void
411059024Sobriens_data1 ()
411159024Sobrien{
411259024Sobrien  subseg_set (data_section, 1);
411359024Sobrien  demand_empty_rest_of_line ();
411459024Sobrien}
411559024Sobrien
411659024Sobrienstatic void
411759024Sobriens_proc (ignore)
411877298Sobrien     int ignore ATTRIBUTE_UNUSED;
411959024Sobrien{
412059024Sobrien  while (!is_end_of_line[(unsigned char) *input_line_pointer])
412159024Sobrien    {
412259024Sobrien      ++input_line_pointer;
412359024Sobrien    }
412459024Sobrien  ++input_line_pointer;
412559024Sobrien}
412659024Sobrien
412759024Sobrien/* This static variable is set by s_uacons to tell sparc_cons_align
4128130561Sobrien   that the expression does not need to be aligned.  */
412959024Sobrien
413059024Sobrienstatic int sparc_no_align_cons = 0;
413159024Sobrien
413289857Sobrien/* This static variable is set by sparc_cons to emit requested types
413389857Sobrien   of relocations in cons_fix_new_sparc.  */
413489857Sobrien
413589857Sobrienstatic const char *sparc_cons_special_reloc;
413689857Sobrien
413759024Sobrien/* This handles the unaligned space allocation pseudo-ops, such as
413859024Sobrien   .uaword.  .uaword is just like .word, but the value does not need
413959024Sobrien   to be aligned.  */
414059024Sobrien
414159024Sobrienstatic void
414259024Sobriens_uacons (bytes)
414359024Sobrien     int bytes;
414459024Sobrien{
414559024Sobrien  /* Tell sparc_cons_align not to align this value.  */
414659024Sobrien  sparc_no_align_cons = 1;
414759024Sobrien  cons (bytes);
414889857Sobrien  sparc_no_align_cons = 0;
414959024Sobrien}
415059024Sobrien
415160484Sobrien/* This handles the native word allocation pseudo-op .nword.
415260484Sobrien   For sparc_arch_size 32 it is equivalent to .word,  for
415360484Sobrien   sparc_arch_size 64 it is equivalent to .xword.  */
415460484Sobrien
415560484Sobrienstatic void
415660484Sobriens_ncons (bytes)
415777298Sobrien     int bytes ATTRIBUTE_UNUSED;
415860484Sobrien{
415960484Sobrien  cons (sparc_arch_size == 32 ? 4 : 8);
416060484Sobrien}
416160484Sobrien
416260484Sobrien#ifdef OBJ_ELF
416360484Sobrien/* Handle the SPARC ELF .register pseudo-op.  This sets the binding of a
416460484Sobrien   global register.
416560484Sobrien   The syntax is:
416677298Sobrien
416760484Sobrien   .register %g[2367],{#scratch|symbolname|#ignore}
416877298Sobrien*/
416960484Sobrien
417060484Sobrienstatic void
417160484Sobriens_register (ignore)
417277298Sobrien     int ignore ATTRIBUTE_UNUSED;
417360484Sobrien{
417460484Sobrien  char c;
417560484Sobrien  int reg;
417660484Sobrien  int flags;
417760484Sobrien  const char *regname;
417860484Sobrien
417960484Sobrien  if (input_line_pointer[0] != '%'
418060484Sobrien      || input_line_pointer[1] != 'g'
418160484Sobrien      || ((input_line_pointer[2] & ~1) != '2'
418260484Sobrien	  && (input_line_pointer[2] & ~1) != '6')
418360484Sobrien      || input_line_pointer[3] != ',')
418460484Sobrien    as_bad (_("register syntax is .register %%g[2367],{#scratch|symbolname|#ignore}"));
418560484Sobrien  reg = input_line_pointer[2] - '0';
418660484Sobrien  input_line_pointer += 4;
418760484Sobrien
418860484Sobrien  if (*input_line_pointer == '#')
418960484Sobrien    {
419060484Sobrien      ++input_line_pointer;
419160484Sobrien      regname = input_line_pointer;
419260484Sobrien      c = get_symbol_end ();
419360484Sobrien      if (strcmp (regname, "scratch") && strcmp (regname, "ignore"))
419460484Sobrien	as_bad (_("register syntax is .register %%g[2367],{#scratch|symbolname|#ignore}"));
419577298Sobrien      if (regname[0] == 'i')
419660484Sobrien	regname = NULL;
419760484Sobrien      else
419860484Sobrien	regname = "";
419960484Sobrien    }
420060484Sobrien  else
420160484Sobrien    {
420260484Sobrien      regname = input_line_pointer;
420360484Sobrien      c = get_symbol_end ();
420460484Sobrien    }
420560484Sobrien  if (sparc_arch_size == 64)
420660484Sobrien    {
420777298Sobrien      if (globals[reg])
420860484Sobrien	{
420977298Sobrien	  if ((regname && globals[reg] != (symbolS *) 1
421077298Sobrien	       && strcmp (S_GET_NAME (globals[reg]), regname))
421177298Sobrien	      || ((regname != NULL) ^ (globals[reg] != (symbolS *) 1)))
421260484Sobrien	    as_bad (_("redefinition of global register"));
421360484Sobrien	}
421460484Sobrien      else
421560484Sobrien	{
421660484Sobrien	  if (regname == NULL)
421777298Sobrien	    globals[reg] = (symbolS *) 1;
421860484Sobrien	  else
421960484Sobrien	    {
422060484Sobrien	      if (*regname)
422160484Sobrien		{
422260484Sobrien		  if (symbol_find (regname))
422360484Sobrien		    as_bad (_("Register symbol %s already defined."),
422460484Sobrien			    regname);
422560484Sobrien		}
422677298Sobrien	      globals[reg] = symbol_make (regname);
422777298Sobrien	      flags = symbol_get_bfdsym (globals[reg])->flags;
422860484Sobrien	      if (! *regname)
422960484Sobrien		flags = flags & ~(BSF_GLOBAL|BSF_LOCAL|BSF_WEAK);
423060484Sobrien	      if (! (flags & (BSF_GLOBAL|BSF_LOCAL|BSF_WEAK)))
423160484Sobrien		flags |= BSF_GLOBAL;
423277298Sobrien	      symbol_get_bfdsym (globals[reg])->flags = flags;
423377298Sobrien	      S_SET_VALUE (globals[reg], (valueT) reg);
423477298Sobrien	      S_SET_ALIGN (globals[reg], reg);
423577298Sobrien	      S_SET_SIZE (globals[reg], 0);
423660484Sobrien	      /* Although we actually want undefined_section here,
423760484Sobrien		 we have to use absolute_section, because otherwise
423860484Sobrien		 generic as code will make it a COM section.
423960484Sobrien		 We fix this up in sparc_adjust_symtab.  */
424077298Sobrien	      S_SET_SEGMENT (globals[reg], absolute_section);
424177298Sobrien	      S_SET_OTHER (globals[reg], 0);
424277298Sobrien	      elf_symbol (symbol_get_bfdsym (globals[reg]))
424360484Sobrien		->internal_elf_sym.st_info =
424460484Sobrien		  ELF_ST_INFO(STB_GLOBAL, STT_REGISTER);
424577298Sobrien	      elf_symbol (symbol_get_bfdsym (globals[reg]))
424660484Sobrien		->internal_elf_sym.st_shndx = SHN_UNDEF;
424760484Sobrien	    }
424860484Sobrien	}
424960484Sobrien    }
425060484Sobrien
425160484Sobrien  *input_line_pointer = c;
425260484Sobrien
425360484Sobrien  demand_empty_rest_of_line ();
425460484Sobrien}
425560484Sobrien
425660484Sobrien/* Adjust the symbol table.  We set undefined sections for STT_REGISTER
425760484Sobrien   symbols which need it.  */
425877298Sobrien
425960484Sobrienvoid
426060484Sobriensparc_adjust_symtab ()
426160484Sobrien{
426260484Sobrien  symbolS *sym;
426377298Sobrien
426460484Sobrien  for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
426560484Sobrien    {
426660484Sobrien      if (ELF_ST_TYPE (elf_symbol (symbol_get_bfdsym (sym))
426760484Sobrien		       ->internal_elf_sym.st_info) != STT_REGISTER)
426860484Sobrien	continue;
426960484Sobrien
427060484Sobrien      if (ELF_ST_TYPE (elf_symbol (symbol_get_bfdsym (sym))
427160484Sobrien		       ->internal_elf_sym.st_shndx != SHN_UNDEF))
427260484Sobrien	continue;
427360484Sobrien
427460484Sobrien      S_SET_SEGMENT (sym, undefined_section);
427560484Sobrien    }
427660484Sobrien}
427760484Sobrien#endif
427860484Sobrien
427959024Sobrien/* If the --enforce-aligned-data option is used, we require .word,
428059024Sobrien   et. al., to be aligned correctly.  We do it by setting up an
428159024Sobrien   rs_align_code frag, and checking in HANDLE_ALIGN to make sure that
428259024Sobrien   no unexpected alignment was introduced.
428359024Sobrien
428459024Sobrien   The SunOS and Solaris native assemblers enforce aligned data by
428559024Sobrien   default.  We don't want to do that, because gcc can deliberately
428659024Sobrien   generate misaligned data if the packed attribute is used.  Instead,
428759024Sobrien   we permit misaligned data by default, and permit the user to set an
428859024Sobrien   option to check for it.  */
428959024Sobrien
429059024Sobrienvoid
429159024Sobriensparc_cons_align (nbytes)
429259024Sobrien     int nbytes;
429359024Sobrien{
429459024Sobrien  int nalign;
429559024Sobrien  char *p;
429659024Sobrien
429759024Sobrien  /* Only do this if we are enforcing aligned data.  */
429859024Sobrien  if (! enforce_aligned_data)
429959024Sobrien    return;
430059024Sobrien
430178828Sobrien  /* Don't align if this is an unaligned pseudo-op.  */
430259024Sobrien  if (sparc_no_align_cons)
430378828Sobrien    return;
430459024Sobrien
4305218822Sdim  nalign = mylog2 (nbytes);
430659024Sobrien  if (nalign == 0)
430759024Sobrien    return;
430859024Sobrien
430960484Sobrien  assert (nalign > 0);
431060484Sobrien
431159024Sobrien  if (now_seg == absolute_section)
431259024Sobrien    {
431359024Sobrien      if ((abs_section_offset & ((1 << nalign) - 1)) != 0)
431460484Sobrien	as_bad (_("misaligned data"));
431559024Sobrien      return;
431659024Sobrien    }
431759024Sobrien
431877298Sobrien  p = frag_var (rs_align_test, 1, 1, (relax_substateT) 0,
431959024Sobrien		(symbolS *) NULL, (offsetT) nalign, (char *) NULL);
432059024Sobrien
432159024Sobrien  record_alignment (now_seg, nalign);
432259024Sobrien}
432359024Sobrien
432477298Sobrien/* This is called from HANDLE_ALIGN in tc-sparc.h.  */
432559024Sobrien
432659024Sobrienvoid
432759024Sobriensparc_handle_align (fragp)
432859024Sobrien     fragS *fragp;
432959024Sobrien{
433077298Sobrien  int count, fix;
433177298Sobrien  char *p;
433277298Sobrien
433377298Sobrien  count = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
433477298Sobrien
433577298Sobrien  switch (fragp->fr_type)
433659024Sobrien    {
433777298Sobrien    case rs_align_test:
433877298Sobrien      if (count != 0)
433977298Sobrien	as_bad_where (fragp->fr_file, fragp->fr_line, _("misaligned data"));
434077298Sobrien      break;
434160484Sobrien
434277298Sobrien    case rs_align_code:
434377298Sobrien      p = fragp->fr_literal + fragp->fr_fix;
434477298Sobrien      fix = 0;
434577298Sobrien
434677298Sobrien      if (count & 3)
434777298Sobrien	{
434877298Sobrien	  fix = count & 3;
434977298Sobrien	  memset (p, 0, fix);
435077298Sobrien	  p += fix;
435177298Sobrien	  count -= fix;
435277298Sobrien	}
435377298Sobrien
435477298Sobrien      if (SPARC_OPCODE_ARCH_V9_P (max_architecture) && count > 8)
435577298Sobrien	{
435677298Sobrien	  unsigned wval = (0x30680000 | count >> 2); /* ba,a,pt %xcc, 1f  */
435777298Sobrien	  if (INSN_BIG_ENDIAN)
435877298Sobrien	    number_to_chars_bigendian (p, wval, 4);
435977298Sobrien	  else
436077298Sobrien	    number_to_chars_littleendian (p, wval, 4);
436177298Sobrien	  p += 4;
436277298Sobrien	  count -= 4;
436377298Sobrien	  fix += 4;
436477298Sobrien	}
436577298Sobrien
436677298Sobrien      if (INSN_BIG_ENDIAN)
436777298Sobrien	number_to_chars_bigendian (p, 0x01000000, 4);
436877298Sobrien      else
436977298Sobrien	number_to_chars_littleendian (p, 0x01000000, 4);
437077298Sobrien
437177298Sobrien      fragp->fr_fix += fix;
437277298Sobrien      fragp->fr_var = 4;
437377298Sobrien      break;
437477298Sobrien
437577298Sobrien    default:
437677298Sobrien      break;
437759024Sobrien    }
437859024Sobrien}
437959024Sobrien
438059024Sobrien#ifdef OBJ_ELF
438159024Sobrien/* Some special processing for a Sparc ELF file.  */
438259024Sobrien
438359024Sobrienvoid
438459024Sobriensparc_elf_final_processing ()
438559024Sobrien{
438659024Sobrien  /* Set the Sparc ELF flag bits.  FIXME: There should probably be some
438759024Sobrien     sort of BFD interface for this.  */
438859024Sobrien  if (sparc_arch_size == 64)
438960484Sobrien    {
439060484Sobrien      switch (sparc_memory_model)
439160484Sobrien	{
439260484Sobrien	case MM_RMO:
439360484Sobrien	  elf_elfheader (stdoutput)->e_flags |= EF_SPARCV9_RMO;
439460484Sobrien	  break;
439560484Sobrien	case MM_PSO:
439660484Sobrien	  elf_elfheader (stdoutput)->e_flags |= EF_SPARCV9_PSO;
439760484Sobrien	  break;
439860484Sobrien	default:
439960484Sobrien	  break;
440060484Sobrien	}
440160484Sobrien    }
440259024Sobrien  else if (current_architecture >= SPARC_OPCODE_ARCH_V9)
440359024Sobrien    elf_elfheader (stdoutput)->e_flags |= EF_SPARC_32PLUS;
440459024Sobrien  if (current_architecture == SPARC_OPCODE_ARCH_V9A)
440559024Sobrien    elf_elfheader (stdoutput)->e_flags |= EF_SPARC_SUN_US1;
440677298Sobrien  else if (current_architecture == SPARC_OPCODE_ARCH_V9B)
440777298Sobrien    elf_elfheader (stdoutput)->e_flags |= EF_SPARC_SUN_US1|EF_SPARC_SUN_US3;
440859024Sobrien}
440989857Sobrien
441089857Sobrienvoid
441189857Sobriensparc_cons (exp, size)
441289857Sobrien     expressionS *exp;
441389857Sobrien     int size;
441489857Sobrien{
441589857Sobrien  char *save;
441689857Sobrien
441789857Sobrien  SKIP_WHITESPACE ();
441889857Sobrien  sparc_cons_special_reloc = NULL;
441989857Sobrien  save = input_line_pointer;
442089857Sobrien  if (input_line_pointer[0] == '%'
442189857Sobrien      && input_line_pointer[1] == 'r'
442289857Sobrien      && input_line_pointer[2] == '_')
442389857Sobrien    {
442489857Sobrien      if (strncmp (input_line_pointer + 3, "disp", 4) == 0)
442589857Sobrien	{
442689857Sobrien	  input_line_pointer += 7;
442789857Sobrien	  sparc_cons_special_reloc = "disp";
442889857Sobrien	}
442989857Sobrien      else if (strncmp (input_line_pointer + 3, "plt", 3) == 0)
443089857Sobrien	{
443189857Sobrien	  if (size != 4 && size != 8)
443289857Sobrien	    as_bad (_("Illegal operands: %%r_plt in %d-byte data field"), size);
443389857Sobrien	  else
443489857Sobrien	    {
443589857Sobrien	      input_line_pointer += 6;
443689857Sobrien	      sparc_cons_special_reloc = "plt";
443789857Sobrien	    }
443889857Sobrien	}
4439130561Sobrien      else if (strncmp (input_line_pointer + 3, "tls_dtpoff", 10) == 0)
4440130561Sobrien	{
4441130561Sobrien	  if (size != 4 && size != 8)
4442130561Sobrien	    as_bad (_("Illegal operands: %%r_tls_dtpoff in %d-byte data field"), size);
4443130561Sobrien	  else
4444130561Sobrien	    {
4445130561Sobrien	      input_line_pointer += 13;
4446130561Sobrien	      sparc_cons_special_reloc = "tls_dtpoff";
4447130561Sobrien	    }
4448130561Sobrien	}
444989857Sobrien      if (sparc_cons_special_reloc)
445089857Sobrien	{
445189857Sobrien	  int bad = 0;
445289857Sobrien
445389857Sobrien	  switch (size)
445489857Sobrien	    {
445589857Sobrien	    case 1:
445689857Sobrien	      if (*input_line_pointer != '8')
445789857Sobrien		bad = 1;
445889857Sobrien	      input_line_pointer--;
445989857Sobrien	      break;
446089857Sobrien	    case 2:
446189857Sobrien	      if (input_line_pointer[0] != '1' || input_line_pointer[1] != '6')
446289857Sobrien		bad = 1;
446389857Sobrien	      break;
446489857Sobrien	    case 4:
446589857Sobrien	      if (input_line_pointer[0] != '3' || input_line_pointer[1] != '2')
446689857Sobrien		bad = 1;
446789857Sobrien	      break;
446889857Sobrien	    case 8:
446989857Sobrien	      if (input_line_pointer[0] != '6' || input_line_pointer[1] != '4')
447089857Sobrien		bad = 1;
447189857Sobrien	      break;
447289857Sobrien	    default:
447389857Sobrien	      bad = 1;
447489857Sobrien	      break;
447589857Sobrien	    }
447689857Sobrien
447789857Sobrien	  if (bad)
447889857Sobrien	    {
447989857Sobrien	      as_bad (_("Illegal operands: Only %%r_%s%d allowed in %d-byte data fields"),
448089857Sobrien		      sparc_cons_special_reloc, size * 8, size);
448189857Sobrien	    }
448289857Sobrien	  else
448389857Sobrien	    {
448489857Sobrien	      input_line_pointer += 2;
448589857Sobrien	      if (*input_line_pointer != '(')
448689857Sobrien		{
448789857Sobrien		  as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
448889857Sobrien			  sparc_cons_special_reloc, size * 8);
448989857Sobrien		  bad = 1;
449089857Sobrien		}
449189857Sobrien	    }
449289857Sobrien
449389857Sobrien	  if (bad)
449489857Sobrien	    {
449589857Sobrien	      input_line_pointer = save;
449689857Sobrien	      sparc_cons_special_reloc = NULL;
449789857Sobrien	    }
449889857Sobrien	  else
449989857Sobrien	    {
450089857Sobrien	      int c;
450189857Sobrien	      char *end = ++input_line_pointer;
450289857Sobrien	      int npar = 0;
450389857Sobrien
450489857Sobrien	      while (! is_end_of_line[(c = *end)])
450589857Sobrien		{
450689857Sobrien		  if (c == '(')
450789857Sobrien	  	    npar++;
450889857Sobrien		  else if (c == ')')
450989857Sobrien	  	    {
451089857Sobrien		      if (!npar)
451189857Sobrien	      		break;
451289857Sobrien		      npar--;
451389857Sobrien		    }
451489857Sobrien	    	  end++;
451589857Sobrien		}
451689857Sobrien
451789857Sobrien	      if (c != ')')
451889857Sobrien		as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
451989857Sobrien			sparc_cons_special_reloc, size * 8);
452089857Sobrien	      else
452189857Sobrien		{
452289857Sobrien		  *end = '\0';
452389857Sobrien		  expression (exp);
452489857Sobrien		  *end = c;
452589857Sobrien		  if (input_line_pointer != end)
452689857Sobrien		    {
452789857Sobrien		      as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
452889857Sobrien			      sparc_cons_special_reloc, size * 8);
452989857Sobrien		    }
453089857Sobrien		  else
453189857Sobrien		    {
453289857Sobrien		      input_line_pointer++;
453389857Sobrien		      SKIP_WHITESPACE ();
453489857Sobrien		      c = *input_line_pointer;
453589857Sobrien		      if (! is_end_of_line[c] && c != ',')
453689857Sobrien			as_bad (_("Illegal operands: garbage after %%r_%s%d()"),
453789857Sobrien			        sparc_cons_special_reloc, size * 8);
453889857Sobrien		    }
453989857Sobrien		}
454089857Sobrien	    }
454189857Sobrien	}
454289857Sobrien    }
454389857Sobrien  if (sparc_cons_special_reloc == NULL)
454489857Sobrien    expression (exp);
454589857Sobrien}
454689857Sobrien
454759024Sobrien#endif
454860484Sobrien
454960484Sobrien/* This is called by emit_expr via TC_CONS_FIX_NEW when creating a
455060484Sobrien   reloc for a cons.  We could use the definition there, except that
455160484Sobrien   we want to handle little endian relocs specially.  */
455260484Sobrien
455360484Sobrienvoid
455460484Sobriencons_fix_new_sparc (frag, where, nbytes, exp)
455560484Sobrien     fragS *frag;
455660484Sobrien     int where;
455760484Sobrien     unsigned int nbytes;
455860484Sobrien     expressionS *exp;
455960484Sobrien{
456060484Sobrien  bfd_reloc_code_real_type r;
456160484Sobrien
456260484Sobrien  r = (nbytes == 1 ? BFD_RELOC_8 :
456360484Sobrien       (nbytes == 2 ? BFD_RELOC_16 :
456460484Sobrien	(nbytes == 4 ? BFD_RELOC_32 : BFD_RELOC_64)));
456560484Sobrien
456678828Sobrien  if (target_little_endian_data
456778828Sobrien      && nbytes == 4
456877298Sobrien      && now_seg->flags & SEC_ALLOC)
456960484Sobrien    r = BFD_RELOC_SPARC_REV32;
457078828Sobrien
457189857Sobrien  if (sparc_cons_special_reloc)
457278828Sobrien    {
457389857Sobrien      if (*sparc_cons_special_reloc == 'd')
457489857Sobrien	switch (nbytes)
457589857Sobrien	  {
457689857Sobrien	  case 1: r = BFD_RELOC_8_PCREL; break;
457789857Sobrien	  case 2: r = BFD_RELOC_16_PCREL; break;
457889857Sobrien	  case 4: r = BFD_RELOC_32_PCREL; break;
457989857Sobrien	  case 8: r = BFD_RELOC_64_PCREL; break;
458089857Sobrien	  default: abort ();
458189857Sobrien	  }
4582130561Sobrien      else if (*sparc_cons_special_reloc == 'p')
458389857Sobrien	switch (nbytes)
458489857Sobrien	  {
458589857Sobrien	  case 4: r = BFD_RELOC_SPARC_PLT32; break;
458689857Sobrien	  case 8: r = BFD_RELOC_SPARC_PLT64; break;
458789857Sobrien	  }
4588130561Sobrien      else
4589130561Sobrien	switch (nbytes)
4590130561Sobrien	  {
4591130561Sobrien	  case 4: r = BFD_RELOC_SPARC_TLS_DTPOFF32; break;
4592130561Sobrien	  case 8: r = BFD_RELOC_SPARC_TLS_DTPOFF64; break;
4593130561Sobrien	  }
459489857Sobrien    }
459589857Sobrien  else if (sparc_no_align_cons)
459689857Sobrien    {
459778828Sobrien      switch (nbytes)
459878828Sobrien	{
459978828Sobrien	case 2: r = BFD_RELOC_SPARC_UA16; break;
460078828Sobrien	case 4: r = BFD_RELOC_SPARC_UA32; break;
460178828Sobrien	case 8: r = BFD_RELOC_SPARC_UA64; break;
460278828Sobrien	default: abort ();
460378828Sobrien	}
460489857Sobrien   }
460578828Sobrien
460660484Sobrien  fix_new_exp (frag, where, (int) nbytes, exp, 0, r);
4607130561Sobrien  sparc_cons_special_reloc = NULL;
460860484Sobrien}
460960484Sobrien
4610130561Sobrienvoid
4611130561Sobriensparc_cfi_frame_initial_instructions ()
4612130561Sobrien{
4613130561Sobrien  cfi_add_CFA_def_cfa (14, sparc_arch_size == 64 ? 0x7ff : 0);
4614130561Sobrien}
4615130561Sobrien
461660484Sobrienint
4617218822Sdimsparc_regname_to_dw2regnum (char *regname)
461860484Sobrien{
4619130561Sobrien  char *p, *q;
462077298Sobrien
4621130561Sobrien  if (!regname[0])
4622130561Sobrien    return -1;
4623130561Sobrien
4624130561Sobrien  q = "goli";
4625130561Sobrien  p = strchr (q, regname[0]);
4626130561Sobrien  if (p)
4627130561Sobrien    {
4628130561Sobrien      if (regname[1] < '0' || regname[1] > '8' || regname[2])
4629130561Sobrien	return -1;
4630130561Sobrien      return (p - q) * 8 + regname[1] - '0';
4631130561Sobrien    }
4632130561Sobrien  if (regname[0] == 's' && regname[1] == 'p' && !regname[2])
4633130561Sobrien    return 14;
4634130561Sobrien  if (regname[0] == 'f' && regname[1] == 'p' && !regname[2])
4635130561Sobrien    return 30;
4636130561Sobrien  if (regname[0] == 'f' || regname[0] == 'r')
4637130561Sobrien    {
4638130561Sobrien      unsigned int regnum;
4639130561Sobrien
4640130561Sobrien      regnum = strtoul (regname + 1, &q, 10);
4641130561Sobrien      if (p == q || *q)
4642130561Sobrien        return -1;
4643130561Sobrien      if (regnum >= ((regname[0] == 'f'
4644130561Sobrien		      && SPARC_OPCODE_ARCH_V9_P (max_architecture))
4645130561Sobrien		     ? 64 : 32))
4646130561Sobrien	return -1;
4647130561Sobrien      if (regname[0] == 'f')
4648130561Sobrien	{
4649130561Sobrien          regnum += 32;
4650130561Sobrien          if (regnum >= 64 && (regnum & 1))
4651130561Sobrien	    return -1;
4652130561Sobrien        }
4653130561Sobrien      return regnum;
4654130561Sobrien    }
4655130561Sobrien  return -1;
465660484Sobrien}
4657130561Sobrien
4658130561Sobrienvoid
4659130561Sobriensparc_cfi_emit_pcrel_expr (expressionS *exp, unsigned int nbytes)
4660130561Sobrien{
4661130561Sobrien  sparc_cons_special_reloc = "disp";
4662130561Sobrien  sparc_no_align_cons = 1;
4663130561Sobrien  emit_expr (exp, nbytes);
4664130561Sobrien  sparc_no_align_cons = 0;
4665130561Sobrien  sparc_cons_special_reloc = NULL;
4666130561Sobrien}
4667