tc-sparc.c revision 89857
159024Sobrien/* tc-sparc.c -- Assemble for the SPARC
278828Sobrien   Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
378828Sobrien   1999, 2000, 2001
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
1959024Sobrien   to the Free Software Foundation, 59 Temple Place - Suite 330,
2077298Sobrien   Boston, MA 02111-1307, USA.  */
2159024Sobrien
2259024Sobrien#include <stdio.h>
2359024Sobrien
2459024Sobrien#include "as.h"
2589857Sobrien#include "safe-ctype.h"
2659024Sobrien#include "subsegs.h"
2759024Sobrien
2859024Sobrien#include "opcode/sparc.h"
2959024Sobrien
3059024Sobrien#ifdef OBJ_ELF
3159024Sobrien#include "elf/sparc.h"
3277298Sobrien#include "dwarf2dbg.h"
3359024Sobrien#endif
3459024Sobrien
3559024Sobrienstatic struct sparc_arch *lookup_arch PARAMS ((char *));
3659024Sobrienstatic void init_default_arch PARAMS ((void));
3760484Sobrienstatic int sparc_ip PARAMS ((char *, const struct sparc_opcode **));
3859024Sobrienstatic int in_signed_range PARAMS ((bfd_signed_vma, bfd_signed_vma));
3959024Sobrienstatic int in_unsigned_range PARAMS ((bfd_vma, bfd_vma));
4059024Sobrienstatic int in_bitfield_range PARAMS ((bfd_signed_vma, bfd_signed_vma));
4159024Sobrienstatic int sparc_ffs PARAMS ((unsigned int));
4260484Sobrienstatic void synthetize_setuw PARAMS ((const struct sparc_opcode *));
4360484Sobrienstatic void synthetize_setsw PARAMS ((const struct sparc_opcode *));
4460484Sobrienstatic void synthetize_setx PARAMS ((const struct sparc_opcode *));
4559024Sobrienstatic bfd_vma BSR PARAMS ((bfd_vma, int));
4659024Sobrienstatic int cmp_reg_entry PARAMS ((const PTR, const PTR));
4759024Sobrienstatic int parse_keyword_arg PARAMS ((int (*) (const char *), char **, int *));
4859024Sobrienstatic int parse_const_expr_arg PARAMS ((char **, int *));
4959024Sobrienstatic int get_expression PARAMS ((char *str));
5059024Sobrien
5159024Sobrien/* Default architecture.  */
5259024Sobrien/* ??? The default value should be V8, but sparclite support was added
5359024Sobrien   by making it the default.  GCC now passes -Asparclite, so maybe sometime in
5459024Sobrien   the future we can set this to V8.  */
5559024Sobrien#ifndef DEFAULT_ARCH
5659024Sobrien#define DEFAULT_ARCH "sparclite"
5759024Sobrien#endif
5859024Sobrienstatic char *default_arch = DEFAULT_ARCH;
5959024Sobrien
6059024Sobrien/* Non-zero if the initial values of `max_architecture' and `sparc_arch_size'
6159024Sobrien   have been set.  */
6259024Sobrienstatic int default_init_p;
6359024Sobrien
6459024Sobrien/* Current architecture.  We don't bump up unless necessary.  */
6559024Sobrienstatic enum sparc_opcode_arch_val current_architecture = SPARC_OPCODE_ARCH_V6;
6659024Sobrien
6759024Sobrien/* The maximum architecture level we can bump up to.
6859024Sobrien   In a 32 bit environment, don't allow bumping up to v9 by default.
6959024Sobrien   The native assembler works this way.  The user is required to pass
7059024Sobrien   an explicit argument before we'll create v9 object files.  However, if
7159024Sobrien   we don't see any v9 insns, a v8plus object file is not created.  */
7259024Sobrienstatic enum sparc_opcode_arch_val max_architecture;
7359024Sobrien
7459024Sobrien/* Either 32 or 64, selects file format.  */
7559024Sobrienstatic int sparc_arch_size;
7659024Sobrien/* Initial (default) value, recorded separately in case a user option
7759024Sobrien   changes the value before md_show_usage is called.  */
7859024Sobrienstatic int default_arch_size;
7959024Sobrien
8059024Sobrien#ifdef OBJ_ELF
8159024Sobrien/* The currently selected v9 memory model.  Currently only used for
8259024Sobrien   ELF.  */
8359024Sobrienstatic enum { MM_TSO, MM_PSO, MM_RMO } sparc_memory_model = MM_RMO;
8459024Sobrien#endif
8559024Sobrien
8659024Sobrienstatic int architecture_requested;
8759024Sobrienstatic int warn_on_bump;
8859024Sobrien
8959024Sobrien/* If warn_on_bump and the needed architecture is higher than this
9059024Sobrien   architecture, issue a warning.  */
9159024Sobrienstatic enum sparc_opcode_arch_val warn_after_architecture;
9259024Sobrien
9360484Sobrien/* Non-zero if as should generate error if an undeclared g[23] register
9460484Sobrien   has been used in -64.  */
9560484Sobrienstatic int no_undeclared_regs;
9660484Sobrien
9777298Sobrien/* Non-zero if we should try to relax jumps and calls.  */
9877298Sobrienstatic int sparc_relax;
9977298Sobrien
10059024Sobrien/* Non-zero if we are generating PIC code.  */
10159024Sobrienint sparc_pic_code;
10259024Sobrien
10359024Sobrien/* Non-zero if we should give an error when misaligned data is seen.  */
10459024Sobrienstatic int enforce_aligned_data;
10559024Sobrien
10659024Sobrienextern int target_big_endian;
10759024Sobrien
10860484Sobrienstatic int target_little_endian_data;
10960484Sobrien
11060484Sobrien/* Symbols for global registers on v9.  */
11160484Sobrienstatic symbolS *globals[8];
11260484Sobrien
11360484Sobrien/* V9 and 86x have big and little endian data, but instructions are always big
11460484Sobrien   endian.  The sparclet has bi-endian support but both data and insns have
11560484Sobrien   the same endianness.  Global `target_big_endian' is used for data.
11660484Sobrien   The following macro is used for instructions.  */
11760484Sobrien#ifndef INSN_BIG_ENDIAN
11859024Sobrien#define INSN_BIG_ENDIAN (target_big_endian \
11960484Sobrien			 || default_arch_type == sparc86x \
12059024Sobrien			 || SPARC_OPCODE_ARCH_V9_P (max_architecture))
12160484Sobrien#endif
12259024Sobrien
12377298Sobrien/* Handle of the OPCODE hash table.  */
12459024Sobrienstatic struct hash_control *op_hash;
12559024Sobrien
12660484Sobrienstatic int log2 PARAMS ((int));
12759024Sobrienstatic void s_data1 PARAMS ((void));
12859024Sobrienstatic void s_seg PARAMS ((int));
12959024Sobrienstatic void s_proc PARAMS ((int));
13059024Sobrienstatic void s_reserve PARAMS ((int));
13159024Sobrienstatic void s_common PARAMS ((int));
13259024Sobrienstatic void s_empty PARAMS ((int));
13359024Sobrienstatic void s_uacons PARAMS ((int));
13460484Sobrienstatic void s_ncons PARAMS ((int));
13560484Sobrienstatic void s_register PARAMS ((int));
13659024Sobrien
13759024Sobrienconst pseudo_typeS md_pseudo_table[] =
13859024Sobrien{
13977298Sobrien  {"align", s_align_bytes, 0},	/* Defaulting is invalid (0).  */
14059024Sobrien  {"common", s_common, 0},
14159024Sobrien  {"empty", s_empty, 0},
14259024Sobrien  {"global", s_globl, 0},
14359024Sobrien  {"half", cons, 2},
14460484Sobrien  {"nword", s_ncons, 0},
14559024Sobrien  {"optim", s_ignore, 0},
14659024Sobrien  {"proc", s_proc, 0},
14759024Sobrien  {"reserve", s_reserve, 0},
14859024Sobrien  {"seg", s_seg, 0},
14959024Sobrien  {"skip", s_space, 0},
15059024Sobrien  {"word", cons, 4},
15159024Sobrien  {"xword", cons, 8},
15259024Sobrien  {"uahalf", s_uacons, 2},
15359024Sobrien  {"uaword", s_uacons, 4},
15459024Sobrien  {"uaxword", s_uacons, 8},
15559024Sobrien#ifdef OBJ_ELF
15677298Sobrien  {"file", dwarf2_directive_file, 0},
15777298Sobrien  {"loc", dwarf2_directive_loc, 0},
15877298Sobrien  /* These are specific to sparc/svr4.  */
15959024Sobrien  {"2byte", s_uacons, 2},
16059024Sobrien  {"4byte", s_uacons, 4},
16159024Sobrien  {"8byte", s_uacons, 8},
16260484Sobrien  {"register", s_register, 0},
16359024Sobrien#endif
16459024Sobrien  {NULL, 0, 0},
16559024Sobrien};
16659024Sobrien
16777298Sobrien/* Size of relocation record.  */
16877298Sobrienconst int md_reloc_size = 12;
16959024Sobrien
17059024Sobrien/* This array holds the chars that always start a comment.  If the
17177298Sobrien   pre-processor is disabled, these aren't very useful.  */
17277298Sobrienconst char comment_chars[] = "!";	/* JF removed '|' from
17377298Sobrien                                           comment_chars.  */
17459024Sobrien
17559024Sobrien/* This array holds the chars that only start a comment at the beginning of
17659024Sobrien   a line.  If the line seems to have the form '# 123 filename'
17777298Sobrien   .line and .file directives will appear in the pre-processed output.  */
17859024Sobrien/* Note that input_file.c hand checks for '#' at the beginning of the
17959024Sobrien   first line of the input file.  This is because the compiler outputs
18077298Sobrien   #NO_APP at the beginning of its output.  */
18159024Sobrien/* Also note that comments started like this one will always
18277298Sobrien   work if '/' isn't otherwise defined.  */
18359024Sobrienconst char line_comment_chars[] = "#";
18459024Sobrien
18577298Sobrienconst char line_separator_chars[] = ";";
18659024Sobrien
18777298Sobrien/* Chars that can be used to separate mant from exp in floating point
18877298Sobrien   nums.  */
18959024Sobrienconst char EXP_CHARS[] = "eE";
19059024Sobrien
19177298Sobrien/* Chars that mean this number is a floating point constant.
19277298Sobrien   As in 0f12.456
19377298Sobrien   or    0d1.2345e12  */
19459024Sobrienconst char FLT_CHARS[] = "rRsSfFdDxXpP";
19559024Sobrien
19659024Sobrien/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
19759024Sobrien   changed in read.c.  Ideally it shouldn't have to know about it at all,
19859024Sobrien   but nothing is ideal around here.  */
19959024Sobrien
20077298Sobrien#define isoctal(c)  ((unsigned) ((c) - '0') < '8')
20159024Sobrien
20259024Sobrienstruct sparc_it
20359024Sobrien  {
20459024Sobrien    char *error;
20559024Sobrien    unsigned long opcode;
20659024Sobrien    struct nlist *nlistp;
20759024Sobrien    expressionS exp;
20860484Sobrien    expressionS exp2;
20959024Sobrien    int pcrel;
21059024Sobrien    bfd_reloc_code_real_type reloc;
21159024Sobrien  };
21259024Sobrien
21359024Sobrienstruct sparc_it the_insn, set_insn;
21459024Sobrien
21559024Sobrienstatic void output_insn
21659024Sobrien  PARAMS ((const struct sparc_opcode *, struct sparc_it *));
21759024Sobrien
21859024Sobrien/* Table of arguments to -A.
21959024Sobrien   The sparc_opcode_arch table in sparc-opc.c is insufficient and incorrect
22059024Sobrien   for this use.  That table is for opcodes only.  This table is for opcodes
22159024Sobrien   and file formats.  */
22259024Sobrien
22360484Sobrienenum sparc_arch_types {v6, v7, v8, sparclet, sparclite, sparc86x, v8plus,
22477298Sobrien		       v8plusa, v9, v9a, v9b, v9_64};
22560484Sobrien
22659024Sobrienstatic struct sparc_arch {
22759024Sobrien  char *name;
22859024Sobrien  char *opcode_arch;
22960484Sobrien  enum sparc_arch_types arch_type;
23059024Sobrien  /* Default word size, as specified during configuration.
23159024Sobrien     A value of zero means can't be used to specify default architecture.  */
23259024Sobrien  int default_arch_size;
23359024Sobrien  /* Allowable arg to -A?  */
23459024Sobrien  int user_option_p;
23559024Sobrien} sparc_arch_table[] = {
23660484Sobrien  { "v6", "v6", v6, 0, 1 },
23760484Sobrien  { "v7", "v7", v7, 0, 1 },
23860484Sobrien  { "v8", "v8", v8, 32, 1 },
23960484Sobrien  { "sparclet", "sparclet", sparclet, 32, 1 },
24060484Sobrien  { "sparclite", "sparclite", sparclite, 32, 1 },
24160484Sobrien  { "sparc86x", "sparclite", sparc86x, 32, 1 },
24260484Sobrien  { "v8plus", "v9", v9, 0, 1 },
24360484Sobrien  { "v8plusa", "v9a", v9, 0, 1 },
24477298Sobrien  { "v8plusb", "v9b", v9, 0, 1 },
24560484Sobrien  { "v9", "v9", v9, 0, 1 },
24660484Sobrien  { "v9a", "v9a", v9, 0, 1 },
24777298Sobrien  { "v9b", "v9b", v9, 0, 1 },
24859024Sobrien  /* This exists to allow configure.in/Makefile.in to pass one
24959024Sobrien     value to specify both the default machine and default word size.  */
25060484Sobrien  { "v9-64", "v9", v9, 64, 0 },
25160484Sobrien  { NULL, NULL, v8, 0, 0 }
25259024Sobrien};
25359024Sobrien
25460484Sobrien/* Variant of default_arch */
25560484Sobrienstatic enum sparc_arch_types default_arch_type;
25660484Sobrien
25759024Sobrienstatic struct sparc_arch *
25859024Sobrienlookup_arch (name)
25959024Sobrien     char *name;
26059024Sobrien{
26159024Sobrien  struct sparc_arch *sa;
26259024Sobrien
26359024Sobrien  for (sa = &sparc_arch_table[0]; sa->name != NULL; sa++)
26459024Sobrien    if (strcmp (sa->name, name) == 0)
26559024Sobrien      break;
26659024Sobrien  if (sa->name == NULL)
26759024Sobrien    return NULL;
26859024Sobrien  return sa;
26959024Sobrien}
27059024Sobrien
27159024Sobrien/* Initialize the default opcode arch and word size from the default
27259024Sobrien   architecture name.  */
27359024Sobrien
27459024Sobrienstatic void
27559024Sobrieninit_default_arch ()
27659024Sobrien{
27759024Sobrien  struct sparc_arch *sa = lookup_arch (default_arch);
27859024Sobrien
27959024Sobrien  if (sa == NULL
28059024Sobrien      || sa->default_arch_size == 0)
28160484Sobrien    as_fatal (_("Invalid default architecture, broken assembler."));
28259024Sobrien
28359024Sobrien  max_architecture = sparc_opcode_lookup_arch (sa->opcode_arch);
28459024Sobrien  if (max_architecture == SPARC_OPCODE_ARCH_BAD)
28560484Sobrien    as_fatal (_("Bad opcode table, broken assembler."));
28659024Sobrien  default_arch_size = sparc_arch_size = sa->default_arch_size;
28759024Sobrien  default_init_p = 1;
28860484Sobrien  default_arch_type = sa->arch_type;
28959024Sobrien}
29059024Sobrien
29159024Sobrien/* Called by TARGET_FORMAT.  */
29259024Sobrien
29359024Sobrienconst char *
29459024Sobriensparc_target_format ()
29559024Sobrien{
29659024Sobrien  /* We don't get a chance to initialize anything before we're called,
29759024Sobrien     so handle that now.  */
29859024Sobrien  if (! default_init_p)
29959024Sobrien    init_default_arch ();
30059024Sobrien
30159024Sobrien#ifdef OBJ_AOUT
30259024Sobrien#ifdef TE_NetBSD
30359024Sobrien  return "a.out-sparc-netbsd";
30459024Sobrien#else
30559024Sobrien#ifdef TE_SPARCAOUT
30660484Sobrien  if (target_big_endian)
30760484Sobrien    return "a.out-sunos-big";
30860484Sobrien  else if (default_arch_type == sparc86x && target_little_endian_data)
30960484Sobrien    return "a.out-sunos-big";
31077298Sobrien  else
31177298Sobrien    return "a.out-sparc-little";
31259024Sobrien#else
31359024Sobrien  return "a.out-sunos-big";
31459024Sobrien#endif
31559024Sobrien#endif
31659024Sobrien#endif
31759024Sobrien
31859024Sobrien#ifdef OBJ_BOUT
31959024Sobrien  return "b.out.big";
32059024Sobrien#endif
32159024Sobrien
32259024Sobrien#ifdef OBJ_COFF
32359024Sobrien#ifdef TE_LYNX
32459024Sobrien  return "coff-sparc-lynx";
32559024Sobrien#else
32659024Sobrien  return "coff-sparc";
32759024Sobrien#endif
32859024Sobrien#endif
32959024Sobrien
33059024Sobrien#ifdef OBJ_ELF
33159024Sobrien  return sparc_arch_size == 64 ? "elf64-sparc" : "elf32-sparc";
33259024Sobrien#endif
33359024Sobrien
33459024Sobrien  abort ();
33559024Sobrien}
33659024Sobrien
33777298Sobrien/* md_parse_option
33859024Sobrien *	Invocation line includes a switch not recognized by the base assembler.
33959024Sobrien *	See if it's a processor-specific option.  These are:
34059024Sobrien *
34159024Sobrien *	-bump
34259024Sobrien *		Warn on architecture bumps.  See also -A.
34359024Sobrien *
34459024Sobrien *	-Av6, -Av7, -Av8, -Asparclite, -Asparclet
34559024Sobrien *		Standard 32 bit architectures.
34677298Sobrien *	-Av9, -Av9a, -Av9b
34759024Sobrien *		Sparc64 in either a 32 or 64 bit world (-32/-64 says which).
34859024Sobrien *		This used to only mean 64 bits, but properly specifying it
34959024Sobrien *		complicated gcc's ASM_SPECs, so now opcode selection is
35059024Sobrien *		specified orthogonally to word size (except when specifying
35159024Sobrien *		the default, but that is an internal implementation detail).
35277298Sobrien *	-Av8plus, -Av8plusa, -Av8plusb
35377298Sobrien *		Same as -Av9{,a,b}.
35477298Sobrien *	-xarch=v8plus, -xarch=v8plusa, -xarch=v8plusb
35577298Sobrien *		Same as -Av8plus{,a,b} -32, for compatibility with Sun's
35677298Sobrien *		assembler.
35777298Sobrien *	-xarch=v9, -xarch=v9a, -xarch=v9b
35877298Sobrien *		Same as -Av9{,a,b} -64, for compatibility with Sun's
35977298Sobrien *		assembler.
36059024Sobrien *
36159024Sobrien *		Select the architecture and possibly the file format.
36259024Sobrien *		Instructions or features not supported by the selected
36359024Sobrien *		architecture cause fatal errors.
36459024Sobrien *
36559024Sobrien *		The default is to start at v6, and bump the architecture up
36659024Sobrien *		whenever an instruction is seen at a higher level.  In 32 bit
36759024Sobrien *		environments, v9 is not bumped up to, the user must pass
36877298Sobrien * 		-Av8plus{,a,b}.
36959024Sobrien *
37059024Sobrien *		If -bump is specified, a warning is printing when bumping to
37159024Sobrien *		higher levels.
37259024Sobrien *
37359024Sobrien *		If an architecture is specified, all instructions must match
37459024Sobrien *		that architecture.  Any higher level instructions are flagged
37559024Sobrien *		as errors.  Note that in the 32 bit environment specifying
37659024Sobrien *		-Av8plus does not automatically create a v8plus object file, a
37759024Sobrien *		v9 insn must be seen.
37859024Sobrien *
37959024Sobrien *		If both an architecture and -bump are specified, the
38059024Sobrien *		architecture starts at the specified level, but bumps are
38159024Sobrien *		warnings.  Note that we can't set `current_architecture' to
38259024Sobrien *		the requested level in this case: in the 32 bit environment,
38359024Sobrien *		we still must avoid creating v8plus object files unless v9
38459024Sobrien * 		insns are seen.
38559024Sobrien *
38659024Sobrien * Note:
38759024Sobrien *		Bumping between incompatible architectures is always an
38859024Sobrien *		error.  For example, from sparclite to v9.
38959024Sobrien */
39059024Sobrien
39159024Sobrien#ifdef OBJ_ELF
39259024SobrienCONST char *md_shortopts = "A:K:VQ:sq";
39359024Sobrien#else
39459024Sobrien#ifdef OBJ_AOUT
39559024SobrienCONST char *md_shortopts = "A:k";
39659024Sobrien#else
39759024SobrienCONST char *md_shortopts = "A:";
39859024Sobrien#endif
39959024Sobrien#endif
40059024Sobrienstruct option md_longopts[] = {
40159024Sobrien#define OPTION_BUMP (OPTION_MD_BASE)
40259024Sobrien  {"bump", no_argument, NULL, OPTION_BUMP},
40359024Sobrien#define OPTION_SPARC (OPTION_MD_BASE + 1)
40459024Sobrien  {"sparc", no_argument, NULL, OPTION_SPARC},
40559024Sobrien#define OPTION_XARCH (OPTION_MD_BASE + 2)
40659024Sobrien  {"xarch", required_argument, NULL, OPTION_XARCH},
40759024Sobrien#ifdef OBJ_ELF
40859024Sobrien#define OPTION_32 (OPTION_MD_BASE + 3)
40959024Sobrien  {"32", no_argument, NULL, OPTION_32},
41059024Sobrien#define OPTION_64 (OPTION_MD_BASE + 4)
41159024Sobrien  {"64", no_argument, NULL, OPTION_64},
41259024Sobrien#define OPTION_TSO (OPTION_MD_BASE + 5)
41359024Sobrien  {"TSO", no_argument, NULL, OPTION_TSO},
41459024Sobrien#define OPTION_PSO (OPTION_MD_BASE + 6)
41559024Sobrien  {"PSO", no_argument, NULL, OPTION_PSO},
41659024Sobrien#define OPTION_RMO (OPTION_MD_BASE + 7)
41759024Sobrien  {"RMO", no_argument, NULL, OPTION_RMO},
41859024Sobrien#endif
41959024Sobrien#ifdef SPARC_BIENDIAN
42059024Sobrien#define OPTION_LITTLE_ENDIAN (OPTION_MD_BASE + 8)
42159024Sobrien  {"EL", no_argument, NULL, OPTION_LITTLE_ENDIAN},
42259024Sobrien#define OPTION_BIG_ENDIAN (OPTION_MD_BASE + 9)
42359024Sobrien  {"EB", no_argument, NULL, OPTION_BIG_ENDIAN},
42459024Sobrien#endif
42559024Sobrien#define OPTION_ENFORCE_ALIGNED_DATA (OPTION_MD_BASE + 10)
42659024Sobrien  {"enforce-aligned-data", no_argument, NULL, OPTION_ENFORCE_ALIGNED_DATA},
42760484Sobrien#define OPTION_LITTLE_ENDIAN_DATA (OPTION_MD_BASE + 11)
42860484Sobrien  {"little-endian-data", no_argument, NULL, OPTION_LITTLE_ENDIAN_DATA},
42960484Sobrien#ifdef OBJ_ELF
43060484Sobrien#define OPTION_NO_UNDECLARED_REGS (OPTION_MD_BASE + 12)
43160484Sobrien  {"no-undeclared-regs", no_argument, NULL, OPTION_NO_UNDECLARED_REGS},
43260484Sobrien#define OPTION_UNDECLARED_REGS (OPTION_MD_BASE + 13)
43360484Sobrien  {"undeclared-regs", no_argument, NULL, OPTION_UNDECLARED_REGS},
43460484Sobrien#endif
43577298Sobrien#define OPTION_RELAX (OPTION_MD_BASE + 14)
43677298Sobrien  {"relax", no_argument, NULL, OPTION_RELAX},
43777298Sobrien#define OPTION_NO_RELAX (OPTION_MD_BASE + 15)
43877298Sobrien  {"no-relax", no_argument, NULL, OPTION_NO_RELAX},
43959024Sobrien  {NULL, no_argument, NULL, 0}
44059024Sobrien};
44159024Sobrien
44277298Sobriensize_t md_longopts_size = sizeof (md_longopts);
44377298Sobrien
44459024Sobrienint
44559024Sobrienmd_parse_option (c, arg)
44659024Sobrien     int c;
44759024Sobrien     char *arg;
44859024Sobrien{
44959024Sobrien  /* We don't get a chance to initialize anything before we're called,
45059024Sobrien     so handle that now.  */
45159024Sobrien  if (! default_init_p)
45259024Sobrien    init_default_arch ();
45359024Sobrien
45459024Sobrien  switch (c)
45559024Sobrien    {
45659024Sobrien    case OPTION_BUMP:
45759024Sobrien      warn_on_bump = 1;
45859024Sobrien      warn_after_architecture = SPARC_OPCODE_ARCH_V6;
45959024Sobrien      break;
46059024Sobrien
46159024Sobrien    case OPTION_XARCH:
46277298Sobrien#ifdef OBJ_ELF
46377298Sobrien      if (strncmp (arg, "v9", 2) != 0)
46477298Sobrien	md_parse_option (OPTION_32, NULL);
46577298Sobrien      else
46677298Sobrien	md_parse_option (OPTION_64, NULL);
46777298Sobrien#endif
46877298Sobrien      /* Fall through.  */
46959024Sobrien
47059024Sobrien    case 'A':
47159024Sobrien      {
47259024Sobrien	struct sparc_arch *sa;
47359024Sobrien	enum sparc_opcode_arch_val opcode_arch;
47459024Sobrien
47559024Sobrien	sa = lookup_arch (arg);
47659024Sobrien	if (sa == NULL
47759024Sobrien	    || ! sa->user_option_p)
47859024Sobrien	  {
47977298Sobrien	    if (c == OPTION_XARCH)
48077298Sobrien	      as_bad (_("invalid architecture -xarch=%s"), arg);
48177298Sobrien	    else
48277298Sobrien	      as_bad (_("invalid architecture -A%s"), arg);
48359024Sobrien	    return 0;
48459024Sobrien	  }
48559024Sobrien
48659024Sobrien	opcode_arch = sparc_opcode_lookup_arch (sa->opcode_arch);
48759024Sobrien	if (opcode_arch == SPARC_OPCODE_ARCH_BAD)
48860484Sobrien	  as_fatal (_("Bad opcode table, broken assembler."));
48959024Sobrien
49059024Sobrien	max_architecture = opcode_arch;
49159024Sobrien	architecture_requested = 1;
49259024Sobrien      }
49359024Sobrien      break;
49459024Sobrien
49559024Sobrien    case OPTION_SPARC:
49659024Sobrien      /* Ignore -sparc, used by SunOS make default .s.o rule.  */
49759024Sobrien      break;
49859024Sobrien
49959024Sobrien    case OPTION_ENFORCE_ALIGNED_DATA:
50059024Sobrien      enforce_aligned_data = 1;
50159024Sobrien      break;
50259024Sobrien
50359024Sobrien#ifdef SPARC_BIENDIAN
50459024Sobrien    case OPTION_LITTLE_ENDIAN:
50559024Sobrien      target_big_endian = 0;
50660484Sobrien      if (default_arch_type != sparclet)
50760484Sobrien	as_fatal ("This target does not support -EL");
50859024Sobrien      break;
50960484Sobrien    case OPTION_LITTLE_ENDIAN_DATA:
51060484Sobrien      target_little_endian_data = 1;
51160484Sobrien      target_big_endian = 0;
51260484Sobrien      if (default_arch_type != sparc86x
51360484Sobrien	  && default_arch_type != v9)
51460484Sobrien	as_fatal ("This target does not support --little-endian-data");
51560484Sobrien      break;
51659024Sobrien    case OPTION_BIG_ENDIAN:
51759024Sobrien      target_big_endian = 1;
51859024Sobrien      break;
51959024Sobrien#endif
52059024Sobrien
52159024Sobrien#ifdef OBJ_AOUT
52259024Sobrien    case 'k':
52359024Sobrien      sparc_pic_code = 1;
52459024Sobrien      break;
52559024Sobrien#endif
52659024Sobrien
52759024Sobrien#ifdef OBJ_ELF
52859024Sobrien    case OPTION_32:
52959024Sobrien    case OPTION_64:
53059024Sobrien      {
53159024Sobrien	const char **list, **l;
53259024Sobrien
53359024Sobrien	sparc_arch_size = c == OPTION_32 ? 32 : 64;
53459024Sobrien	list = bfd_target_list ();
53559024Sobrien	for (l = list; *l != NULL; l++)
53659024Sobrien	  {
53759024Sobrien	    if (sparc_arch_size == 32)
53859024Sobrien	      {
53959024Sobrien		if (strcmp (*l, "elf32-sparc") == 0)
54059024Sobrien		  break;
54159024Sobrien	      }
54259024Sobrien	    else
54359024Sobrien	      {
54459024Sobrien		if (strcmp (*l, "elf64-sparc") == 0)
54559024Sobrien		  break;
54659024Sobrien	      }
54759024Sobrien	  }
54859024Sobrien	if (*l == NULL)
54960484Sobrien	  as_fatal (_("No compiled in support for %d bit object file format"),
55059024Sobrien		    sparc_arch_size);
55159024Sobrien	free (list);
55259024Sobrien      }
55359024Sobrien      break;
55459024Sobrien
55559024Sobrien    case OPTION_TSO:
55659024Sobrien      sparc_memory_model = MM_TSO;
55759024Sobrien      break;
55859024Sobrien
55959024Sobrien    case OPTION_PSO:
56059024Sobrien      sparc_memory_model = MM_PSO;
56159024Sobrien      break;
56259024Sobrien
56359024Sobrien    case OPTION_RMO:
56459024Sobrien      sparc_memory_model = MM_RMO;
56559024Sobrien      break;
56659024Sobrien
56759024Sobrien    case 'V':
56859024Sobrien      print_version_id ();
56959024Sobrien      break;
57059024Sobrien
57159024Sobrien    case 'Q':
57259024Sobrien      /* Qy - do emit .comment
57377298Sobrien	 Qn - do not emit .comment.  */
57459024Sobrien      break;
57559024Sobrien
57659024Sobrien    case 's':
57777298Sobrien      /* Use .stab instead of .stab.excl.  */
57859024Sobrien      break;
57959024Sobrien
58059024Sobrien    case 'q':
58177298Sobrien      /* quick -- Native assembler does fewer checks.  */
58259024Sobrien      break;
58359024Sobrien
58459024Sobrien    case 'K':
58559024Sobrien      if (strcmp (arg, "PIC") != 0)
58660484Sobrien	as_warn (_("Unrecognized option following -K"));
58759024Sobrien      else
58859024Sobrien	sparc_pic_code = 1;
58959024Sobrien      break;
59060484Sobrien
59160484Sobrien    case OPTION_NO_UNDECLARED_REGS:
59260484Sobrien      no_undeclared_regs = 1;
59360484Sobrien      break;
59460484Sobrien
59560484Sobrien    case OPTION_UNDECLARED_REGS:
59660484Sobrien      no_undeclared_regs = 0;
59760484Sobrien      break;
59859024Sobrien#endif
59959024Sobrien
60077298Sobrien    case OPTION_RELAX:
60177298Sobrien      sparc_relax = 1;
60277298Sobrien      break;
60377298Sobrien
60477298Sobrien    case OPTION_NO_RELAX:
60577298Sobrien      sparc_relax = 0;
60677298Sobrien      break;
60777298Sobrien
60859024Sobrien    default:
60959024Sobrien      return 0;
61059024Sobrien    }
61159024Sobrien
61259024Sobrien  return 1;
61359024Sobrien}
61459024Sobrien
61559024Sobrienvoid
61659024Sobrienmd_show_usage (stream)
61759024Sobrien     FILE *stream;
61859024Sobrien{
61959024Sobrien  const struct sparc_arch *arch;
62077298Sobrien  int column;
62159024Sobrien
62259024Sobrien  /* We don't get a chance to initialize anything before we're called,
62359024Sobrien     so handle that now.  */
62459024Sobrien  if (! default_init_p)
62559024Sobrien    init_default_arch ();
62659024Sobrien
62777298Sobrien  fprintf (stream, _("SPARC options:\n"));
62877298Sobrien  column = 0;
62959024Sobrien  for (arch = &sparc_arch_table[0]; arch->name; arch++)
63059024Sobrien    {
63177298Sobrien      if (!arch->user_option_p)
63277298Sobrien	continue;
63359024Sobrien      if (arch != &sparc_arch_table[0])
63459024Sobrien	fprintf (stream, " | ");
63589857Sobrien      if (column + strlen (arch->name) > 70)
63677298Sobrien	{
63777298Sobrien	  column = 0;
63877298Sobrien	  fputc ('\n', stream);
63977298Sobrien	}
64089857Sobrien      column += 5 + 2 + strlen (arch->name);
64177298Sobrien      fprintf (stream, "-A%s", arch->name);
64259024Sobrien    }
64377298Sobrien  for (arch = &sparc_arch_table[0]; arch->name; arch++)
64477298Sobrien    {
64577298Sobrien      if (!arch->user_option_p)
64677298Sobrien	continue;
64777298Sobrien      fprintf (stream, " | ");
64889857Sobrien      if (column + strlen (arch->name) > 65)
64977298Sobrien	{
65077298Sobrien	  column = 0;
65177298Sobrien	  fputc ('\n', stream);
65277298Sobrien	}
65389857Sobrien      column += 5 + 7 + strlen (arch->name);
65477298Sobrien      fprintf (stream, "-xarch=%s", arch->name);
65577298Sobrien    }
65677298Sobrien  fprintf (stream, _("\n\
65759024Sobrien			specify variant of SPARC architecture\n\
65859024Sobrien-bump			warn when assembler switches architectures\n\
65959024Sobrien-sparc			ignored\n\
66077298Sobrien--enforce-aligned-data	force .long, etc., to be aligned correctly\n\
66177298Sobrien-relax			relax jumps and branches (default)\n\
66277298Sobrien-no-relax		avoid changing any jumps and branches\n"));
66359024Sobrien#ifdef OBJ_AOUT
66460484Sobrien  fprintf (stream, _("\
66560484Sobrien-k			generate PIC\n"));
66659024Sobrien#endif
66759024Sobrien#ifdef OBJ_ELF
66860484Sobrien  fprintf (stream, _("\
66959024Sobrien-32			create 32 bit object file\n\
67060484Sobrien-64			create 64 bit object file\n"));
67160484Sobrien  fprintf (stream, _("\
67260484Sobrien			[default is %d]\n"), default_arch_size);
67360484Sobrien  fprintf (stream, _("\
67459024Sobrien-TSO			use Total Store Ordering\n\
67559024Sobrien-PSO			use Partial Store Ordering\n\
67660484Sobrien-RMO			use Relaxed Memory Ordering\n"));
67760484Sobrien  fprintf (stream, _("\
67860484Sobrien			[default is %s]\n"), (default_arch_size == 64) ? "RMO" : "TSO");
67960484Sobrien  fprintf (stream, _("\
68059024Sobrien-KPIC			generate PIC\n\
68159024Sobrien-V			print assembler version number\n\
68260484Sobrien-undeclared-regs	ignore application global register usage without\n\
68360484Sobrien			appropriate .register directive (default)\n\
68460484Sobrien-no-undeclared-regs	force error on application global register usage\n\
68560484Sobrien			without appropriate .register directive\n\
68659024Sobrien-q			ignored\n\
68759024Sobrien-Qy, -Qn		ignored\n\
68860484Sobrien-s			ignored\n"));
68959024Sobrien#endif
69059024Sobrien#ifdef SPARC_BIENDIAN
69160484Sobrien  fprintf (stream, _("\
69259024Sobrien-EL			generate code for a little endian machine\n\
69360484Sobrien-EB			generate code for a big endian machine\n\
69460484Sobrien--little-endian-data	generate code for a machine having big endian\n\
69560484Sobrien                        instructions and little endian data.\n"));
69659024Sobrien#endif
69759024Sobrien}
69859024Sobrien
69977298Sobrien/* Native operand size opcode translation.  */
70060484Sobrienstruct
70160484Sobrien  {
70260484Sobrien    char *name;
70360484Sobrien    char *name32;
70460484Sobrien    char *name64;
70560484Sobrien  } native_op_table[] =
70660484Sobrien{
70760484Sobrien  {"ldn", "ld", "ldx"},
70860484Sobrien  {"ldna", "lda", "ldxa"},
70960484Sobrien  {"stn", "st", "stx"},
71060484Sobrien  {"stna", "sta", "stxa"},
71160484Sobrien  {"slln", "sll", "sllx"},
71260484Sobrien  {"srln", "srl", "srlx"},
71360484Sobrien  {"sran", "sra", "srax"},
71460484Sobrien  {"casn", "cas", "casx"},
71560484Sobrien  {"casna", "casa", "casxa"},
71660484Sobrien  {"clrn", "clr", "clrx"},
71760484Sobrien  {NULL, NULL, NULL},
71860484Sobrien};
71960484Sobrien
72077298Sobrien/* sparc64 priviledged registers.  */
72159024Sobrien
72259024Sobrienstruct priv_reg_entry
72377298Sobrien{
72477298Sobrien  char *name;
72577298Sobrien  int regnum;
72677298Sobrien};
72759024Sobrien
72859024Sobrienstruct priv_reg_entry priv_reg_table[] =
72959024Sobrien{
73059024Sobrien  {"tpc", 0},
73159024Sobrien  {"tnpc", 1},
73259024Sobrien  {"tstate", 2},
73359024Sobrien  {"tt", 3},
73459024Sobrien  {"tick", 4},
73559024Sobrien  {"tba", 5},
73659024Sobrien  {"pstate", 6},
73759024Sobrien  {"tl", 7},
73859024Sobrien  {"pil", 8},
73959024Sobrien  {"cwp", 9},
74059024Sobrien  {"cansave", 10},
74159024Sobrien  {"canrestore", 11},
74259024Sobrien  {"cleanwin", 12},
74359024Sobrien  {"otherwin", 13},
74459024Sobrien  {"wstate", 14},
74559024Sobrien  {"fq", 15},
74659024Sobrien  {"ver", 31},
74777298Sobrien  {"", -1},			/* End marker.  */
74859024Sobrien};
74959024Sobrien
75077298Sobrien/* v9a specific asrs.  */
75159024Sobrien
75259024Sobrienstruct priv_reg_entry v9a_asr_table[] =
75359024Sobrien{
75459024Sobrien  {"tick_cmpr", 23},
75577298Sobrien  {"sys_tick_cmpr", 25},
75677298Sobrien  {"sys_tick", 24},
75759024Sobrien  {"softint", 22},
75859024Sobrien  {"set_softint", 20},
75959024Sobrien  {"pic", 17},
76059024Sobrien  {"pcr", 16},
76159024Sobrien  {"gsr", 19},
76259024Sobrien  {"dcr", 18},
76359024Sobrien  {"clear_softint", 21},
76477298Sobrien  {"", -1},			/* End marker.  */
76559024Sobrien};
76659024Sobrien
76759024Sobrienstatic int
76859024Sobriencmp_reg_entry (parg, qarg)
76959024Sobrien     const PTR parg;
77059024Sobrien     const PTR qarg;
77159024Sobrien{
77259024Sobrien  const struct priv_reg_entry *p = (const struct priv_reg_entry *) parg;
77359024Sobrien  const struct priv_reg_entry *q = (const struct priv_reg_entry *) qarg;
77459024Sobrien
77559024Sobrien  return strcmp (q->name, p->name);
77659024Sobrien}
77759024Sobrien
77859024Sobrien/* This function is called once, at assembler startup time.  It should
77977298Sobrien   set up all the tables, etc. that the MD part of the assembler will
78077298Sobrien   need.  */
78159024Sobrien
78259024Sobrienvoid
78359024Sobrienmd_begin ()
78459024Sobrien{
78559024Sobrien  register const char *retval = NULL;
78659024Sobrien  int lose = 0;
78759024Sobrien  register unsigned int i = 0;
78859024Sobrien
78959024Sobrien  /* We don't get a chance to initialize anything before md_parse_option
79059024Sobrien     is called, and it may not be called, so handle default initialization
79159024Sobrien     now if not already done.  */
79259024Sobrien  if (! default_init_p)
79359024Sobrien    init_default_arch ();
79459024Sobrien
79559024Sobrien  op_hash = hash_new ();
79659024Sobrien
79759024Sobrien  while (i < (unsigned int) sparc_num_opcodes)
79859024Sobrien    {
79959024Sobrien      const char *name = sparc_opcodes[i].name;
80059024Sobrien      retval = hash_insert (op_hash, name, (PTR) &sparc_opcodes[i]);
80159024Sobrien      if (retval != NULL)
80259024Sobrien	{
80360484Sobrien	  as_bad (_("Internal error: can't hash `%s': %s\n"),
80460484Sobrien		  sparc_opcodes[i].name, retval);
80559024Sobrien	  lose = 1;
80659024Sobrien	}
80759024Sobrien      do
80859024Sobrien	{
80959024Sobrien	  if (sparc_opcodes[i].match & sparc_opcodes[i].lose)
81059024Sobrien	    {
81160484Sobrien	      as_bad (_("Internal error: losing opcode: `%s' \"%s\"\n"),
81260484Sobrien		      sparc_opcodes[i].name, sparc_opcodes[i].args);
81359024Sobrien	      lose = 1;
81459024Sobrien	    }
81559024Sobrien	  ++i;
81659024Sobrien	}
81759024Sobrien      while (i < (unsigned int) sparc_num_opcodes
81859024Sobrien	     && !strcmp (sparc_opcodes[i].name, name));
81959024Sobrien    }
82059024Sobrien
82160484Sobrien  for (i = 0; native_op_table[i].name; i++)
82260484Sobrien    {
82360484Sobrien      const struct sparc_opcode *insn;
82477298Sobrien      char *name = ((sparc_arch_size == 32)
82577298Sobrien		    ? native_op_table[i].name32
82677298Sobrien		    : native_op_table[i].name64);
82777298Sobrien      insn = (struct sparc_opcode *) hash_find (op_hash, name);
82860484Sobrien      if (insn == NULL)
82977298Sobrien	{
83077298Sobrien	  as_bad (_("Internal error: can't find opcode `%s' for `%s'\n"),
83177298Sobrien		  name, native_op_table[i].name);
83277298Sobrien	  lose = 1;
83377298Sobrien	}
83460484Sobrien      else
83560484Sobrien	{
83660484Sobrien	  retval = hash_insert (op_hash, native_op_table[i].name, (PTR) insn);
83760484Sobrien	  if (retval != NULL)
83860484Sobrien	    {
83960484Sobrien	      as_bad (_("Internal error: can't hash `%s': %s\n"),
84060484Sobrien		      sparc_opcodes[i].name, retval);
84160484Sobrien	      lose = 1;
84260484Sobrien	    }
84360484Sobrien	}
84460484Sobrien    }
84560484Sobrien
84659024Sobrien  if (lose)
84760484Sobrien    as_fatal (_("Broken assembler.  No assembly attempted."));
84859024Sobrien
84959024Sobrien  qsort (priv_reg_table, sizeof (priv_reg_table) / sizeof (priv_reg_table[0]),
85059024Sobrien	 sizeof (priv_reg_table[0]), cmp_reg_entry);
85159024Sobrien
85259024Sobrien  /* If -bump, record the architecture level at which we start issuing
85359024Sobrien     warnings.  The behaviour is different depending upon whether an
85459024Sobrien     architecture was explicitly specified.  If it wasn't, we issue warnings
85559024Sobrien     for all upwards bumps.  If it was, we don't start issuing warnings until
85659024Sobrien     we need to bump beyond the requested architecture or when we bump between
85759024Sobrien     conflicting architectures.  */
85859024Sobrien
85959024Sobrien  if (warn_on_bump
86059024Sobrien      && architecture_requested)
86159024Sobrien    {
86259024Sobrien      /* `max_architecture' records the requested architecture.
86359024Sobrien	 Issue warnings if we go above it.  */
86459024Sobrien      warn_after_architecture = max_architecture;
86559024Sobrien
86659024Sobrien      /* Find the highest architecture level that doesn't conflict with
86759024Sobrien	 the requested one.  */
86859024Sobrien      for (max_architecture = SPARC_OPCODE_ARCH_MAX;
86959024Sobrien	   max_architecture > warn_after_architecture;
87059024Sobrien	   --max_architecture)
87159024Sobrien	if (! SPARC_OPCODE_CONFLICT_P (max_architecture,
87259024Sobrien				       warn_after_architecture))
87359024Sobrien	  break;
87459024Sobrien    }
87559024Sobrien}
87659024Sobrien
87759024Sobrien/* Called after all assembly has been done.  */
87859024Sobrien
87959024Sobrienvoid
88059024Sobriensparc_md_end ()
88159024Sobrien{
88277298Sobrien  unsigned long mach = bfd_mach_sparc;
88377298Sobrien
88459024Sobrien  if (sparc_arch_size == 64)
88577298Sobrien    switch (current_architecture)
88677298Sobrien      {
88777298Sobrien      case SPARC_OPCODE_ARCH_V9A: mach = bfd_mach_sparc_v9a; break;
88877298Sobrien      case SPARC_OPCODE_ARCH_V9B: mach = bfd_mach_sparc_v9b; break;
88977298Sobrien      default: mach = bfd_mach_sparc_v9; break;
89077298Sobrien      }
89159024Sobrien  else
89277298Sobrien    switch (current_architecture)
89377298Sobrien      {
89477298Sobrien      case SPARC_OPCODE_ARCH_SPARCLET: mach = bfd_mach_sparc_sparclet; break;
89577298Sobrien      case SPARC_OPCODE_ARCH_V9: mach = bfd_mach_sparc_v8plus; break;
89677298Sobrien      case SPARC_OPCODE_ARCH_V9A: mach = bfd_mach_sparc_v8plusa; break;
89777298Sobrien      case SPARC_OPCODE_ARCH_V9B: mach = bfd_mach_sparc_v8plusb; break;
89877298Sobrien      /* The sparclite is treated like a normal sparc.  Perhaps it shouldn't
89977298Sobrien	 be but for now it is (since that's the way it's always been
90077298Sobrien	 treated).  */
90177298Sobrien      default: break;
90277298Sobrien      }
90377298Sobrien  bfd_set_arch_mach (stdoutput, bfd_arch_sparc, mach);
90459024Sobrien}
90559024Sobrien
90659024Sobrien/* Return non-zero if VAL is in the range -(MAX+1) to MAX.  */
90759024Sobrien
90859024Sobrienstatic INLINE int
90959024Sobrienin_signed_range (val, max)
91059024Sobrien     bfd_signed_vma val, max;
91159024Sobrien{
91259024Sobrien  if (max <= 0)
91359024Sobrien    abort ();
91460484Sobrien  /* Sign-extend the value from the architecture word size, so that
91560484Sobrien     0xffffffff is always considered -1 on sparc32.  */
91660484Sobrien  if (sparc_arch_size == 32)
91760484Sobrien    {
91877298Sobrien      bfd_signed_vma sign = (bfd_signed_vma) 1 << 31;
91960484Sobrien      val = ((val & 0xffffffff) ^ sign) - sign;
92060484Sobrien    }
92159024Sobrien  if (val > max)
92259024Sobrien    return 0;
92359024Sobrien  if (val < ~max)
92459024Sobrien    return 0;
92559024Sobrien  return 1;
92659024Sobrien}
92759024Sobrien
92859024Sobrien/* Return non-zero if VAL is in the range 0 to MAX.  */
92959024Sobrien
93059024Sobrienstatic INLINE int
93159024Sobrienin_unsigned_range (val, max)
93259024Sobrien     bfd_vma val, max;
93359024Sobrien{
93459024Sobrien  if (val > max)
93559024Sobrien    return 0;
93659024Sobrien  return 1;
93759024Sobrien}
93859024Sobrien
93959024Sobrien/* Return non-zero if VAL is in the range -(MAX/2+1) to MAX.
94059024Sobrien   (e.g. -15 to +31).  */
94159024Sobrien
94259024Sobrienstatic INLINE int
94359024Sobrienin_bitfield_range (val, max)
94459024Sobrien     bfd_signed_vma val, max;
94559024Sobrien{
94659024Sobrien  if (max <= 0)
94759024Sobrien    abort ();
94859024Sobrien  if (val > max)
94959024Sobrien    return 0;
95059024Sobrien  if (val < ~(max >> 1))
95159024Sobrien    return 0;
95259024Sobrien  return 1;
95359024Sobrien}
95459024Sobrien
95559024Sobrienstatic int
95659024Sobriensparc_ffs (mask)
95759024Sobrien     unsigned int mask;
95859024Sobrien{
95959024Sobrien  int i;
96059024Sobrien
96159024Sobrien  if (mask == 0)
96259024Sobrien    return -1;
96359024Sobrien
96459024Sobrien  for (i = 0; (mask & 1) == 0; ++i)
96559024Sobrien    mask >>= 1;
96659024Sobrien  return i;
96759024Sobrien}
96859024Sobrien
96959024Sobrien/* Implement big shift right.  */
97059024Sobrienstatic bfd_vma
97159024SobrienBSR (val, amount)
97259024Sobrien     bfd_vma val;
97359024Sobrien     int amount;
97459024Sobrien{
97559024Sobrien  if (sizeof (bfd_vma) <= 4 && amount >= 32)
97660484Sobrien    as_fatal (_("Support for 64-bit arithmetic not compiled in."));
97759024Sobrien  return val >> amount;
97859024Sobrien}
97959024Sobrien
98059024Sobrien/* For communication between sparc_ip and get_expression.  */
98159024Sobrienstatic char *expr_end;
98259024Sobrien
98359024Sobrien/* Values for `special_case'.
98459024Sobrien   Instructions that require wierd handling because they're longer than
98559024Sobrien   4 bytes.  */
98659024Sobrien#define SPECIAL_CASE_NONE	0
98759024Sobrien#define	SPECIAL_CASE_SET	1
98859024Sobrien#define SPECIAL_CASE_SETSW	2
98959024Sobrien#define SPECIAL_CASE_SETX	3
99059024Sobrien/* FIXME: sparc-opc.c doesn't have necessary "S" trigger to enable this.  */
99159024Sobrien#define	SPECIAL_CASE_FDIV	4
99259024Sobrien
99359024Sobrien/* Bit masks of various insns.  */
99459024Sobrien#define NOP_INSN 0x01000000
99559024Sobrien#define OR_INSN 0x80100000
99660484Sobrien#define XOR_INSN 0x80180000
99759024Sobrien#define FMOVS_INSN 0x81A00020
99859024Sobrien#define SETHI_INSN 0x01000000
99959024Sobrien#define SLLX_INSN 0x81281000
100059024Sobrien#define SRA_INSN 0x81380000
100159024Sobrien
100259024Sobrien/* The last instruction to be assembled.  */
100359024Sobrienstatic const struct sparc_opcode *last_insn;
100459024Sobrien/* The assembled opcode of `last_insn'.  */
100559024Sobrienstatic unsigned long last_opcode;
100659024Sobrien
100760484Sobrien/* Handle the set and setuw synthetic instructions.  */
100877298Sobrien
100960484Sobrienstatic void
101060484Sobriensynthetize_setuw (insn)
101160484Sobrien     const struct sparc_opcode *insn;
101260484Sobrien{
101360484Sobrien  int need_hi22_p = 0;
101460484Sobrien  int rd = (the_insn.opcode & RD (~0)) >> 25;
101560484Sobrien
101660484Sobrien  if (the_insn.exp.X_op == O_constant)
101760484Sobrien    {
101860484Sobrien      if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
101960484Sobrien	{
102077298Sobrien	  if (sizeof (offsetT) > 4
102160484Sobrien	      && (the_insn.exp.X_add_number < 0
102260484Sobrien		  || the_insn.exp.X_add_number > (offsetT) 0xffffffff))
102360484Sobrien	    as_warn (_("set: number not in 0..4294967295 range"));
102460484Sobrien	}
102560484Sobrien      else
102660484Sobrien	{
102777298Sobrien	  if (sizeof (offsetT) > 4
102860484Sobrien	      && (the_insn.exp.X_add_number < -(offsetT) 0x80000000
102960484Sobrien		  || the_insn.exp.X_add_number > (offsetT) 0xffffffff))
103060484Sobrien	    as_warn (_("set: number not in -2147483648..4294967295 range"));
103177298Sobrien	  the_insn.exp.X_add_number = (int) the_insn.exp.X_add_number;
103260484Sobrien	}
103360484Sobrien    }
103460484Sobrien
103560484Sobrien  /* See if operand is absolute and small; skip sethi if so.  */
103660484Sobrien  if (the_insn.exp.X_op != O_constant
103760484Sobrien      || the_insn.exp.X_add_number >= (1 << 12)
103860484Sobrien      || the_insn.exp.X_add_number < -(1 << 12))
103960484Sobrien    {
104060484Sobrien      the_insn.opcode = (SETHI_INSN | RD (rd)
104160484Sobrien			 | ((the_insn.exp.X_add_number >> 10)
104277298Sobrien			    & (the_insn.exp.X_op == O_constant
104377298Sobrien			       ? 0x3fffff : 0)));
104460484Sobrien      the_insn.reloc = (the_insn.exp.X_op != O_constant
104577298Sobrien			? BFD_RELOC_HI22 : BFD_RELOC_NONE);
104660484Sobrien      output_insn (insn, &the_insn);
104760484Sobrien      need_hi22_p = 1;
104860484Sobrien    }
104960484Sobrien
105060484Sobrien  /* See if operand has no low-order bits; skip OR if so.  */
105160484Sobrien  if (the_insn.exp.X_op != O_constant
105260484Sobrien      || (need_hi22_p && (the_insn.exp.X_add_number & 0x3FF) != 0)
105360484Sobrien      || ! need_hi22_p)
105460484Sobrien    {
105560484Sobrien      the_insn.opcode = (OR_INSN | (need_hi22_p ? RS1 (rd) : 0)
105660484Sobrien			 | RD (rd) | IMMED
105760484Sobrien			 | (the_insn.exp.X_add_number
105877298Sobrien			    & (the_insn.exp.X_op != O_constant
105977298Sobrien			       ? 0 : need_hi22_p ? 0x3ff : 0x1fff)));
106060484Sobrien      the_insn.reloc = (the_insn.exp.X_op != O_constant
106177298Sobrien			? BFD_RELOC_LO10 : BFD_RELOC_NONE);
106260484Sobrien      output_insn (insn, &the_insn);
106360484Sobrien    }
106460484Sobrien}
106577298Sobrien
106660484Sobrien/* Handle the setsw synthetic instruction.  */
106777298Sobrien
106860484Sobrienstatic void
106960484Sobriensynthetize_setsw (insn)
107060484Sobrien     const struct sparc_opcode *insn;
107160484Sobrien{
107260484Sobrien  int low32, rd, opc;
107360484Sobrien
107460484Sobrien  rd = (the_insn.opcode & RD (~0)) >> 25;
107560484Sobrien
107660484Sobrien  if (the_insn.exp.X_op != O_constant)
107760484Sobrien    {
107860484Sobrien      synthetize_setuw (insn);
107960484Sobrien
108060484Sobrien      /* Need to sign extend it.  */
108160484Sobrien      the_insn.opcode = (SRA_INSN | RS1 (rd) | RD (rd));
108260484Sobrien      the_insn.reloc = BFD_RELOC_NONE;
108360484Sobrien      output_insn (insn, &the_insn);
108460484Sobrien      return;
108560484Sobrien    }
108660484Sobrien
108777298Sobrien  if (sizeof (offsetT) > 4
108860484Sobrien      && (the_insn.exp.X_add_number < -(offsetT) 0x80000000
108960484Sobrien	  || the_insn.exp.X_add_number > (offsetT) 0xffffffff))
109060484Sobrien    as_warn (_("setsw: number not in -2147483648..4294967295 range"));
109160484Sobrien
109277298Sobrien  low32 = the_insn.exp.X_add_number;
109377298Sobrien
109460484Sobrien  if (low32 >= 0)
109560484Sobrien    {
109660484Sobrien      synthetize_setuw (insn);
109760484Sobrien      return;
109860484Sobrien    }
109960484Sobrien
110060484Sobrien  opc = OR_INSN;
110177298Sobrien
110260484Sobrien  the_insn.reloc = BFD_RELOC_NONE;
110360484Sobrien  /* See if operand is absolute and small; skip sethi if so.  */
110460484Sobrien  if (low32 < -(1 << 12))
110560484Sobrien    {
110660484Sobrien      the_insn.opcode = (SETHI_INSN | RD (rd)
110760484Sobrien			 | (((~the_insn.exp.X_add_number) >> 10) & 0x3fffff));
110860484Sobrien      output_insn (insn, &the_insn);
110960484Sobrien      low32 = 0x1c00 | (low32 & 0x3ff);
111060484Sobrien      opc = RS1 (rd) | XOR_INSN;
111160484Sobrien    }
111260484Sobrien
111360484Sobrien  the_insn.opcode = (opc | RD (rd) | IMMED
111460484Sobrien		     | (low32 & 0x1fff));
111560484Sobrien  output_insn (insn, &the_insn);
111660484Sobrien}
111760484Sobrien
111860484Sobrien/* Handle the setsw synthetic instruction.  */
111977298Sobrien
112060484Sobrienstatic void
112160484Sobriensynthetize_setx (insn)
112260484Sobrien     const struct sparc_opcode *insn;
112360484Sobrien{
112460484Sobrien  int upper32, lower32;
112560484Sobrien  int tmpreg = (the_insn.opcode & RS1 (~0)) >> 14;
112660484Sobrien  int dstreg = (the_insn.opcode & RD (~0)) >> 25;
112760484Sobrien  int upper_dstreg;
112860484Sobrien  int need_hh22_p = 0, need_hm10_p = 0, need_hi22_p = 0, need_lo10_p = 0;
112960484Sobrien  int need_xor10_p = 0;
113077298Sobrien
113160484Sobrien#define SIGNEXT32(x) ((((x) & 0xffffffff) ^ 0x80000000) - 0x80000000)
113260484Sobrien  lower32 = SIGNEXT32 (the_insn.exp.X_add_number);
113360484Sobrien  upper32 = SIGNEXT32 (BSR (the_insn.exp.X_add_number, 32));
113460484Sobrien#undef SIGNEXT32
113560484Sobrien
113660484Sobrien  upper_dstreg = tmpreg;
113760484Sobrien  /* The tmp reg should not be the dst reg.  */
113860484Sobrien  if (tmpreg == dstreg)
113960484Sobrien    as_warn (_("setx: temporary register same as destination register"));
114060484Sobrien
114160484Sobrien  /* ??? Obviously there are other optimizations we can do
114260484Sobrien     (e.g. sethi+shift for 0x1f0000000) and perhaps we shouldn't be
114360484Sobrien     doing some of these.  Later.  If you do change things, try to
114460484Sobrien     change all of this to be table driven as well.  */
114560484Sobrien  /* What to output depends on the number if it's constant.
114660484Sobrien     Compute that first, then output what we've decided upon.  */
114760484Sobrien  if (the_insn.exp.X_op != O_constant)
114860484Sobrien    {
114960484Sobrien      if (sparc_arch_size == 32)
115060484Sobrien	{
115160484Sobrien	  /* When arch size is 32, we want setx to be equivalent
115260484Sobrien	     to setuw for anything but constants.  */
115360484Sobrien	  the_insn.exp.X_add_number &= 0xffffffff;
115460484Sobrien	  synthetize_setuw (insn);
115560484Sobrien	  return;
115660484Sobrien	}
115760484Sobrien      need_hh22_p = need_hm10_p = need_hi22_p = need_lo10_p = 1;
115877298Sobrien      lower32 = 0;
115977298Sobrien      upper32 = 0;
116060484Sobrien    }
116160484Sobrien  else
116260484Sobrien    {
116360484Sobrien      /* Reset X_add_number, we've extracted it as upper32/lower32.
116460484Sobrien	 Otherwise fixup_segment will complain about not being able to
116560484Sobrien	 write an 8 byte number in a 4 byte field.  */
116660484Sobrien      the_insn.exp.X_add_number = 0;
116777298Sobrien
116860484Sobrien      /* Only need hh22 if `or' insn can't handle constant.  */
116960484Sobrien      if (upper32 < -(1 << 12) || upper32 >= (1 << 12))
117060484Sobrien	need_hh22_p = 1;
117177298Sobrien
117260484Sobrien      /* Does bottom part (after sethi) have bits?  */
117360484Sobrien      if ((need_hh22_p && (upper32 & 0x3ff) != 0)
117460484Sobrien	  /* No hh22, but does upper32 still have bits we can't set
117560484Sobrien	     from lower32?  */
117660484Sobrien	  || (! need_hh22_p && upper32 != 0 && upper32 != -1))
117760484Sobrien	need_hm10_p = 1;
117877298Sobrien
117960484Sobrien      /* If the lower half is all zero, we build the upper half directly
118060484Sobrien	 into the dst reg.  */
118160484Sobrien      if (lower32 != 0
118260484Sobrien	  /* Need lower half if number is zero or 0xffffffff00000000.  */
118360484Sobrien	  || (! need_hh22_p && ! need_hm10_p))
118460484Sobrien	{
118560484Sobrien	  /* No need for sethi if `or' insn can handle constant.  */
118660484Sobrien	  if (lower32 < -(1 << 12) || lower32 >= (1 << 12)
118760484Sobrien	      /* Note that we can't use a negative constant in the `or'
118860484Sobrien		 insn unless the upper 32 bits are all ones.  */
118960484Sobrien	      || (lower32 < 0 && upper32 != -1)
119060484Sobrien	      || (lower32 >= 0 && upper32 == -1))
119160484Sobrien	    need_hi22_p = 1;
119277298Sobrien
119360484Sobrien	  if (need_hi22_p && upper32 == -1)
119460484Sobrien	    need_xor10_p = 1;
119560484Sobrien
119660484Sobrien	  /* Does bottom part (after sethi) have bits?  */
119760484Sobrien	  else if ((need_hi22_p && (lower32 & 0x3ff) != 0)
119860484Sobrien		   /* No sethi.  */
119960484Sobrien		   || (! need_hi22_p && (lower32 & 0x1fff) != 0)
120060484Sobrien		   /* Need `or' if we didn't set anything else.  */
120160484Sobrien		   || (! need_hi22_p && ! need_hh22_p && ! need_hm10_p))
120260484Sobrien	    need_lo10_p = 1;
120360484Sobrien	}
120460484Sobrien      else
120560484Sobrien	/* Output directly to dst reg if lower 32 bits are all zero.  */
120660484Sobrien	upper_dstreg = dstreg;
120760484Sobrien    }
120877298Sobrien
120960484Sobrien  if (!upper_dstreg && dstreg)
121060484Sobrien    as_warn (_("setx: illegal temporary register g0"));
121160484Sobrien
121260484Sobrien  if (need_hh22_p)
121360484Sobrien    {
121460484Sobrien      the_insn.opcode = (SETHI_INSN | RD (upper_dstreg)
121560484Sobrien			 | ((upper32 >> 10) & 0x3fffff));
121660484Sobrien      the_insn.reloc = (the_insn.exp.X_op != O_constant
121760484Sobrien			? BFD_RELOC_SPARC_HH22 : BFD_RELOC_NONE);
121860484Sobrien      output_insn (insn, &the_insn);
121960484Sobrien    }
122077298Sobrien
122160484Sobrien  if (need_hi22_p)
122260484Sobrien    {
122360484Sobrien      the_insn.opcode = (SETHI_INSN | RD (dstreg)
122460484Sobrien			 | (((need_xor10_p ? ~lower32 : lower32)
122577298Sobrien			     >> 10) & 0x3fffff));
122660484Sobrien      the_insn.reloc = (the_insn.exp.X_op != O_constant
122760484Sobrien			? BFD_RELOC_SPARC_LM22 : BFD_RELOC_NONE);
122860484Sobrien      output_insn (insn, &the_insn);
122960484Sobrien    }
123060484Sobrien
123160484Sobrien  if (need_hm10_p)
123260484Sobrien    {
123360484Sobrien      the_insn.opcode = (OR_INSN
123460484Sobrien			 | (need_hh22_p ? RS1 (upper_dstreg) : 0)
123560484Sobrien			 | RD (upper_dstreg)
123660484Sobrien			 | IMMED
123760484Sobrien			 | (upper32 & (need_hh22_p ? 0x3ff : 0x1fff)));
123860484Sobrien      the_insn.reloc = (the_insn.exp.X_op != O_constant
123960484Sobrien			? BFD_RELOC_SPARC_HM10 : BFD_RELOC_NONE);
124060484Sobrien      output_insn (insn, &the_insn);
124160484Sobrien    }
124277298Sobrien
124360484Sobrien  if (need_lo10_p)
124460484Sobrien    {
124560484Sobrien      /* FIXME: One nice optimization to do here is to OR the low part
124660484Sobrien	 with the highpart if hi22 isn't needed and the low part is
124760484Sobrien	 positive.  */
124860484Sobrien      the_insn.opcode = (OR_INSN | (need_hi22_p ? RS1 (dstreg) : 0)
124960484Sobrien			 | RD (dstreg)
125060484Sobrien			 | IMMED
125160484Sobrien			 | (lower32 & (need_hi22_p ? 0x3ff : 0x1fff)));
125260484Sobrien      the_insn.reloc = (the_insn.exp.X_op != O_constant
125360484Sobrien			? BFD_RELOC_LO10 : BFD_RELOC_NONE);
125460484Sobrien      output_insn (insn, &the_insn);
125560484Sobrien    }
125677298Sobrien
125760484Sobrien  /* If we needed to build the upper part, shift it into place.  */
125860484Sobrien  if (need_hh22_p || need_hm10_p)
125960484Sobrien    {
126060484Sobrien      the_insn.opcode = (SLLX_INSN | RS1 (upper_dstreg) | RD (upper_dstreg)
126160484Sobrien			 | IMMED | 32);
126260484Sobrien      the_insn.reloc = BFD_RELOC_NONE;
126360484Sobrien      output_insn (insn, &the_insn);
126460484Sobrien    }
126577298Sobrien
126660484Sobrien  /* To get -1 in upper32, we do sethi %hi(~x), r; xor r, -0x400 | x, r.  */
126760484Sobrien  if (need_xor10_p)
126860484Sobrien    {
126960484Sobrien      the_insn.opcode = (XOR_INSN | RS1 (dstreg) | RD (dstreg) | IMMED
127060484Sobrien			 | 0x1c00 | (lower32 & 0x3ff));
127160484Sobrien      the_insn.reloc = BFD_RELOC_NONE;
127260484Sobrien      output_insn (insn, &the_insn);
127360484Sobrien    }
127460484Sobrien
127560484Sobrien  /* If we needed to build both upper and lower parts, OR them together.  */
127660484Sobrien  else if ((need_hh22_p || need_hm10_p) && (need_hi22_p || need_lo10_p))
127760484Sobrien    {
127860484Sobrien      the_insn.opcode = (OR_INSN | RS1 (dstreg) | RS2 (upper_dstreg)
127960484Sobrien			 | RD (dstreg));
128060484Sobrien      the_insn.reloc = BFD_RELOC_NONE;
128160484Sobrien      output_insn (insn, &the_insn);
128260484Sobrien    }
128360484Sobrien}
128460484Sobrien
128559024Sobrien/* Main entry point to assemble one instruction.  */
128659024Sobrien
128759024Sobrienvoid
128859024Sobrienmd_assemble (str)
128959024Sobrien     char *str;
129059024Sobrien{
129159024Sobrien  const struct sparc_opcode *insn;
129260484Sobrien  int special_case;
129359024Sobrien
129459024Sobrien  know (str);
129560484Sobrien  special_case = sparc_ip (str, &insn);
129659024Sobrien
129759024Sobrien  /* We warn about attempts to put a floating point branch in a delay slot,
129859024Sobrien     unless the delay slot has been annulled.  */
129959024Sobrien  if (insn != NULL
130059024Sobrien      && last_insn != NULL
130159024Sobrien      && (insn->flags & F_FBR) != 0
130259024Sobrien      && (last_insn->flags & F_DELAYED) != 0
130359024Sobrien      /* ??? This test isn't completely accurate.  We assume anything with
130459024Sobrien	 F_{UNBR,CONDBR,FBR} set is annullable.  */
130559024Sobrien      && ((last_insn->flags & (F_UNBR | F_CONDBR | F_FBR)) == 0
130659024Sobrien	  || (last_opcode & ANNUL) == 0))
130760484Sobrien    as_warn (_("FP branch in delay slot"));
130859024Sobrien
130959024Sobrien  /* SPARC before v9 requires a nop instruction between a floating
131059024Sobrien     point instruction and a floating point branch.  We insert one
131159024Sobrien     automatically, with a warning.  */
131259024Sobrien  if (max_architecture < SPARC_OPCODE_ARCH_V9
131359024Sobrien      && insn != NULL
131459024Sobrien      && last_insn != NULL
131559024Sobrien      && (insn->flags & F_FBR) != 0
131659024Sobrien      && (last_insn->flags & F_FLOAT) != 0)
131759024Sobrien    {
131859024Sobrien      struct sparc_it nop_insn;
131959024Sobrien
132059024Sobrien      nop_insn.opcode = NOP_INSN;
132159024Sobrien      nop_insn.reloc = BFD_RELOC_NONE;
132259024Sobrien      output_insn (insn, &nop_insn);
132360484Sobrien      as_warn (_("FP branch preceded by FP instruction; NOP inserted"));
132459024Sobrien    }
132559024Sobrien
132659024Sobrien  switch (special_case)
132759024Sobrien    {
132859024Sobrien    case SPECIAL_CASE_NONE:
132977298Sobrien      /* Normal insn.  */
133059024Sobrien      output_insn (insn, &the_insn);
133159024Sobrien      break;
133259024Sobrien
133360484Sobrien    case SPECIAL_CASE_SETSW:
133460484Sobrien      synthetize_setsw (insn);
133560484Sobrien      break;
133677298Sobrien
133759024Sobrien    case SPECIAL_CASE_SET:
133860484Sobrien      synthetize_setuw (insn);
133960484Sobrien      break;
134059024Sobrien
134159024Sobrien    case SPECIAL_CASE_SETX:
134260484Sobrien      synthetize_setx (insn);
134360484Sobrien      break;
134477298Sobrien
134559024Sobrien    case SPECIAL_CASE_FDIV:
134659024Sobrien      {
134759024Sobrien	int rd = (the_insn.opcode >> 25) & 0x1f;
134877298Sobrien
134959024Sobrien	output_insn (insn, &the_insn);
135077298Sobrien
135159024Sobrien	/* According to information leaked from Sun, the "fdiv" instructions
135259024Sobrien	   on early SPARC machines would produce incorrect results sometimes.
135359024Sobrien	   The workaround is to add an fmovs of the destination register to
135459024Sobrien	   itself just after the instruction.  This was true on machines
135577298Sobrien	   with Weitek 1165 float chips, such as the Sun-4/260 and /280.  */
135659024Sobrien	assert (the_insn.reloc == BFD_RELOC_NONE);
135759024Sobrien	the_insn.opcode = FMOVS_INSN | rd | RD (rd);
135859024Sobrien	output_insn (insn, &the_insn);
135960484Sobrien	return;
136059024Sobrien      }
136177298Sobrien
136259024Sobrien    default:
136360484Sobrien      as_fatal (_("failed special case insn sanity check"));
136459024Sobrien    }
136559024Sobrien}
136659024Sobrien
136759024Sobrien/* Subroutine of md_assemble to do the actual parsing.  */
136859024Sobrien
136960484Sobrienstatic int
137059024Sobriensparc_ip (str, pinsn)
137159024Sobrien     char *str;
137259024Sobrien     const struct sparc_opcode **pinsn;
137359024Sobrien{
137459024Sobrien  char *error_message = "";
137559024Sobrien  char *s;
137659024Sobrien  const char *args;
137759024Sobrien  char c;
137859024Sobrien  const struct sparc_opcode *insn;
137959024Sobrien  char *argsStart;
138059024Sobrien  unsigned long opcode;
138159024Sobrien  unsigned int mask = 0;
138259024Sobrien  int match = 0;
138359024Sobrien  int comma = 0;
138459024Sobrien  int v9_arg_p;
138560484Sobrien  int special_case = SPECIAL_CASE_NONE;
138659024Sobrien
138760484Sobrien  s = str;
138889857Sobrien  if (ISLOWER (*s))
138960484Sobrien    {
139060484Sobrien      do
139160484Sobrien	++s;
139289857Sobrien      while (ISLOWER (*s) || ISDIGIT (*s));
139360484Sobrien    }
139459024Sobrien
139559024Sobrien  switch (*s)
139659024Sobrien    {
139759024Sobrien    case '\0':
139859024Sobrien      break;
139959024Sobrien
140059024Sobrien    case ',':
140159024Sobrien      comma = 1;
140277298Sobrien      /* Fall through.  */
140359024Sobrien
140459024Sobrien    case ' ':
140559024Sobrien      *s++ = '\0';
140659024Sobrien      break;
140759024Sobrien
140859024Sobrien    default:
140960484Sobrien      as_fatal (_("Unknown opcode: `%s'"), str);
141059024Sobrien    }
141159024Sobrien  insn = (struct sparc_opcode *) hash_find (op_hash, str);
141259024Sobrien  *pinsn = insn;
141359024Sobrien  if (insn == NULL)
141459024Sobrien    {
141560484Sobrien      as_bad (_("Unknown opcode: `%s'"), str);
141660484Sobrien      return special_case;
141759024Sobrien    }
141859024Sobrien  if (comma)
141959024Sobrien    {
142059024Sobrien      *--s = ',';
142159024Sobrien    }
142259024Sobrien
142359024Sobrien  argsStart = s;
142459024Sobrien  for (;;)
142559024Sobrien    {
142659024Sobrien      opcode = insn->match;
142759024Sobrien      memset (&the_insn, '\0', sizeof (the_insn));
142859024Sobrien      the_insn.reloc = BFD_RELOC_NONE;
142959024Sobrien      v9_arg_p = 0;
143059024Sobrien
143177298Sobrien      /* Build the opcode, checking as we go to make sure that the
143277298Sobrien         operands match.  */
143359024Sobrien      for (args = insn->args;; ++args)
143459024Sobrien	{
143559024Sobrien	  switch (*args)
143659024Sobrien	    {
143759024Sobrien	    case 'K':
143859024Sobrien	      {
143959024Sobrien		int kmask = 0;
144059024Sobrien
144159024Sobrien		/* Parse a series of masks.  */
144259024Sobrien		if (*s == '#')
144359024Sobrien		  {
144459024Sobrien		    while (*s == '#')
144559024Sobrien		      {
144659024Sobrien			int mask;
144759024Sobrien
144859024Sobrien			if (! parse_keyword_arg (sparc_encode_membar, &s,
144959024Sobrien						 &mask))
145059024Sobrien			  {
145160484Sobrien			    error_message = _(": invalid membar mask name");
145259024Sobrien			    goto error;
145359024Sobrien			  }
145459024Sobrien			kmask |= mask;
145577298Sobrien			while (*s == ' ')
145677298Sobrien			  ++s;
145759024Sobrien			if (*s == '|' || *s == '+')
145859024Sobrien			  ++s;
145977298Sobrien			while (*s == ' ')
146077298Sobrien			  ++s;
146159024Sobrien		      }
146259024Sobrien		  }
146359024Sobrien		else
146459024Sobrien		  {
146559024Sobrien		    if (! parse_const_expr_arg (&s, &kmask))
146659024Sobrien		      {
146760484Sobrien			error_message = _(": invalid membar mask expression");
146859024Sobrien			goto error;
146959024Sobrien		      }
147059024Sobrien		    if (kmask < 0 || kmask > 127)
147159024Sobrien		      {
147260484Sobrien			error_message = _(": invalid membar mask number");
147359024Sobrien			goto error;
147459024Sobrien		      }
147559024Sobrien		  }
147659024Sobrien
147759024Sobrien		opcode |= MEMBAR (kmask);
147859024Sobrien		continue;
147959024Sobrien	      }
148059024Sobrien
148177298Sobrien	    case '3':
148277298Sobrien	      {
148377298Sobrien		int smask = 0;
148477298Sobrien
148577298Sobrien		if (! parse_const_expr_arg (&s, &smask))
148677298Sobrien		  {
148777298Sobrien		    error_message = _(": invalid siam mode expression");
148877298Sobrien		    goto error;
148977298Sobrien		  }
149077298Sobrien		if (smask < 0 || smask > 7)
149177298Sobrien		  {
149277298Sobrien		    error_message = _(": invalid siam mode number");
149377298Sobrien		    goto error;
149477298Sobrien		  }
149577298Sobrien		opcode |= smask;
149677298Sobrien		continue;
149777298Sobrien	      }
149877298Sobrien
149959024Sobrien	    case '*':
150059024Sobrien	      {
150159024Sobrien		int fcn = 0;
150259024Sobrien
150359024Sobrien		/* Parse a prefetch function.  */
150459024Sobrien		if (*s == '#')
150559024Sobrien		  {
150659024Sobrien		    if (! parse_keyword_arg (sparc_encode_prefetch, &s, &fcn))
150759024Sobrien		      {
150860484Sobrien			error_message = _(": invalid prefetch function name");
150959024Sobrien			goto error;
151059024Sobrien		      }
151159024Sobrien		  }
151259024Sobrien		else
151359024Sobrien		  {
151459024Sobrien		    if (! parse_const_expr_arg (&s, &fcn))
151559024Sobrien		      {
151660484Sobrien			error_message = _(": invalid prefetch function expression");
151759024Sobrien			goto error;
151859024Sobrien		      }
151959024Sobrien		    if (fcn < 0 || fcn > 31)
152059024Sobrien		      {
152160484Sobrien			error_message = _(": invalid prefetch function number");
152259024Sobrien			goto error;
152359024Sobrien		      }
152459024Sobrien		  }
152559024Sobrien		opcode |= RD (fcn);
152659024Sobrien		continue;
152759024Sobrien	      }
152859024Sobrien
152959024Sobrien	    case '!':
153059024Sobrien	    case '?':
153159024Sobrien	      /* Parse a sparc64 privileged register.  */
153259024Sobrien	      if (*s == '%')
153359024Sobrien		{
153459024Sobrien		  struct priv_reg_entry *p = priv_reg_table;
153577298Sobrien		  unsigned int len = 9999999; /* Init to make gcc happy.  */
153659024Sobrien
153759024Sobrien		  s += 1;
153859024Sobrien		  while (p->name[0] > s[0])
153959024Sobrien		    p++;
154059024Sobrien		  while (p->name[0] == s[0])
154159024Sobrien		    {
154259024Sobrien		      len = strlen (p->name);
154359024Sobrien		      if (strncmp (p->name, s, len) == 0)
154459024Sobrien			break;
154559024Sobrien		      p++;
154659024Sobrien		    }
154759024Sobrien		  if (p->name[0] != s[0])
154859024Sobrien		    {
154960484Sobrien		      error_message = _(": unrecognizable privileged register");
155059024Sobrien		      goto error;
155159024Sobrien		    }
155259024Sobrien		  if (*args == '?')
155359024Sobrien		    opcode |= (p->regnum << 14);
155459024Sobrien		  else
155559024Sobrien		    opcode |= (p->regnum << 25);
155659024Sobrien		  s += len;
155759024Sobrien		  continue;
155859024Sobrien		}
155959024Sobrien	      else
156059024Sobrien		{
156160484Sobrien		  error_message = _(": unrecognizable privileged register");
156259024Sobrien		  goto error;
156359024Sobrien		}
156459024Sobrien
156559024Sobrien	    case '_':
156659024Sobrien	    case '/':
156777298Sobrien	      /* Parse a v9a/v9b ancillary state register.  */
156859024Sobrien	      if (*s == '%')
156959024Sobrien		{
157059024Sobrien		  struct priv_reg_entry *p = v9a_asr_table;
157177298Sobrien		  unsigned int len = 9999999; /* Init to make gcc happy.  */
157259024Sobrien
157359024Sobrien		  s += 1;
157459024Sobrien		  while (p->name[0] > s[0])
157559024Sobrien		    p++;
157659024Sobrien		  while (p->name[0] == s[0])
157759024Sobrien		    {
157859024Sobrien		      len = strlen (p->name);
157959024Sobrien		      if (strncmp (p->name, s, len) == 0)
158059024Sobrien			break;
158159024Sobrien		      p++;
158259024Sobrien		    }
158359024Sobrien		  if (p->name[0] != s[0])
158459024Sobrien		    {
158577298Sobrien		      error_message = _(": unrecognizable v9a or v9b ancillary state register");
158659024Sobrien		      goto error;
158759024Sobrien		    }
158859024Sobrien		  if (*args == '/' && (p->regnum == 20 || p->regnum == 21))
158959024Sobrien		    {
159060484Sobrien		      error_message = _(": rd on write only ancillary state register");
159159024Sobrien		      goto error;
159277298Sobrien		    }
159377298Sobrien		  if (p->regnum >= 24
159477298Sobrien		      && (insn->architecture
159577298Sobrien			  & SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9A)))
159677298Sobrien		    {
159777298Sobrien		      /* %sys_tick and %sys_tick_cmpr are v9bnotv9a */
159877298Sobrien		      error_message = _(": unrecognizable v9a ancillary state register");
159977298Sobrien		      goto error;
160077298Sobrien		    }
160159024Sobrien		  if (*args == '/')
160259024Sobrien		    opcode |= (p->regnum << 14);
160359024Sobrien		  else
160459024Sobrien		    opcode |= (p->regnum << 25);
160559024Sobrien		  s += len;
160659024Sobrien		  continue;
160759024Sobrien		}
160859024Sobrien	      else
160959024Sobrien		{
161077298Sobrien		  error_message = _(": unrecognizable v9a or v9b ancillary state register");
161159024Sobrien		  goto error;
161259024Sobrien		}
161359024Sobrien
161459024Sobrien	    case 'M':
161559024Sobrien	    case 'm':
161659024Sobrien	      if (strncmp (s, "%asr", 4) == 0)
161759024Sobrien		{
161859024Sobrien		  s += 4;
161959024Sobrien
162089857Sobrien		  if (ISDIGIT (*s))
162159024Sobrien		    {
162259024Sobrien		      long num = 0;
162359024Sobrien
162489857Sobrien		      while (ISDIGIT (*s))
162559024Sobrien			{
162659024Sobrien			  num = num * 10 + *s - '0';
162759024Sobrien			  ++s;
162859024Sobrien			}
162959024Sobrien
163059024Sobrien		      if (current_architecture >= SPARC_OPCODE_ARCH_V9)
163159024Sobrien			{
163259024Sobrien			  if (num < 16 || 31 < num)
163359024Sobrien			    {
163460484Sobrien			      error_message = _(": asr number must be between 16 and 31");
163559024Sobrien			      goto error;
163659024Sobrien			    }
163759024Sobrien			}
163859024Sobrien		      else
163959024Sobrien			{
164059024Sobrien			  if (num < 0 || 31 < num)
164159024Sobrien			    {
164260484Sobrien			      error_message = _(": asr number must be between 0 and 31");
164359024Sobrien			      goto error;
164459024Sobrien			    }
164559024Sobrien			}
164659024Sobrien
164759024Sobrien		      opcode |= (*args == 'M' ? RS1 (num) : RD (num));
164859024Sobrien		      continue;
164959024Sobrien		    }
165059024Sobrien		  else
165159024Sobrien		    {
165260484Sobrien		      error_message = _(": expecting %asrN");
165359024Sobrien		      goto error;
165459024Sobrien		    }
165577298Sobrien		} /* if %asr  */
165659024Sobrien	      break;
165759024Sobrien
165859024Sobrien	    case 'I':
165959024Sobrien	      the_insn.reloc = BFD_RELOC_SPARC_11;
166059024Sobrien	      goto immediate;
166159024Sobrien
166259024Sobrien	    case 'j':
166359024Sobrien	      the_insn.reloc = BFD_RELOC_SPARC_10;
166459024Sobrien	      goto immediate;
166559024Sobrien
166659024Sobrien	    case 'X':
166759024Sobrien	      /* V8 systems don't understand BFD_RELOC_SPARC_5.  */
166859024Sobrien	      if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
166959024Sobrien		the_insn.reloc = BFD_RELOC_SPARC_5;
167059024Sobrien	      else
167159024Sobrien		the_insn.reloc = BFD_RELOC_SPARC13;
167259024Sobrien	      /* These fields are unsigned, but for upward compatibility,
167359024Sobrien		 allow negative values as well.  */
167459024Sobrien	      goto immediate;
167559024Sobrien
167659024Sobrien	    case 'Y':
167759024Sobrien	      /* V8 systems don't understand BFD_RELOC_SPARC_6.  */
167859024Sobrien	      if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
167959024Sobrien		the_insn.reloc = BFD_RELOC_SPARC_6;
168059024Sobrien	      else
168159024Sobrien		the_insn.reloc = BFD_RELOC_SPARC13;
168259024Sobrien	      /* These fields are unsigned, but for upward compatibility,
168359024Sobrien		 allow negative values as well.  */
168459024Sobrien	      goto immediate;
168559024Sobrien
168659024Sobrien	    case 'k':
168759024Sobrien	      the_insn.reloc = /* RELOC_WDISP2_14 */ BFD_RELOC_SPARC_WDISP16;
168859024Sobrien	      the_insn.pcrel = 1;
168959024Sobrien	      goto immediate;
169059024Sobrien
169159024Sobrien	    case 'G':
169259024Sobrien	      the_insn.reloc = BFD_RELOC_SPARC_WDISP19;
169359024Sobrien	      the_insn.pcrel = 1;
169459024Sobrien	      goto immediate;
169559024Sobrien
169659024Sobrien	    case 'N':
169759024Sobrien	      if (*s == 'p' && s[1] == 'n')
169859024Sobrien		{
169959024Sobrien		  s += 2;
170059024Sobrien		  continue;
170159024Sobrien		}
170259024Sobrien	      break;
170359024Sobrien
170459024Sobrien	    case 'T':
170559024Sobrien	      if (*s == 'p' && s[1] == 't')
170659024Sobrien		{
170759024Sobrien		  s += 2;
170859024Sobrien		  continue;
170959024Sobrien		}
171059024Sobrien	      break;
171159024Sobrien
171259024Sobrien	    case 'z':
171359024Sobrien	      if (*s == ' ')
171459024Sobrien		{
171559024Sobrien		  ++s;
171659024Sobrien		}
171759024Sobrien	      if (strncmp (s, "%icc", 4) == 0)
171859024Sobrien		{
171959024Sobrien		  s += 4;
172059024Sobrien		  continue;
172159024Sobrien		}
172259024Sobrien	      break;
172359024Sobrien
172459024Sobrien	    case 'Z':
172559024Sobrien	      if (*s == ' ')
172659024Sobrien		{
172759024Sobrien		  ++s;
172859024Sobrien		}
172959024Sobrien	      if (strncmp (s, "%xcc", 4) == 0)
173059024Sobrien		{
173159024Sobrien		  s += 4;
173259024Sobrien		  continue;
173359024Sobrien		}
173459024Sobrien	      break;
173559024Sobrien
173659024Sobrien	    case '6':
173759024Sobrien	      if (*s == ' ')
173859024Sobrien		{
173959024Sobrien		  ++s;
174059024Sobrien		}
174159024Sobrien	      if (strncmp (s, "%fcc0", 5) == 0)
174259024Sobrien		{
174359024Sobrien		  s += 5;
174459024Sobrien		  continue;
174559024Sobrien		}
174659024Sobrien	      break;
174759024Sobrien
174859024Sobrien	    case '7':
174959024Sobrien	      if (*s == ' ')
175059024Sobrien		{
175159024Sobrien		  ++s;
175259024Sobrien		}
175359024Sobrien	      if (strncmp (s, "%fcc1", 5) == 0)
175459024Sobrien		{
175559024Sobrien		  s += 5;
175659024Sobrien		  continue;
175759024Sobrien		}
175859024Sobrien	      break;
175959024Sobrien
176059024Sobrien	    case '8':
176159024Sobrien	      if (*s == ' ')
176259024Sobrien		{
176359024Sobrien		  ++s;
176459024Sobrien		}
176559024Sobrien	      if (strncmp (s, "%fcc2", 5) == 0)
176659024Sobrien		{
176759024Sobrien		  s += 5;
176859024Sobrien		  continue;
176959024Sobrien		}
177059024Sobrien	      break;
177159024Sobrien
177259024Sobrien	    case '9':
177359024Sobrien	      if (*s == ' ')
177459024Sobrien		{
177559024Sobrien		  ++s;
177659024Sobrien		}
177759024Sobrien	      if (strncmp (s, "%fcc3", 5) == 0)
177859024Sobrien		{
177959024Sobrien		  s += 5;
178059024Sobrien		  continue;
178159024Sobrien		}
178259024Sobrien	      break;
178359024Sobrien
178459024Sobrien	    case 'P':
178559024Sobrien	      if (strncmp (s, "%pc", 3) == 0)
178659024Sobrien		{
178759024Sobrien		  s += 3;
178859024Sobrien		  continue;
178959024Sobrien		}
179059024Sobrien	      break;
179159024Sobrien
179259024Sobrien	    case 'W':
179359024Sobrien	      if (strncmp (s, "%tick", 5) == 0)
179459024Sobrien		{
179559024Sobrien		  s += 5;
179659024Sobrien		  continue;
179759024Sobrien		}
179859024Sobrien	      break;
179959024Sobrien
180077298Sobrien	    case '\0':		/* End of args.  */
180159024Sobrien	      if (*s == '\0')
180259024Sobrien		{
180359024Sobrien		  match = 1;
180459024Sobrien		}
180559024Sobrien	      break;
180659024Sobrien
180759024Sobrien	    case '+':
180859024Sobrien	      if (*s == '+')
180959024Sobrien		{
181059024Sobrien		  ++s;
181159024Sobrien		  continue;
181259024Sobrien		}
181359024Sobrien	      if (*s == '-')
181459024Sobrien		{
181559024Sobrien		  continue;
181659024Sobrien		}
181759024Sobrien	      break;
181859024Sobrien
181977298Sobrien	    case '[':		/* These must match exactly.  */
182059024Sobrien	    case ']':
182159024Sobrien	    case ',':
182259024Sobrien	    case ' ':
182359024Sobrien	      if (*s++ == *args)
182459024Sobrien		continue;
182559024Sobrien	      break;
182659024Sobrien
182777298Sobrien	    case '#':		/* Must be at least one digit.  */
182889857Sobrien	      if (ISDIGIT (*s++))
182959024Sobrien		{
183089857Sobrien		  while (ISDIGIT (*s))
183159024Sobrien		    {
183259024Sobrien		      ++s;
183359024Sobrien		    }
183459024Sobrien		  continue;
183559024Sobrien		}
183659024Sobrien	      break;
183759024Sobrien
183877298Sobrien	    case 'C':		/* Coprocessor state register.  */
183959024Sobrien	      if (strncmp (s, "%csr", 4) == 0)
184059024Sobrien		{
184159024Sobrien		  s += 4;
184259024Sobrien		  continue;
184359024Sobrien		}
184459024Sobrien	      break;
184559024Sobrien
184677298Sobrien	    case 'b':		/* Next operand is a coprocessor register.  */
184759024Sobrien	    case 'c':
184859024Sobrien	    case 'D':
184989857Sobrien	      if (*s++ == '%' && *s++ == 'c' && ISDIGIT (*s))
185059024Sobrien		{
185159024Sobrien		  mask = *s++;
185289857Sobrien		  if (ISDIGIT (*s))
185359024Sobrien		    {
185459024Sobrien		      mask = 10 * (mask - '0') + (*s++ - '0');
185559024Sobrien		      if (mask >= 32)
185659024Sobrien			{
185759024Sobrien			  break;
185859024Sobrien			}
185959024Sobrien		    }
186059024Sobrien		  else
186159024Sobrien		    {
186259024Sobrien		      mask -= '0';
186359024Sobrien		    }
186459024Sobrien		  switch (*args)
186559024Sobrien		    {
186659024Sobrien
186759024Sobrien		    case 'b':
186859024Sobrien		      opcode |= mask << 14;
186959024Sobrien		      continue;
187059024Sobrien
187159024Sobrien		    case 'c':
187259024Sobrien		      opcode |= mask;
187359024Sobrien		      continue;
187459024Sobrien
187559024Sobrien		    case 'D':
187659024Sobrien		      opcode |= mask << 25;
187759024Sobrien		      continue;
187859024Sobrien		    }
187959024Sobrien		}
188059024Sobrien	      break;
188159024Sobrien
188259024Sobrien	    case 'r':		/* next operand must be a register */
188359024Sobrien	    case 'O':
188459024Sobrien	    case '1':
188559024Sobrien	    case '2':
188659024Sobrien	    case 'd':
188759024Sobrien	      if (*s++ == '%')
188859024Sobrien		{
188959024Sobrien		  switch (c = *s++)
189059024Sobrien		    {
189159024Sobrien
189259024Sobrien		    case 'f':	/* frame pointer */
189359024Sobrien		      if (*s++ == 'p')
189459024Sobrien			{
189559024Sobrien			  mask = 0x1e;
189659024Sobrien			  break;
189759024Sobrien			}
189859024Sobrien		      goto error;
189959024Sobrien
190059024Sobrien		    case 'g':	/* global register */
190160484Sobrien		      c = *s++;
190260484Sobrien		      if (isoctal (c))
190359024Sobrien			{
190459024Sobrien			  mask = c - '0';
190559024Sobrien			  break;
190659024Sobrien			}
190759024Sobrien		      goto error;
190859024Sobrien
190959024Sobrien		    case 'i':	/* in register */
191060484Sobrien		      c = *s++;
191160484Sobrien		      if (isoctal (c))
191259024Sobrien			{
191359024Sobrien			  mask = c - '0' + 24;
191459024Sobrien			  break;
191559024Sobrien			}
191659024Sobrien		      goto error;
191759024Sobrien
191859024Sobrien		    case 'l':	/* local register */
191960484Sobrien		      c = *s++;
192060484Sobrien		      if (isoctal (c))
192159024Sobrien			{
192259024Sobrien			  mask = (c - '0' + 16);
192359024Sobrien			  break;
192459024Sobrien			}
192559024Sobrien		      goto error;
192659024Sobrien
192759024Sobrien		    case 'o':	/* out register */
192860484Sobrien		      c = *s++;
192960484Sobrien		      if (isoctal (c))
193059024Sobrien			{
193159024Sobrien			  mask = (c - '0' + 8);
193259024Sobrien			  break;
193359024Sobrien			}
193459024Sobrien		      goto error;
193559024Sobrien
193659024Sobrien		    case 's':	/* stack pointer */
193759024Sobrien		      if (*s++ == 'p')
193859024Sobrien			{
193959024Sobrien			  mask = 0xe;
194059024Sobrien			  break;
194159024Sobrien			}
194259024Sobrien		      goto error;
194359024Sobrien
194459024Sobrien		    case 'r':	/* any register */
194589857Sobrien		      if (!ISDIGIT ((c = *s++)))
194659024Sobrien			{
194759024Sobrien			  goto error;
194859024Sobrien			}
194959024Sobrien		      /* FALLTHROUGH */
195059024Sobrien		    case '0':
195159024Sobrien		    case '1':
195259024Sobrien		    case '2':
195359024Sobrien		    case '3':
195459024Sobrien		    case '4':
195559024Sobrien		    case '5':
195659024Sobrien		    case '6':
195759024Sobrien		    case '7':
195859024Sobrien		    case '8':
195959024Sobrien		    case '9':
196089857Sobrien		      if (ISDIGIT (*s))
196159024Sobrien			{
196259024Sobrien			  if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32)
196359024Sobrien			    {
196459024Sobrien			      goto error;
196559024Sobrien			    }
196659024Sobrien			}
196759024Sobrien		      else
196859024Sobrien			{
196959024Sobrien			  c -= '0';
197059024Sobrien			}
197159024Sobrien		      mask = c;
197259024Sobrien		      break;
197359024Sobrien
197459024Sobrien		    default:
197559024Sobrien		      goto error;
197659024Sobrien		    }
197759024Sobrien
197860484Sobrien		  if ((mask & ~1) == 2 && sparc_arch_size == 64
197977298Sobrien		      && no_undeclared_regs && ! globals[mask])
198060484Sobrien		    as_bad (_("detected global register use not covered by .register pseudo-op"));
198160484Sobrien
198259024Sobrien		  /* Got the register, now figure out where
198359024Sobrien		     it goes in the opcode.  */
198459024Sobrien		  switch (*args)
198559024Sobrien		    {
198659024Sobrien		    case '1':
198759024Sobrien		      opcode |= mask << 14;
198859024Sobrien		      continue;
198959024Sobrien
199059024Sobrien		    case '2':
199159024Sobrien		      opcode |= mask;
199259024Sobrien		      continue;
199359024Sobrien
199459024Sobrien		    case 'd':
199559024Sobrien		      opcode |= mask << 25;
199659024Sobrien		      continue;
199759024Sobrien
199859024Sobrien		    case 'r':
199959024Sobrien		      opcode |= (mask << 25) | (mask << 14);
200059024Sobrien		      continue;
200159024Sobrien
200259024Sobrien		    case 'O':
200359024Sobrien		      opcode |= (mask << 25) | (mask << 0);
200459024Sobrien		      continue;
200559024Sobrien		    }
200659024Sobrien		}
200759024Sobrien	      break;
200859024Sobrien
200959024Sobrien	    case 'e':		/* next operand is a floating point register */
201059024Sobrien	    case 'v':
201159024Sobrien	    case 'V':
201259024Sobrien
201359024Sobrien	    case 'f':
201459024Sobrien	    case 'B':
201559024Sobrien	    case 'R':
201659024Sobrien
201759024Sobrien	    case 'g':
201859024Sobrien	    case 'H':
201959024Sobrien	    case 'J':
202059024Sobrien	      {
202159024Sobrien		char format;
202259024Sobrien
202359024Sobrien		if (*s++ == '%'
202459024Sobrien		    && ((format = *s) == 'f')
202589857Sobrien		    && ISDIGIT (*++s))
202659024Sobrien		  {
202789857Sobrien		    for (mask = 0; ISDIGIT (*s); ++s)
202859024Sobrien		      {
202959024Sobrien			mask = 10 * mask + (*s - '0');
203059024Sobrien		      }		/* read the number */
203159024Sobrien
203259024Sobrien		    if ((*args == 'v'
203359024Sobrien			 || *args == 'B'
203459024Sobrien			 || *args == 'H')
203559024Sobrien			&& (mask & 1))
203659024Sobrien		      {
203759024Sobrien			break;
203859024Sobrien		      }		/* register must be even numbered */
203959024Sobrien
204059024Sobrien		    if ((*args == 'V'
204159024Sobrien			 || *args == 'R'
204259024Sobrien			 || *args == 'J')
204359024Sobrien			&& (mask & 3))
204459024Sobrien		      {
204559024Sobrien			break;
204659024Sobrien		      }		/* register must be multiple of 4 */
204759024Sobrien
204859024Sobrien		    if (mask >= 64)
204959024Sobrien		      {
205059024Sobrien			if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
205160484Sobrien			  error_message = _(": There are only 64 f registers; [0-63]");
205259024Sobrien			else
205360484Sobrien			  error_message = _(": There are only 32 f registers; [0-31]");
205459024Sobrien			goto error;
205559024Sobrien		      }	/* on error */
205659024Sobrien		    else if (mask >= 32)
205759024Sobrien		      {
205859024Sobrien			if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
205959024Sobrien			  {
206059024Sobrien			    v9_arg_p = 1;
206159024Sobrien			    mask -= 31;	/* wrap high bit */
206259024Sobrien			  }
206359024Sobrien			else
206459024Sobrien			  {
206560484Sobrien			    error_message = _(": There are only 32 f registers; [0-31]");
206659024Sobrien			    goto error;
206759024Sobrien			  }
206859024Sobrien		      }
206959024Sobrien		  }
207059024Sobrien		else
207159024Sobrien		  {
207259024Sobrien		    break;
207377298Sobrien		  }	/* if not an 'f' register.  */
207459024Sobrien
207559024Sobrien		switch (*args)
207659024Sobrien		  {
207759024Sobrien		  case 'v':
207859024Sobrien		  case 'V':
207959024Sobrien		  case 'e':
208059024Sobrien		    opcode |= RS1 (mask);
208159024Sobrien		    continue;
208259024Sobrien
208359024Sobrien		  case 'f':
208459024Sobrien		  case 'B':
208559024Sobrien		  case 'R':
208659024Sobrien		    opcode |= RS2 (mask);
208759024Sobrien		    continue;
208859024Sobrien
208959024Sobrien		  case 'g':
209059024Sobrien		  case 'H':
209159024Sobrien		  case 'J':
209259024Sobrien		    opcode |= RD (mask);
209359024Sobrien		    continue;
209477298Sobrien		  }		/* Pack it in.  */
209559024Sobrien
209659024Sobrien		know (0);
209759024Sobrien		break;
209877298Sobrien	      }			/* float arg  */
209959024Sobrien
210059024Sobrien	    case 'F':
210159024Sobrien	      if (strncmp (s, "%fsr", 4) == 0)
210259024Sobrien		{
210359024Sobrien		  s += 4;
210459024Sobrien		  continue;
210559024Sobrien		}
210659024Sobrien	      break;
210759024Sobrien
210877298Sobrien	    case '0':		/* 64 bit immediate (set, setsw, setx insn)  */
210977298Sobrien	      the_insn.reloc = BFD_RELOC_NONE; /* reloc handled elsewhere  */
211059024Sobrien	      goto immediate;
211159024Sobrien
211277298Sobrien	    case 'l':		/* 22 bit PC relative immediate  */
211359024Sobrien	      the_insn.reloc = BFD_RELOC_SPARC_WDISP22;
211459024Sobrien	      the_insn.pcrel = 1;
211559024Sobrien	      goto immediate;
211659024Sobrien
211777298Sobrien	    case 'L':		/* 30 bit immediate  */
211859024Sobrien	      the_insn.reloc = BFD_RELOC_32_PCREL_S2;
211959024Sobrien	      the_insn.pcrel = 1;
212059024Sobrien	      goto immediate;
212159024Sobrien
212260484Sobrien	    case 'h':
212377298Sobrien	    case 'n':		/* 22 bit immediate  */
212459024Sobrien	      the_insn.reloc = BFD_RELOC_SPARC22;
212559024Sobrien	      goto immediate;
212659024Sobrien
212777298Sobrien	    case 'i':		/* 13 bit immediate  */
212859024Sobrien	      the_insn.reloc = BFD_RELOC_SPARC13;
212959024Sobrien
213059024Sobrien	      /* fallthrough */
213159024Sobrien
213259024Sobrien	    immediate:
213359024Sobrien	      if (*s == ' ')
213459024Sobrien		s++;
213559024Sobrien
213660484Sobrien	      {
213760484Sobrien		char *s1;
213860484Sobrien		char *op_arg = NULL;
213960484Sobrien		expressionS op_exp;
214060484Sobrien		bfd_reloc_code_real_type old_reloc = the_insn.reloc;
214159024Sobrien
214260484Sobrien		/* Check for %hi, etc.  */
214360484Sobrien		if (*s == '%')
214460484Sobrien		  {
214560484Sobrien		    static const struct ops {
214660484Sobrien		      /* The name as it appears in assembler.  */
214760484Sobrien		      char *name;
214860484Sobrien		      /* strlen (name), precomputed for speed */
214960484Sobrien		      int len;
215060484Sobrien		      /* The reloc this pseudo-op translates to.  */
215160484Sobrien		      int reloc;
215260484Sobrien		      /* Non-zero if for v9 only.  */
215360484Sobrien		      int v9_p;
215460484Sobrien		      /* Non-zero if can be used in pc-relative contexts.  */
215560484Sobrien		      int pcrel_p;/*FIXME:wip*/
215660484Sobrien		    } ops[] = {
215760484Sobrien		      /* hix/lox must appear before hi/lo so %hix won't be
215860484Sobrien			 mistaken for %hi.  */
215960484Sobrien		      { "hix", 3, BFD_RELOC_SPARC_HIX22, 1, 0 },
216060484Sobrien		      { "lox", 3, BFD_RELOC_SPARC_LOX10, 1, 0 },
216160484Sobrien		      { "hi", 2, BFD_RELOC_HI22, 0, 1 },
216260484Sobrien		      { "lo", 2, BFD_RELOC_LO10, 0, 1 },
216360484Sobrien		      { "hh", 2, BFD_RELOC_SPARC_HH22, 1, 1 },
216460484Sobrien		      { "hm", 2, BFD_RELOC_SPARC_HM10, 1, 1 },
216560484Sobrien		      { "lm", 2, BFD_RELOC_SPARC_LM22, 1, 1 },
216660484Sobrien		      { "h44", 3, BFD_RELOC_SPARC_H44, 1, 0 },
216760484Sobrien		      { "m44", 3, BFD_RELOC_SPARC_M44, 1, 0 },
216860484Sobrien		      { "l44", 3, BFD_RELOC_SPARC_L44, 1, 0 },
216960484Sobrien		      { "uhi", 3, BFD_RELOC_SPARC_HH22, 1, 0 },
217060484Sobrien		      { "ulo", 3, BFD_RELOC_SPARC_HM10, 1, 0 },
217177298Sobrien		      { NULL, 0, 0, 0, 0 }
217260484Sobrien		    };
217360484Sobrien		    const struct ops *o;
217477298Sobrien
217560484Sobrien		    for (o = ops; o->name; o++)
217660484Sobrien		      if (strncmp (s + 1, o->name, o->len) == 0)
217760484Sobrien			break;
217860484Sobrien		    if (o->name == NULL)
217959024Sobrien		      break;
218077298Sobrien
218160484Sobrien		    if (s[o->len + 1] != '(')
218260484Sobrien		      {
218360484Sobrien			as_bad (_("Illegal operands: %%%s requires arguments in ()"), o->name);
218460484Sobrien			return special_case;
218560484Sobrien		      }
218659024Sobrien
218760484Sobrien		    op_arg = o->name;
218860484Sobrien		    the_insn.reloc = o->reloc;
218960484Sobrien		    s += o->len + 2;
219060484Sobrien		    v9_arg_p = o->v9_p;
219160484Sobrien		  }
219259024Sobrien
219360484Sobrien		/* Note that if the get_expression() fails, we will still
219460484Sobrien		   have created U entries in the symbol table for the
219560484Sobrien		   'symbols' in the input string.  Try not to create U
219660484Sobrien		   symbols for registers, etc.  */
219760484Sobrien
219859024Sobrien		/* This stuff checks to see if the expression ends in
219959024Sobrien		   +%reg.  If it does, it removes the register from
220059024Sobrien		   the expression, and re-sets 's' to point to the
220159024Sobrien		   right place.  */
220259024Sobrien
220360484Sobrien		if (op_arg)
220460484Sobrien		  {
220560484Sobrien		    int npar = 0;
220659024Sobrien
220760484Sobrien		    for (s1 = s; *s1 && *s1 != ',' && *s1 != ']'; s1++)
220860484Sobrien		      if (*s1 == '(')
220960484Sobrien			npar++;
221060484Sobrien		      else if (*s1 == ')')
221160484Sobrien			{
221260484Sobrien			  if (!npar)
221360484Sobrien			    break;
221460484Sobrien			  npar--;
221560484Sobrien			}
221660484Sobrien
221760484Sobrien		    if (*s1 != ')')
221860484Sobrien		      {
221960484Sobrien			as_bad (_("Illegal operands: %%%s requires arguments in ()"), op_arg);
222060484Sobrien			return special_case;
222160484Sobrien		      }
222277298Sobrien
222360484Sobrien		    *s1 = '\0';
222460484Sobrien		    (void) get_expression (s);
222560484Sobrien		    *s1 = ')';
222660484Sobrien		    s = s1 + 1;
222760484Sobrien		    if (*s == ',' || *s == ']' || !*s)
222860484Sobrien		      continue;
222960484Sobrien		    if (*s != '+' && *s != '-')
223060484Sobrien		      {
223160484Sobrien			as_bad (_("Illegal operands: Can't do arithmetics other than + and - involving %%%s()"), op_arg);
223260484Sobrien			return special_case;
223360484Sobrien		      }
223460484Sobrien		    *s1 = '0';
223560484Sobrien		    s = s1;
223660484Sobrien		    op_exp = the_insn.exp;
223777298Sobrien		    memset (&the_insn.exp, 0, sizeof (the_insn.exp));
223860484Sobrien		  }
223960484Sobrien
224077298Sobrien		for (s1 = s; *s1 && *s1 != ',' && *s1 != ']'; s1++)
224177298Sobrien		  ;
224259024Sobrien
224389857Sobrien		if (s1 != s && ISDIGIT (s1[-1]))
224459024Sobrien		  {
224559024Sobrien		    if (s1[-2] == '%' && s1[-3] == '+')
224660484Sobrien		      s1 -= 3;
224760484Sobrien		    else if (strchr ("goli0123456789", s1[-2]) && s1[-3] == '%' && s1[-4] == '+')
224860484Sobrien		      s1 -= 4;
224960484Sobrien		    else
225060484Sobrien		      s1 = NULL;
225160484Sobrien		    if (s1)
225259024Sobrien		      {
225359024Sobrien			*s1 = '\0';
225460484Sobrien			if (op_arg && s1 == s + 1)
225560484Sobrien			  the_insn.exp.X_op = O_absent;
225660484Sobrien			else
225760484Sobrien			  (void) get_expression (s);
225859024Sobrien			*s1 = '+';
225960484Sobrien			if (op_arg)
226060484Sobrien			  *s = ')';
226159024Sobrien			s = s1;
226259024Sobrien		      }
226360484Sobrien		  }
226460484Sobrien		else
226560484Sobrien		  s1 = NULL;
226660484Sobrien
226760484Sobrien		if (!s1)
226860484Sobrien		  {
226960484Sobrien		    (void) get_expression (s);
227060484Sobrien		    if (op_arg)
227160484Sobrien		      *s = ')';
227260484Sobrien		    s = expr_end;
227360484Sobrien		  }
227460484Sobrien
227560484Sobrien		if (op_arg)
227660484Sobrien		  {
227760484Sobrien		    the_insn.exp2 = the_insn.exp;
227860484Sobrien		    the_insn.exp = op_exp;
227960484Sobrien		    if (the_insn.exp2.X_op == O_absent)
228060484Sobrien		      the_insn.exp2.X_op = O_illegal;
228160484Sobrien		    else if (the_insn.exp.X_op == O_absent)
228259024Sobrien		      {
228360484Sobrien			the_insn.exp = the_insn.exp2;
228460484Sobrien			the_insn.exp2.X_op = O_illegal;
228559024Sobrien		      }
228660484Sobrien		    else if (the_insn.exp.X_op == O_constant)
228760484Sobrien		      {
228860484Sobrien			valueT val = the_insn.exp.X_add_number;
228960484Sobrien			switch (the_insn.reloc)
229060484Sobrien			  {
229160484Sobrien			  default:
229260484Sobrien			    break;
229360484Sobrien
229460484Sobrien			  case BFD_RELOC_SPARC_HH22:
229560484Sobrien			    val = BSR (val, 32);
229677298Sobrien			    /* Fall through.  */
229760484Sobrien
229860484Sobrien			  case BFD_RELOC_SPARC_LM22:
229960484Sobrien			  case BFD_RELOC_HI22:
230060484Sobrien			    val = (val >> 10) & 0x3fffff;
230160484Sobrien			    break;
230260484Sobrien
230360484Sobrien			  case BFD_RELOC_SPARC_HM10:
230460484Sobrien			    val = BSR (val, 32);
230577298Sobrien			    /* Fall through.  */
230660484Sobrien
230760484Sobrien			  case BFD_RELOC_LO10:
230860484Sobrien			    val &= 0x3ff;
230960484Sobrien			    break;
231060484Sobrien
231160484Sobrien			  case BFD_RELOC_SPARC_H44:
231260484Sobrien			    val >>= 22;
231360484Sobrien			    val &= 0x3fffff;
231460484Sobrien			    break;
231560484Sobrien
231660484Sobrien			  case BFD_RELOC_SPARC_M44:
231760484Sobrien			    val >>= 12;
231860484Sobrien			    val &= 0x3ff;
231960484Sobrien			    break;
232060484Sobrien
232160484Sobrien			  case BFD_RELOC_SPARC_L44:
232260484Sobrien			    val &= 0xfff;
232360484Sobrien			    break;
232460484Sobrien
232560484Sobrien			  case BFD_RELOC_SPARC_HIX22:
232677298Sobrien			    val = ~val;
232760484Sobrien			    val = (val >> 10) & 0x3fffff;
232860484Sobrien			    break;
232960484Sobrien
233060484Sobrien			  case BFD_RELOC_SPARC_LOX10:
233160484Sobrien			    val = (val & 0x3ff) | 0x1c00;
233260484Sobrien			    break;
233360484Sobrien			  }
233460484Sobrien			the_insn.exp = the_insn.exp2;
233560484Sobrien			the_insn.exp.X_add_number += val;
233660484Sobrien			the_insn.exp2.X_op = O_illegal;
233760484Sobrien			the_insn.reloc = old_reloc;
233860484Sobrien		      }
233960484Sobrien		    else if (the_insn.exp2.X_op != O_constant)
234060484Sobrien		      {
234160484Sobrien			as_bad (_("Illegal operands: Can't add non-constant expression to %%%s()"), op_arg);
234260484Sobrien			return special_case;
234360484Sobrien		      }
234460484Sobrien		    else
234560484Sobrien		      {
234660484Sobrien			if (old_reloc != BFD_RELOC_SPARC13
234760484Sobrien			    || the_insn.reloc != BFD_RELOC_LO10
234860484Sobrien			    || sparc_arch_size != 64
234960484Sobrien			    || sparc_pic_code)
235060484Sobrien			  {
235160484Sobrien			    as_bad (_("Illegal operands: Can't do arithmetics involving %%%s() of a relocatable symbol"), op_arg);
235260484Sobrien			    return special_case;
235360484Sobrien			  }
235460484Sobrien			the_insn.reloc = BFD_RELOC_SPARC_OLO10;
235560484Sobrien		      }
235659024Sobrien		  }
235759024Sobrien	      }
235859024Sobrien	      /* Check for constants that don't require emitting a reloc.  */
235959024Sobrien	      if (the_insn.exp.X_op == O_constant
236059024Sobrien		  && the_insn.exp.X_add_symbol == 0
236159024Sobrien		  && the_insn.exp.X_op_symbol == 0)
236259024Sobrien		{
236359024Sobrien		  /* For pc-relative call instructions, we reject
236459024Sobrien		     constants to get better code.  */
236559024Sobrien		  if (the_insn.pcrel
236659024Sobrien		      && the_insn.reloc == BFD_RELOC_32_PCREL_S2
236759024Sobrien		      && in_signed_range (the_insn.exp.X_add_number, 0x3fff))
236859024Sobrien		    {
236960484Sobrien		      error_message = _(": PC-relative operand can't be a constant");
237059024Sobrien		      goto error;
237159024Sobrien		    }
237259024Sobrien
237359024Sobrien		  /* Constants that won't fit are checked in md_apply_fix3
237459024Sobrien		     and bfd_install_relocation.
237559024Sobrien		     ??? It would be preferable to install the constants
237659024Sobrien		     into the insn here and save having to create a fixS
237759024Sobrien		     for each one.  There already exists code to handle
237859024Sobrien		     all the various cases (e.g. in md_apply_fix3 and
237959024Sobrien		     bfd_install_relocation) so duplicating all that code
238059024Sobrien		     here isn't right.  */
238159024Sobrien		}
238259024Sobrien
238359024Sobrien	      continue;
238459024Sobrien
238559024Sobrien	    case 'a':
238659024Sobrien	      if (*s++ == 'a')
238759024Sobrien		{
238859024Sobrien		  opcode |= ANNUL;
238959024Sobrien		  continue;
239059024Sobrien		}
239159024Sobrien	      break;
239259024Sobrien
239359024Sobrien	    case 'A':
239459024Sobrien	      {
239559024Sobrien		int asi = 0;
239659024Sobrien
239759024Sobrien		/* Parse an asi.  */
239859024Sobrien		if (*s == '#')
239959024Sobrien		  {
240059024Sobrien		    if (! parse_keyword_arg (sparc_encode_asi, &s, &asi))
240159024Sobrien		      {
240260484Sobrien			error_message = _(": invalid ASI name");
240359024Sobrien			goto error;
240459024Sobrien		      }
240559024Sobrien		  }
240659024Sobrien		else
240759024Sobrien		  {
240859024Sobrien		    if (! parse_const_expr_arg (&s, &asi))
240959024Sobrien		      {
241060484Sobrien			error_message = _(": invalid ASI expression");
241159024Sobrien			goto error;
241259024Sobrien		      }
241359024Sobrien		    if (asi < 0 || asi > 255)
241459024Sobrien		      {
241560484Sobrien			error_message = _(": invalid ASI number");
241659024Sobrien			goto error;
241759024Sobrien		      }
241859024Sobrien		  }
241959024Sobrien		opcode |= ASI (asi);
242059024Sobrien		continue;
242177298Sobrien	      }			/* Alternate space.  */
242259024Sobrien
242359024Sobrien	    case 'p':
242459024Sobrien	      if (strncmp (s, "%psr", 4) == 0)
242559024Sobrien		{
242659024Sobrien		  s += 4;
242759024Sobrien		  continue;
242859024Sobrien		}
242959024Sobrien	      break;
243059024Sobrien
243177298Sobrien	    case 'q':		/* Floating point queue.  */
243259024Sobrien	      if (strncmp (s, "%fq", 3) == 0)
243359024Sobrien		{
243459024Sobrien		  s += 3;
243559024Sobrien		  continue;
243659024Sobrien		}
243759024Sobrien	      break;
243859024Sobrien
243977298Sobrien	    case 'Q':		/* Coprocessor queue.  */
244059024Sobrien	      if (strncmp (s, "%cq", 3) == 0)
244159024Sobrien		{
244259024Sobrien		  s += 3;
244359024Sobrien		  continue;
244459024Sobrien		}
244559024Sobrien	      break;
244659024Sobrien
244759024Sobrien	    case 'S':
244859024Sobrien	      if (strcmp (str, "set") == 0
244959024Sobrien		  || strcmp (str, "setuw") == 0)
245059024Sobrien		{
245159024Sobrien		  special_case = SPECIAL_CASE_SET;
245259024Sobrien		  continue;
245359024Sobrien		}
245459024Sobrien	      else if (strcmp (str, "setsw") == 0)
245559024Sobrien		{
245659024Sobrien		  special_case = SPECIAL_CASE_SETSW;
245759024Sobrien		  continue;
245859024Sobrien		}
245959024Sobrien	      else if (strcmp (str, "setx") == 0)
246059024Sobrien		{
246159024Sobrien		  special_case = SPECIAL_CASE_SETX;
246259024Sobrien		  continue;
246359024Sobrien		}
246459024Sobrien	      else if (strncmp (str, "fdiv", 4) == 0)
246559024Sobrien		{
246659024Sobrien		  special_case = SPECIAL_CASE_FDIV;
246759024Sobrien		  continue;
246859024Sobrien		}
246959024Sobrien	      break;
247059024Sobrien
247159024Sobrien	    case 'o':
247259024Sobrien	      if (strncmp (s, "%asi", 4) != 0)
247359024Sobrien		break;
247459024Sobrien	      s += 4;
247559024Sobrien	      continue;
247659024Sobrien
247759024Sobrien	    case 's':
247859024Sobrien	      if (strncmp (s, "%fprs", 5) != 0)
247959024Sobrien		break;
248059024Sobrien	      s += 5;
248159024Sobrien	      continue;
248259024Sobrien
248359024Sobrien	    case 'E':
248459024Sobrien	      if (strncmp (s, "%ccr", 4) != 0)
248559024Sobrien		break;
248659024Sobrien	      s += 4;
248759024Sobrien	      continue;
248859024Sobrien
248959024Sobrien	    case 't':
249059024Sobrien	      if (strncmp (s, "%tbr", 4) != 0)
249159024Sobrien		break;
249259024Sobrien	      s += 4;
249359024Sobrien	      continue;
249459024Sobrien
249559024Sobrien	    case 'w':
249659024Sobrien	      if (strncmp (s, "%wim", 4) != 0)
249759024Sobrien		break;
249859024Sobrien	      s += 4;
249959024Sobrien	      continue;
250059024Sobrien
250159024Sobrien	    case 'x':
250259024Sobrien	      {
250359024Sobrien		char *push = input_line_pointer;
250459024Sobrien		expressionS e;
250559024Sobrien
250659024Sobrien		input_line_pointer = s;
250759024Sobrien		expression (&e);
250859024Sobrien		if (e.X_op == O_constant)
250959024Sobrien		  {
251059024Sobrien		    int n = e.X_add_number;
251159024Sobrien		    if (n != e.X_add_number || (n & ~0x1ff) != 0)
251260484Sobrien		      as_bad (_("OPF immediate operand out of range (0-0x1ff)"));
251359024Sobrien		    else
251459024Sobrien		      opcode |= e.X_add_number << 5;
251559024Sobrien		  }
251659024Sobrien		else
251760484Sobrien		  as_bad (_("non-immediate OPF operand, ignored"));
251859024Sobrien		s = input_line_pointer;
251959024Sobrien		input_line_pointer = push;
252059024Sobrien		continue;
252159024Sobrien	      }
252259024Sobrien
252359024Sobrien	    case 'y':
252459024Sobrien	      if (strncmp (s, "%y", 2) != 0)
252559024Sobrien		break;
252659024Sobrien	      s += 2;
252759024Sobrien	      continue;
252859024Sobrien
252959024Sobrien	    case 'u':
253059024Sobrien	    case 'U':
253159024Sobrien	      {
253259024Sobrien		/* Parse a sparclet cpreg.  */
253359024Sobrien		int cpreg;
253459024Sobrien		if (! parse_keyword_arg (sparc_encode_sparclet_cpreg, &s, &cpreg))
253559024Sobrien		  {
253660484Sobrien		    error_message = _(": invalid cpreg name");
253759024Sobrien		    goto error;
253859024Sobrien		  }
253959024Sobrien		opcode |= (*args == 'U' ? RS1 (cpreg) : RD (cpreg));
254059024Sobrien		continue;
254159024Sobrien	      }
254259024Sobrien
254359024Sobrien	    default:
254460484Sobrien	      as_fatal (_("failed sanity check."));
254577298Sobrien	    }			/* switch on arg code.  */
254659024Sobrien
254759024Sobrien	  /* Break out of for() loop.  */
254859024Sobrien	  break;
254977298Sobrien	}			/* For each arg that we expect.  */
255059024Sobrien
255159024Sobrien    error:
255259024Sobrien      if (match == 0)
255359024Sobrien	{
255477298Sobrien	  /* Args don't match.  */
255559024Sobrien	  if (&insn[1] - sparc_opcodes < sparc_num_opcodes
255659024Sobrien	      && (insn->name == insn[1].name
255759024Sobrien		  || !strcmp (insn->name, insn[1].name)))
255859024Sobrien	    {
255959024Sobrien	      ++insn;
256059024Sobrien	      s = argsStart;
256159024Sobrien	      continue;
256259024Sobrien	    }
256359024Sobrien	  else
256459024Sobrien	    {
256560484Sobrien	      as_bad (_("Illegal operands%s"), error_message);
256660484Sobrien	      return special_case;
256759024Sobrien	    }
256859024Sobrien	}
256959024Sobrien      else
257059024Sobrien	{
257177298Sobrien	  /* We have a match.  Now see if the architecture is OK.  */
257259024Sobrien	  int needed_arch_mask = insn->architecture;
257359024Sobrien
257459024Sobrien	  if (v9_arg_p)
257559024Sobrien	    {
257677298Sobrien	      needed_arch_mask &=
257777298Sobrien		~(SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9) - 1);
257877298Sobrien	      if (! needed_arch_mask)
257977298Sobrien		needed_arch_mask =
258077298Sobrien		  SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9);
258159024Sobrien	    }
258259024Sobrien
258377298Sobrien	  if (needed_arch_mask
258477298Sobrien	      & SPARC_OPCODE_SUPPORTED (current_architecture))
258577298Sobrien	    /* OK.  */
258677298Sobrien	    ;
258759024Sobrien	  /* Can we bump up the architecture?  */
258877298Sobrien	  else if (needed_arch_mask
258977298Sobrien		   & SPARC_OPCODE_SUPPORTED (max_architecture))
259059024Sobrien	    {
259159024Sobrien	      enum sparc_opcode_arch_val needed_architecture =
259259024Sobrien		sparc_ffs (SPARC_OPCODE_SUPPORTED (max_architecture)
259359024Sobrien			   & needed_arch_mask);
259459024Sobrien
259559024Sobrien	      assert (needed_architecture <= SPARC_OPCODE_ARCH_MAX);
259659024Sobrien	      if (warn_on_bump
259759024Sobrien		  && needed_architecture > warn_after_architecture)
259859024Sobrien		{
259960484Sobrien		  as_warn (_("architecture bumped from \"%s\" to \"%s\" on \"%s\""),
260059024Sobrien			   sparc_opcode_archs[current_architecture].name,
260159024Sobrien			   sparc_opcode_archs[needed_architecture].name,
260259024Sobrien			   str);
260359024Sobrien		  warn_after_architecture = needed_architecture;
260459024Sobrien		}
260559024Sobrien	      current_architecture = needed_architecture;
260659024Sobrien	    }
260759024Sobrien	  /* Conflict.  */
260859024Sobrien	  /* ??? This seems to be a bit fragile.  What if the next entry in
260959024Sobrien	     the opcode table is the one we want and it is supported?
261059024Sobrien	     It is possible to arrange the table today so that this can't
261159024Sobrien	     happen but what about tomorrow?  */
261259024Sobrien	  else
261359024Sobrien	    {
261477298Sobrien	      int arch, printed_one_p = 0;
261559024Sobrien	      char *p;
261659024Sobrien	      char required_archs[SPARC_OPCODE_ARCH_MAX * 16];
261759024Sobrien
261859024Sobrien	      /* Create a list of the architectures that support the insn.  */
261977298Sobrien	      needed_arch_mask &= ~SPARC_OPCODE_SUPPORTED (max_architecture);
262059024Sobrien	      p = required_archs;
262159024Sobrien	      arch = sparc_ffs (needed_arch_mask);
262259024Sobrien	      while ((1 << arch) <= needed_arch_mask)
262359024Sobrien		{
262459024Sobrien		  if ((1 << arch) & needed_arch_mask)
262559024Sobrien		    {
262659024Sobrien		      if (printed_one_p)
262759024Sobrien			*p++ = '|';
262859024Sobrien		      strcpy (p, sparc_opcode_archs[arch].name);
262959024Sobrien		      p += strlen (p);
263059024Sobrien		      printed_one_p = 1;
263159024Sobrien		    }
263259024Sobrien		  ++arch;
263359024Sobrien		}
263459024Sobrien
263560484Sobrien	      as_bad (_("Architecture mismatch on \"%s\"."), str);
263660484Sobrien	      as_tsktsk (_(" (Requires %s; requested architecture is %s.)"),
263759024Sobrien			 required_archs,
263859024Sobrien			 sparc_opcode_archs[max_architecture].name);
263960484Sobrien	      return special_case;
264059024Sobrien	    }
264177298Sobrien	} /* If no match.  */
264259024Sobrien
264359024Sobrien      break;
264477298Sobrien    } /* Forever looking for a match.  */
264559024Sobrien
264659024Sobrien  the_insn.opcode = opcode;
264760484Sobrien  return special_case;
264859024Sobrien}
264959024Sobrien
265059024Sobrien/* Parse an argument that can be expressed as a keyword.
265159024Sobrien   (eg: #StoreStore or %ccfr).
265259024Sobrien   The result is a boolean indicating success.
265359024Sobrien   If successful, INPUT_POINTER is updated.  */
265459024Sobrien
265559024Sobrienstatic int
265659024Sobrienparse_keyword_arg (lookup_fn, input_pointerP, valueP)
265759024Sobrien     int (*lookup_fn) PARAMS ((const char *));
265859024Sobrien     char **input_pointerP;
265959024Sobrien     int *valueP;
266059024Sobrien{
266159024Sobrien  int value;
266259024Sobrien  char c, *p, *q;
266359024Sobrien
266459024Sobrien  p = *input_pointerP;
266559024Sobrien  for (q = p + (*p == '#' || *p == '%');
266689857Sobrien       ISALNUM (*q) || *q == '_';
266759024Sobrien       ++q)
266859024Sobrien    continue;
266959024Sobrien  c = *q;
267059024Sobrien  *q = 0;
267159024Sobrien  value = (*lookup_fn) (p);
267259024Sobrien  *q = c;
267359024Sobrien  if (value == -1)
267459024Sobrien    return 0;
267559024Sobrien  *valueP = value;
267659024Sobrien  *input_pointerP = q;
267759024Sobrien  return 1;
267859024Sobrien}
267959024Sobrien
268059024Sobrien/* Parse an argument that is a constant expression.
268159024Sobrien   The result is a boolean indicating success.  */
268259024Sobrien
268359024Sobrienstatic int
268459024Sobrienparse_const_expr_arg (input_pointerP, valueP)
268559024Sobrien     char **input_pointerP;
268659024Sobrien     int *valueP;
268759024Sobrien{
268859024Sobrien  char *save = input_line_pointer;
268959024Sobrien  expressionS exp;
269059024Sobrien
269159024Sobrien  input_line_pointer = *input_pointerP;
269259024Sobrien  /* The next expression may be something other than a constant
269359024Sobrien     (say if we're not processing the right variant of the insn).
269459024Sobrien     Don't call expression unless we're sure it will succeed as it will
269559024Sobrien     signal an error (which we want to defer until later).  */
269659024Sobrien  /* FIXME: It might be better to define md_operand and have it recognize
269759024Sobrien     things like %asi, etc. but continuing that route through to the end
269859024Sobrien     is a lot of work.  */
269959024Sobrien  if (*input_line_pointer == '%')
270059024Sobrien    {
270159024Sobrien      input_line_pointer = save;
270259024Sobrien      return 0;
270359024Sobrien    }
270459024Sobrien  expression (&exp);
270559024Sobrien  *input_pointerP = input_line_pointer;
270659024Sobrien  input_line_pointer = save;
270759024Sobrien  if (exp.X_op != O_constant)
270859024Sobrien    return 0;
270959024Sobrien  *valueP = exp.X_add_number;
271059024Sobrien  return 1;
271159024Sobrien}
271259024Sobrien
271359024Sobrien/* Subroutine of sparc_ip to parse an expression.  */
271459024Sobrien
271559024Sobrienstatic int
271659024Sobrienget_expression (str)
271759024Sobrien     char *str;
271859024Sobrien{
271959024Sobrien  char *save_in;
272059024Sobrien  segT seg;
272159024Sobrien
272259024Sobrien  save_in = input_line_pointer;
272359024Sobrien  input_line_pointer = str;
272459024Sobrien  seg = expression (&the_insn.exp);
272559024Sobrien  if (seg != absolute_section
272659024Sobrien      && seg != text_section
272759024Sobrien      && seg != data_section
272859024Sobrien      && seg != bss_section
272959024Sobrien      && seg != undefined_section)
273059024Sobrien    {
273160484Sobrien      the_insn.error = _("bad segment");
273259024Sobrien      expr_end = input_line_pointer;
273359024Sobrien      input_line_pointer = save_in;
273459024Sobrien      return 1;
273559024Sobrien    }
273659024Sobrien  expr_end = input_line_pointer;
273759024Sobrien  input_line_pointer = save_in;
273859024Sobrien  return 0;
273959024Sobrien}
274059024Sobrien
274159024Sobrien/* Subroutine of md_assemble to output one insn.  */
274259024Sobrien
274359024Sobrienstatic void
274459024Sobrienoutput_insn (insn, the_insn)
274559024Sobrien     const struct sparc_opcode *insn;
274659024Sobrien     struct sparc_it *the_insn;
274759024Sobrien{
274859024Sobrien  char *toP = frag_more (4);
274959024Sobrien
275077298Sobrien  /* Put out the opcode.  */
275159024Sobrien  if (INSN_BIG_ENDIAN)
275259024Sobrien    number_to_chars_bigendian (toP, (valueT) the_insn->opcode, 4);
275359024Sobrien  else
275459024Sobrien    number_to_chars_littleendian (toP, (valueT) the_insn->opcode, 4);
275559024Sobrien
275677298Sobrien  /* Put out the symbol-dependent stuff.  */
275759024Sobrien  if (the_insn->reloc != BFD_RELOC_NONE)
275859024Sobrien    {
275977298Sobrien      fixS *fixP =  fix_new_exp (frag_now,	/* Which frag.  */
276077298Sobrien				 (toP - frag_now->fr_literal),	/* Where.  */
276177298Sobrien				 4,		/* Size.  */
276259024Sobrien				 &the_insn->exp,
276359024Sobrien				 the_insn->pcrel,
276459024Sobrien				 the_insn->reloc);
276559024Sobrien      /* Turn off overflow checking in fixup_segment.  We'll do our
276659024Sobrien	 own overflow checking in md_apply_fix3.  This is necessary because
276759024Sobrien	 the insn size is 4 and fixup_segment will signal an overflow for
276859024Sobrien	 large 8 byte quantities.  */
276959024Sobrien      fixP->fx_no_overflow = 1;
277060484Sobrien      if (the_insn->reloc == BFD_RELOC_SPARC_OLO10)
277160484Sobrien	fixP->tc_fix_data = the_insn->exp2.X_add_number;
277259024Sobrien    }
277359024Sobrien
277459024Sobrien  last_insn = insn;
277559024Sobrien  last_opcode = the_insn->opcode;
277677298Sobrien
277777298Sobrien#ifdef OBJ_ELF
277877298Sobrien  dwarf2_emit_insn (4);
277977298Sobrien#endif
278059024Sobrien}
278159024Sobrien
278277298Sobrien/* This is identical to the md_atof in m68k.c.  I think this is right,
278377298Sobrien   but I'm not sure.
278459024Sobrien
278577298Sobrien   Turn a string in input_line_pointer into a floating point constant
278677298Sobrien   of type TYPE, and store the appropriate bytes in *LITP.  The number
278777298Sobrien   of LITTLENUMS emitted is stored in *SIZEP.  An error message is
278877298Sobrien   returned, or NULL on OK.  */
278959024Sobrien
279077298Sobrien/* Equal to MAX_PRECISION in atof-ieee.c.  */
279159024Sobrien#define MAX_LITTLENUMS 6
279259024Sobrien
279359024Sobrienchar *
279459024Sobrienmd_atof (type, litP, sizeP)
279559024Sobrien     char type;
279659024Sobrien     char *litP;
279759024Sobrien     int *sizeP;
279859024Sobrien{
279977298Sobrien  int i, prec;
280059024Sobrien  LITTLENUM_TYPE words[MAX_LITTLENUMS];
280159024Sobrien  char *t;
280259024Sobrien
280359024Sobrien  switch (type)
280459024Sobrien    {
280559024Sobrien    case 'f':
280659024Sobrien    case 'F':
280759024Sobrien    case 's':
280859024Sobrien    case 'S':
280959024Sobrien      prec = 2;
281059024Sobrien      break;
281159024Sobrien
281259024Sobrien    case 'd':
281359024Sobrien    case 'D':
281459024Sobrien    case 'r':
281559024Sobrien    case 'R':
281659024Sobrien      prec = 4;
281759024Sobrien      break;
281859024Sobrien
281959024Sobrien    case 'x':
282059024Sobrien    case 'X':
282159024Sobrien      prec = 6;
282259024Sobrien      break;
282359024Sobrien
282459024Sobrien    case 'p':
282559024Sobrien    case 'P':
282659024Sobrien      prec = 6;
282759024Sobrien      break;
282859024Sobrien
282959024Sobrien    default:
283059024Sobrien      *sizeP = 0;
283160484Sobrien      return _("Bad call to MD_ATOF()");
283259024Sobrien    }
283359024Sobrien
283459024Sobrien  t = atof_ieee (input_line_pointer, type, words);
283559024Sobrien  if (t)
283659024Sobrien    input_line_pointer = t;
283759024Sobrien  *sizeP = prec * sizeof (LITTLENUM_TYPE);
283859024Sobrien
283959024Sobrien  if (target_big_endian)
284059024Sobrien    {
284159024Sobrien      for (i = 0; i < prec; i++)
284259024Sobrien	{
284377298Sobrien	  md_number_to_chars (litP, (valueT) words[i],
284477298Sobrien			      sizeof (LITTLENUM_TYPE));
284559024Sobrien	  litP += sizeof (LITTLENUM_TYPE);
284659024Sobrien	}
284759024Sobrien    }
284859024Sobrien  else
284959024Sobrien    {
285059024Sobrien      for (i = prec - 1; i >= 0; i--)
285159024Sobrien	{
285277298Sobrien	  md_number_to_chars (litP, (valueT) words[i],
285377298Sobrien			      sizeof (LITTLENUM_TYPE));
285459024Sobrien	  litP += sizeof (LITTLENUM_TYPE);
285559024Sobrien	}
285659024Sobrien    }
285777298Sobrien
285859024Sobrien  return 0;
285959024Sobrien}
286059024Sobrien
286159024Sobrien/* Write a value out to the object file, using the appropriate
286259024Sobrien   endianness.  */
286359024Sobrien
286459024Sobrienvoid
286559024Sobrienmd_number_to_chars (buf, val, n)
286659024Sobrien     char *buf;
286759024Sobrien     valueT val;
286859024Sobrien     int n;
286959024Sobrien{
287059024Sobrien  if (target_big_endian)
287159024Sobrien    number_to_chars_bigendian (buf, val, n);
287260484Sobrien  else if (target_little_endian_data
287360484Sobrien	   && ((n == 4 || n == 2) && ~now_seg->flags & SEC_ALLOC))
287477298Sobrien    /* Output debug words, which are not in allocated sections, as big
287577298Sobrien       endian.  */
287660484Sobrien    number_to_chars_bigendian (buf, val, n);
287760484Sobrien  else if (target_little_endian_data || ! target_big_endian)
287859024Sobrien    number_to_chars_littleendian (buf, val, n);
287959024Sobrien}
288059024Sobrien
288159024Sobrien/* Apply a fixS to the frags, now that we know the value it ought to
288277298Sobrien   hold.  */
288359024Sobrien
288489857Sobrienvoid
288589857Sobrienmd_apply_fix3 (fixP, valP, segment)
288659024Sobrien     fixS *fixP;
288789857Sobrien     valueT *valP;
288859024Sobrien     segT segment;
288959024Sobrien{
289059024Sobrien  char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
289189857Sobrien  offsetT val = * (offsetT *) valP;
289259024Sobrien  long insn;
289359024Sobrien
289459024Sobrien  assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
289559024Sobrien
289677298Sobrien  fixP->fx_addnumber = val;	/* Remember value for emit_reloc.  */
289759024Sobrien
289859024Sobrien#ifdef OBJ_ELF
289959024Sobrien  /* FIXME: SPARC ELF relocations don't use an addend in the data
290059024Sobrien     field itself.  This whole approach should be somehow combined
290159024Sobrien     with the calls to bfd_install_relocation.  Also, the value passed
290259024Sobrien     in by fixup_segment includes the value of a defined symbol.  We
290359024Sobrien     don't want to include the value of an externally visible symbol.  */
290459024Sobrien  if (fixP->fx_addsy != NULL)
290559024Sobrien    {
290689857Sobrien	symbolS * sym = fixP->fx_addsy;
290789857Sobrien        segT      seg = S_GET_SEGMENT (sym);
290889857Sobrien
290989857Sobrien      if (symbol_used_in_reloc_p (sym)
291089857Sobrien	  && (S_IS_EXTERNAL (sym)
291189857Sobrien	      || S_IS_WEAK (sym)
291289857Sobrien	      || (seg->flags & SEC_MERGE)
291359024Sobrien	      || (sparc_pic_code && ! fixP->fx_pcrel)
291489857Sobrien	      || (seg != segment
291589857Sobrien		  && (((bfd_get_section_flags (stdoutput, seg) & SEC_LINK_ONCE) != 0)
291689857Sobrien		      || (strncmp (segment_name (seg),
291789857Sobrien			 	   ".gnu.linkonce",
291889857Sobrien				   sizeof ".gnu.linkonce" - 1) == 0))))
291989857Sobrien	  && seg != absolute_section
292089857Sobrien	  && seg != undefined_section
292189857Sobrien	  && ! bfd_is_com_section (seg))
292289857Sobrien	fixP->fx_addnumber -= S_GET_VALUE (sym);
292389857Sobrien
292489857Sobrien      return;
292559024Sobrien    }
292659024Sobrien#endif
292759024Sobrien
292859024Sobrien  /* This is a hack.  There should be a better way to
292959024Sobrien     handle this.  Probably in terms of howto fields, once
293059024Sobrien     we can look at these fixups in terms of howtos.  */
293159024Sobrien  if (fixP->fx_r_type == BFD_RELOC_32_PCREL_S2 && fixP->fx_addsy)
293259024Sobrien    val += fixP->fx_where + fixP->fx_frag->fr_address;
293359024Sobrien
293459024Sobrien#ifdef OBJ_AOUT
293559024Sobrien  /* FIXME: More ridiculous gas reloc hacking.  If we are going to
293659024Sobrien     generate a reloc, then we just want to let the reloc addend set
293759024Sobrien     the value.  We do not want to also stuff the addend into the
293859024Sobrien     object file.  Including the addend in the object file works when
293959024Sobrien     doing a static link, because the linker will ignore the object
294059024Sobrien     file contents.  However, the dynamic linker does not ignore the
294159024Sobrien     object file contents.  */
294259024Sobrien  if (fixP->fx_addsy != NULL
294359024Sobrien      && fixP->fx_r_type != BFD_RELOC_32_PCREL_S2)
294459024Sobrien    val = 0;
294559024Sobrien
294659024Sobrien  /* When generating PIC code, we do not want an addend for a reloc
294759024Sobrien     against a local symbol.  We adjust fx_addnumber to cancel out the
294859024Sobrien     value already included in val, and to also cancel out the
294959024Sobrien     adjustment which bfd_install_relocation will create.  */
295059024Sobrien  if (sparc_pic_code
295159024Sobrien      && fixP->fx_r_type != BFD_RELOC_32_PCREL_S2
295259024Sobrien      && fixP->fx_addsy != NULL
295359024Sobrien      && ! S_IS_COMMON (fixP->fx_addsy)
295460484Sobrien      && symbol_section_p (fixP->fx_addsy))
295559024Sobrien    fixP->fx_addnumber -= 2 * S_GET_VALUE (fixP->fx_addsy);
295660484Sobrien
295760484Sobrien  /* When generating PIC code, we need to fiddle to get
295860484Sobrien     bfd_install_relocation to do the right thing for a PC relative
295960484Sobrien     reloc against a local symbol which we are going to keep.  */
296060484Sobrien  if (sparc_pic_code
296160484Sobrien      && fixP->fx_r_type == BFD_RELOC_32_PCREL_S2
296260484Sobrien      && fixP->fx_addsy != NULL
296360484Sobrien      && (S_IS_EXTERNAL (fixP->fx_addsy)
296460484Sobrien	  || S_IS_WEAK (fixP->fx_addsy))
296560484Sobrien      && S_IS_DEFINED (fixP->fx_addsy)
296660484Sobrien      && ! S_IS_COMMON (fixP->fx_addsy))
296760484Sobrien    {
296860484Sobrien      val = 0;
296960484Sobrien      fixP->fx_addnumber -= 2 * S_GET_VALUE (fixP->fx_addsy);
297060484Sobrien    }
297159024Sobrien#endif
297259024Sobrien
297359024Sobrien  /* If this is a data relocation, just output VAL.  */
297459024Sobrien
297578828Sobrien  if (fixP->fx_r_type == BFD_RELOC_16
297678828Sobrien      || fixP->fx_r_type == BFD_RELOC_SPARC_UA16)
297759024Sobrien    {
297859024Sobrien      md_number_to_chars (buf, val, 2);
297959024Sobrien    }
298060484Sobrien  else if (fixP->fx_r_type == BFD_RELOC_32
298178828Sobrien	   || fixP->fx_r_type == BFD_RELOC_SPARC_UA32
298260484Sobrien	   || fixP->fx_r_type == BFD_RELOC_SPARC_REV32)
298359024Sobrien    {
298459024Sobrien      md_number_to_chars (buf, val, 4);
298559024Sobrien    }
298678828Sobrien  else if (fixP->fx_r_type == BFD_RELOC_64
298778828Sobrien	   || fixP->fx_r_type == BFD_RELOC_SPARC_UA64)
298859024Sobrien    {
298959024Sobrien      md_number_to_chars (buf, val, 8);
299059024Sobrien    }
299177298Sobrien  else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
299260484Sobrien           || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
299360484Sobrien    {
299460484Sobrien      fixP->fx_done = 0;
299589857Sobrien      return;
299660484Sobrien    }
299759024Sobrien  else
299859024Sobrien    {
299959024Sobrien      /* It's a relocation against an instruction.  */
300059024Sobrien
300159024Sobrien      if (INSN_BIG_ENDIAN)
300259024Sobrien	insn = bfd_getb32 ((unsigned char *) buf);
300359024Sobrien      else
300459024Sobrien	insn = bfd_getl32 ((unsigned char *) buf);
300577298Sobrien
300659024Sobrien      switch (fixP->fx_r_type)
300759024Sobrien	{
300859024Sobrien	case BFD_RELOC_32_PCREL_S2:
300959024Sobrien	  val = val >> 2;
301059024Sobrien	  /* FIXME: This increment-by-one deserves a comment of why it's
301159024Sobrien	     being done!  */
301259024Sobrien	  if (! sparc_pic_code
301359024Sobrien	      || fixP->fx_addsy == NULL
301460484Sobrien	      || symbol_section_p (fixP->fx_addsy))
301559024Sobrien	    ++val;
301677298Sobrien
301759024Sobrien	  insn |= val & 0x3fffffff;
301877298Sobrien
301977298Sobrien	  /* See if we have a delay slot.  */
302077298Sobrien	  if (sparc_relax && fixP->fx_where + 8 <= fixP->fx_frag->fr_fix)
302177298Sobrien	    {
302277298Sobrien#define G0		0
302377298Sobrien#define O7		15
302477298Sobrien#define XCC		(2 << 20)
302577298Sobrien#define COND(x)		(((x)&0xf)<<25)
302677298Sobrien#define CONDA		COND(0x8)
302777298Sobrien#define INSN_BPA	(F2(0,1) | CONDA | BPRED | XCC)
302877298Sobrien#define INSN_BA		(F2(0,2) | CONDA)
302977298Sobrien#define INSN_OR		F3(2, 0x2, 0)
303077298Sobrien#define INSN_NOP	F2(0,4)
303177298Sobrien
303277298Sobrien	      long delay;
303377298Sobrien
303477298Sobrien	      /* If the instruction is a call with either:
303577298Sobrien		 restore
303677298Sobrien		 arithmetic instruction with rd == %o7
303777298Sobrien		 where rs1 != %o7 and rs2 if it is register != %o7
303877298Sobrien		 then we can optimize if the call destination is near
303977298Sobrien		 by changing the call into a branch always.  */
304077298Sobrien	      if (INSN_BIG_ENDIAN)
304177298Sobrien		delay = bfd_getb32 ((unsigned char *) buf + 4);
304277298Sobrien	      else
304377298Sobrien		delay = bfd_getl32 ((unsigned char *) buf + 4);
304477298Sobrien	      if ((insn & OP (~0)) != OP (1) || (delay & OP (~0)) != OP (2))
304577298Sobrien		break;
304677298Sobrien	      if ((delay & OP3 (~0)) != OP3 (0x3d) /* Restore.  */
304777298Sobrien		  && ((delay & OP3 (0x28)) != 0 /* Arithmetic.  */
304877298Sobrien		      || ((delay & RD (~0)) != RD (O7))))
304977298Sobrien		break;
305077298Sobrien	      if ((delay & RS1 (~0)) == RS1 (O7)
305177298Sobrien		  || ((delay & F3I (~0)) == 0
305277298Sobrien		      && (delay & RS2 (~0)) == RS2 (O7)))
305377298Sobrien		break;
305477298Sobrien	      /* Ensure the branch will fit into simm22.  */
305577298Sobrien	      if ((val & 0x3fe00000)
305677298Sobrien		  && (val & 0x3fe00000) != 0x3fe00000)
305777298Sobrien		break;
305877298Sobrien	      /* Check if the arch is v9 and branch will fit
305977298Sobrien		 into simm19.  */
306077298Sobrien	      if (((val & 0x3c0000) == 0
306177298Sobrien		   || (val & 0x3c0000) == 0x3c0000)
306277298Sobrien		  && (sparc_arch_size == 64
306377298Sobrien		      || current_architecture >= SPARC_OPCODE_ARCH_V9))
306477298Sobrien		/* ba,pt %xcc  */
306577298Sobrien		insn = INSN_BPA | (val & 0x7ffff);
306677298Sobrien	      else
306777298Sobrien		/* ba  */
306877298Sobrien		insn = INSN_BA | (val & 0x3fffff);
306977298Sobrien	      if (fixP->fx_where >= 4
307077298Sobrien		  && ((delay & (0xffffffff ^ RS1 (~0)))
307177298Sobrien		      == (INSN_OR | RD (O7) | RS2 (G0))))
307277298Sobrien		{
307377298Sobrien		  long setter;
307477298Sobrien		  int reg;
307577298Sobrien
307677298Sobrien		  if (INSN_BIG_ENDIAN)
307777298Sobrien		    setter = bfd_getb32 ((unsigned char *) buf - 4);
307877298Sobrien		  else
307977298Sobrien		    setter = bfd_getl32 ((unsigned char *) buf - 4);
308077298Sobrien		  if ((setter & (0xffffffff ^ RD (~0)))
308177298Sobrien		      != (INSN_OR | RS1 (O7) | RS2 (G0)))
308277298Sobrien		    break;
308377298Sobrien		  /* The sequence was
308477298Sobrien		     or %o7, %g0, %rN
308577298Sobrien		     call foo
308677298Sobrien		     or %rN, %g0, %o7
308777298Sobrien
308877298Sobrien		     If call foo was replaced with ba, replace
308977298Sobrien		     or %rN, %g0, %o7 with nop.  */
309077298Sobrien		  reg = (delay & RS1 (~0)) >> 14;
309177298Sobrien		  if (reg != ((setter & RD (~0)) >> 25)
309277298Sobrien		      || reg == G0 || reg == O7)
309377298Sobrien		    break;
309477298Sobrien
309577298Sobrien		  if (INSN_BIG_ENDIAN)
309677298Sobrien		    bfd_putb32 (INSN_NOP, (unsigned char *) buf + 4);
309777298Sobrien		  else
309877298Sobrien		    bfd_putl32 (INSN_NOP, (unsigned char *) buf + 4);
309977298Sobrien		}
310077298Sobrien	    }
310159024Sobrien	  break;
310259024Sobrien
310359024Sobrien	case BFD_RELOC_SPARC_11:
310459024Sobrien	  if (! in_signed_range (val, 0x7ff))
310560484Sobrien	    as_bad_where (fixP->fx_file, fixP->fx_line,
310660484Sobrien			  _("relocation overflow"));
310759024Sobrien	  insn |= val & 0x7ff;
310859024Sobrien	  break;
310959024Sobrien
311059024Sobrien	case BFD_RELOC_SPARC_10:
311159024Sobrien	  if (! in_signed_range (val, 0x3ff))
311260484Sobrien	    as_bad_where (fixP->fx_file, fixP->fx_line,
311360484Sobrien			  _("relocation overflow"));
311459024Sobrien	  insn |= val & 0x3ff;
311559024Sobrien	  break;
311659024Sobrien
311759024Sobrien	case BFD_RELOC_SPARC_7:
311859024Sobrien	  if (! in_bitfield_range (val, 0x7f))
311960484Sobrien	    as_bad_where (fixP->fx_file, fixP->fx_line,
312060484Sobrien			  _("relocation overflow"));
312159024Sobrien	  insn |= val & 0x7f;
312259024Sobrien	  break;
312359024Sobrien
312459024Sobrien	case BFD_RELOC_SPARC_6:
312559024Sobrien	  if (! in_bitfield_range (val, 0x3f))
312660484Sobrien	    as_bad_where (fixP->fx_file, fixP->fx_line,
312760484Sobrien			  _("relocation overflow"));
312859024Sobrien	  insn |= val & 0x3f;
312959024Sobrien	  break;
313059024Sobrien
313159024Sobrien	case BFD_RELOC_SPARC_5:
313259024Sobrien	  if (! in_bitfield_range (val, 0x1f))
313360484Sobrien	    as_bad_where (fixP->fx_file, fixP->fx_line,
313460484Sobrien			  _("relocation overflow"));
313559024Sobrien	  insn |= val & 0x1f;
313659024Sobrien	  break;
313759024Sobrien
313859024Sobrien	case BFD_RELOC_SPARC_WDISP16:
313977298Sobrien	  /* FIXME: simplify.  */
314059024Sobrien	  if (((val > 0) && (val & ~0x3fffc))
314159024Sobrien	      || ((val < 0) && (~(val - 1) & ~0x3fffc)))
314260484Sobrien	    as_bad_where (fixP->fx_file, fixP->fx_line,
314360484Sobrien			  _("relocation overflow"));
314459024Sobrien	  /* FIXME: The +1 deserves a comment.  */
314559024Sobrien	  val = (val >> 2) + 1;
314659024Sobrien	  insn |= ((val & 0xc000) << 6) | (val & 0x3fff);
314759024Sobrien	  break;
314859024Sobrien
314959024Sobrien	case BFD_RELOC_SPARC_WDISP19:
315077298Sobrien	  /* FIXME: simplify.  */
315159024Sobrien	  if (((val > 0) && (val & ~0x1ffffc))
315259024Sobrien	      || ((val < 0) && (~(val - 1) & ~0x1ffffc)))
315360484Sobrien	    as_bad_where (fixP->fx_file, fixP->fx_line,
315460484Sobrien			  _("relocation overflow"));
315559024Sobrien	  /* FIXME: The +1 deserves a comment.  */
315659024Sobrien	  val = (val >> 2) + 1;
315759024Sobrien	  insn |= val & 0x7ffff;
315859024Sobrien	  break;
315959024Sobrien
316059024Sobrien	case BFD_RELOC_SPARC_HH22:
316159024Sobrien	  val = BSR (val, 32);
316277298Sobrien	  /* Fall through.  */
316359024Sobrien
316459024Sobrien	case BFD_RELOC_SPARC_LM22:
316559024Sobrien	case BFD_RELOC_HI22:
316659024Sobrien	  if (!fixP->fx_addsy)
316789857Sobrien	    insn |= (val >> 10) & 0x3fffff;
316859024Sobrien	  else
316989857Sobrien	    /* FIXME: Need comment explaining why we do this.  */
317089857Sobrien	    insn &= ~0xffff;
317159024Sobrien	  break;
317259024Sobrien
317359024Sobrien	case BFD_RELOC_SPARC22:
317459024Sobrien	  if (val & ~0x003fffff)
317560484Sobrien	    as_bad_where (fixP->fx_file, fixP->fx_line,
317660484Sobrien			  _("relocation overflow"));
317759024Sobrien	  insn |= (val & 0x3fffff);
317859024Sobrien	  break;
317959024Sobrien
318059024Sobrien	case BFD_RELOC_SPARC_HM10:
318159024Sobrien	  val = BSR (val, 32);
318277298Sobrien	  /* Fall through.  */
318359024Sobrien
318459024Sobrien	case BFD_RELOC_LO10:
318559024Sobrien	  if (!fixP->fx_addsy)
318689857Sobrien	    insn |= val & 0x3ff;
318759024Sobrien	  else
318889857Sobrien	    /* FIXME: Need comment explaining why we do this.  */
318989857Sobrien	    insn &= ~0xff;
319059024Sobrien	  break;
319159024Sobrien
319260484Sobrien	case BFD_RELOC_SPARC_OLO10:
319360484Sobrien	  val &= 0x3ff;
319460484Sobrien	  val += fixP->tc_fix_data;
319577298Sobrien	  /* Fall through.  */
319660484Sobrien
319759024Sobrien	case BFD_RELOC_SPARC13:
319859024Sobrien	  if (! in_signed_range (val, 0x1fff))
319960484Sobrien	    as_bad_where (fixP->fx_file, fixP->fx_line,
320060484Sobrien			  _("relocation overflow"));
320159024Sobrien	  insn |= val & 0x1fff;
320259024Sobrien	  break;
320359024Sobrien
320459024Sobrien	case BFD_RELOC_SPARC_WDISP22:
320559024Sobrien	  val = (val >> 2) + 1;
320677298Sobrien	  /* Fall through.  */
320759024Sobrien	case BFD_RELOC_SPARC_BASE22:
320859024Sobrien	  insn |= val & 0x3fffff;
320959024Sobrien	  break;
321059024Sobrien
321159024Sobrien	case BFD_RELOC_SPARC_H44:
321259024Sobrien	  if (!fixP->fx_addsy)
321359024Sobrien	    {
321459024Sobrien	      bfd_vma tval = val;
321559024Sobrien	      tval >>= 22;
321659024Sobrien	      insn |= tval & 0x3fffff;
321759024Sobrien	    }
321859024Sobrien	  break;
321959024Sobrien
322059024Sobrien	case BFD_RELOC_SPARC_M44:
322159024Sobrien	  if (!fixP->fx_addsy)
322259024Sobrien	    insn |= (val >> 12) & 0x3ff;
322359024Sobrien	  break;
322459024Sobrien
322559024Sobrien	case BFD_RELOC_SPARC_L44:
322659024Sobrien	  if (!fixP->fx_addsy)
322759024Sobrien	    insn |= val & 0xfff;
322859024Sobrien	  break;
322959024Sobrien
323059024Sobrien	case BFD_RELOC_SPARC_HIX22:
323159024Sobrien	  if (!fixP->fx_addsy)
323259024Sobrien	    {
323377298Sobrien	      val ^= ~(offsetT) 0;
323459024Sobrien	      insn |= (val >> 10) & 0x3fffff;
323559024Sobrien	    }
323659024Sobrien	  break;
323759024Sobrien
323859024Sobrien	case BFD_RELOC_SPARC_LOX10:
323959024Sobrien	  if (!fixP->fx_addsy)
324059024Sobrien	    insn |= 0x1c00 | (val & 0x3ff);
324159024Sobrien	  break;
324259024Sobrien
324359024Sobrien	case BFD_RELOC_NONE:
324459024Sobrien	default:
324559024Sobrien	  as_bad_where (fixP->fx_file, fixP->fx_line,
324660484Sobrien			_("bad or unhandled relocation type: 0x%02x"),
324759024Sobrien			fixP->fx_r_type);
324859024Sobrien	  break;
324959024Sobrien	}
325059024Sobrien
325159024Sobrien      if (INSN_BIG_ENDIAN)
325259024Sobrien	bfd_putb32 (insn, (unsigned char *) buf);
325359024Sobrien      else
325459024Sobrien	bfd_putl32 (insn, (unsigned char *) buf);
325559024Sobrien    }
325659024Sobrien
325759024Sobrien  /* Are we finished with this relocation now?  */
325859024Sobrien  if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
325959024Sobrien    fixP->fx_done = 1;
326059024Sobrien}
326159024Sobrien
326259024Sobrien/* Translate internal representation of relocation info to BFD target
326359024Sobrien   format.  */
326477298Sobrien
326560484Sobrienarelent **
326659024Sobrientc_gen_reloc (section, fixp)
326759024Sobrien     asection *section;
326859024Sobrien     fixS *fixp;
326959024Sobrien{
327060484Sobrien  static arelent *relocs[3];
327159024Sobrien  arelent *reloc;
327259024Sobrien  bfd_reloc_code_real_type code;
327359024Sobrien
327460484Sobrien  relocs[0] = reloc = (arelent *) xmalloc (sizeof (arelent));
327560484Sobrien  relocs[1] = NULL;
327659024Sobrien
327760484Sobrien  reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
327860484Sobrien  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
327959024Sobrien  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
328059024Sobrien
328159024Sobrien  switch (fixp->fx_r_type)
328259024Sobrien    {
328359024Sobrien    case BFD_RELOC_16:
328459024Sobrien    case BFD_RELOC_32:
328559024Sobrien    case BFD_RELOC_HI22:
328659024Sobrien    case BFD_RELOC_LO10:
328759024Sobrien    case BFD_RELOC_32_PCREL_S2:
328859024Sobrien    case BFD_RELOC_SPARC13:
328960484Sobrien    case BFD_RELOC_SPARC22:
329059024Sobrien    case BFD_RELOC_SPARC_BASE13:
329159024Sobrien    case BFD_RELOC_SPARC_WDISP16:
329259024Sobrien    case BFD_RELOC_SPARC_WDISP19:
329359024Sobrien    case BFD_RELOC_SPARC_WDISP22:
329459024Sobrien    case BFD_RELOC_64:
329559024Sobrien    case BFD_RELOC_SPARC_5:
329659024Sobrien    case BFD_RELOC_SPARC_6:
329759024Sobrien    case BFD_RELOC_SPARC_7:
329859024Sobrien    case BFD_RELOC_SPARC_10:
329959024Sobrien    case BFD_RELOC_SPARC_11:
330059024Sobrien    case BFD_RELOC_SPARC_HH22:
330159024Sobrien    case BFD_RELOC_SPARC_HM10:
330259024Sobrien    case BFD_RELOC_SPARC_LM22:
330359024Sobrien    case BFD_RELOC_SPARC_PC_HH22:
330459024Sobrien    case BFD_RELOC_SPARC_PC_HM10:
330559024Sobrien    case BFD_RELOC_SPARC_PC_LM22:
330659024Sobrien    case BFD_RELOC_SPARC_H44:
330759024Sobrien    case BFD_RELOC_SPARC_M44:
330859024Sobrien    case BFD_RELOC_SPARC_L44:
330959024Sobrien    case BFD_RELOC_SPARC_HIX22:
331059024Sobrien    case BFD_RELOC_SPARC_LOX10:
331160484Sobrien    case BFD_RELOC_SPARC_REV32:
331260484Sobrien    case BFD_RELOC_SPARC_OLO10:
331378828Sobrien    case BFD_RELOC_SPARC_UA16:
331478828Sobrien    case BFD_RELOC_SPARC_UA32:
331578828Sobrien    case BFD_RELOC_SPARC_UA64:
331689857Sobrien    case BFD_RELOC_8_PCREL:
331789857Sobrien    case BFD_RELOC_16_PCREL:
331889857Sobrien    case BFD_RELOC_32_PCREL:
331989857Sobrien    case BFD_RELOC_64_PCREL:
332089857Sobrien    case BFD_RELOC_SPARC_PLT32:
332189857Sobrien    case BFD_RELOC_SPARC_PLT64:
332260484Sobrien    case BFD_RELOC_VTABLE_ENTRY:
332360484Sobrien    case BFD_RELOC_VTABLE_INHERIT:
332459024Sobrien      code = fixp->fx_r_type;
332559024Sobrien      break;
332659024Sobrien    default:
332759024Sobrien      abort ();
332859024Sobrien      return NULL;
332959024Sobrien    }
333059024Sobrien
333159024Sobrien#if defined (OBJ_ELF) || defined (OBJ_AOUT)
333259024Sobrien  /* If we are generating PIC code, we need to generate a different
333359024Sobrien     set of relocs.  */
333459024Sobrien
333559024Sobrien#ifdef OBJ_ELF
333659024Sobrien#define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
333759024Sobrien#else
333859024Sobrien#define GOT_NAME "__GLOBAL_OFFSET_TABLE_"
333959024Sobrien#endif
334059024Sobrien
334160484Sobrien  /* This code must be parallel to the OBJ_ELF tc_fix_adjustable.  */
334260484Sobrien
334359024Sobrien  if (sparc_pic_code)
334459024Sobrien    {
334559024Sobrien      switch (code)
334659024Sobrien	{
334759024Sobrien	case BFD_RELOC_32_PCREL_S2:
334859024Sobrien	  if (! S_IS_DEFINED (fixp->fx_addsy)
334959024Sobrien	      || S_IS_COMMON (fixp->fx_addsy)
335059024Sobrien	      || S_IS_EXTERNAL (fixp->fx_addsy)
335159024Sobrien	      || S_IS_WEAK (fixp->fx_addsy))
335259024Sobrien	    code = BFD_RELOC_SPARC_WPLT30;
335359024Sobrien	  break;
335459024Sobrien	case BFD_RELOC_HI22:
335559024Sobrien	  if (fixp->fx_addsy != NULL
335659024Sobrien	      && strcmp (S_GET_NAME (fixp->fx_addsy), GOT_NAME) == 0)
335759024Sobrien	    code = BFD_RELOC_SPARC_PC22;
335859024Sobrien	  else
335959024Sobrien	    code = BFD_RELOC_SPARC_GOT22;
336059024Sobrien	  break;
336159024Sobrien	case BFD_RELOC_LO10:
336259024Sobrien	  if (fixp->fx_addsy != NULL
336359024Sobrien	      && strcmp (S_GET_NAME (fixp->fx_addsy), GOT_NAME) == 0)
336459024Sobrien	    code = BFD_RELOC_SPARC_PC10;
336559024Sobrien	  else
336659024Sobrien	    code = BFD_RELOC_SPARC_GOT10;
336759024Sobrien	  break;
336859024Sobrien	case BFD_RELOC_SPARC13:
336959024Sobrien	  code = BFD_RELOC_SPARC_GOT13;
337059024Sobrien	  break;
337159024Sobrien	default:
337259024Sobrien	  break;
337359024Sobrien	}
337459024Sobrien    }
337577298Sobrien#endif /* defined (OBJ_ELF) || defined (OBJ_AOUT)  */
337659024Sobrien
337760484Sobrien  if (code == BFD_RELOC_SPARC_OLO10)
337860484Sobrien    reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO10);
337960484Sobrien  else
338060484Sobrien    reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
338159024Sobrien  if (reloc->howto == 0)
338259024Sobrien    {
338359024Sobrien      as_bad_where (fixp->fx_file, fixp->fx_line,
338460484Sobrien		    _("internal error: can't export reloc type %d (`%s')"),
338559024Sobrien		    fixp->fx_r_type, bfd_get_reloc_code_name (code));
338660484Sobrien      xfree (reloc);
338760484Sobrien      relocs[0] = NULL;
338860484Sobrien      return relocs;
338959024Sobrien    }
339059024Sobrien
339159024Sobrien  /* @@ Why fx_addnumber sometimes and fx_offset other times?  */
339259024Sobrien#ifdef OBJ_AOUT
339359024Sobrien
339459024Sobrien  if (reloc->howto->pc_relative == 0
339559024Sobrien      || code == BFD_RELOC_SPARC_PC10
339659024Sobrien      || code == BFD_RELOC_SPARC_PC22)
339759024Sobrien    reloc->addend = fixp->fx_addnumber;
339860484Sobrien  else if (sparc_pic_code
339960484Sobrien	   && fixp->fx_r_type == BFD_RELOC_32_PCREL_S2
340060484Sobrien	   && fixp->fx_addsy != NULL
340160484Sobrien	   && (S_IS_EXTERNAL (fixp->fx_addsy)
340260484Sobrien	       || S_IS_WEAK (fixp->fx_addsy))
340360484Sobrien	   && S_IS_DEFINED (fixp->fx_addsy)
340460484Sobrien	   && ! S_IS_COMMON (fixp->fx_addsy))
340560484Sobrien    reloc->addend = fixp->fx_addnumber;
340659024Sobrien  else
340759024Sobrien    reloc->addend = fixp->fx_offset - reloc->address;
340859024Sobrien
340977298Sobrien#else /* elf or coff  */
341059024Sobrien
341189857Sobrien  if (code != BFD_RELOC_32_PCREL_S2
341289857Sobrien      && code != BFD_RELOC_SPARC_WDISP22
341389857Sobrien      && code != BFD_RELOC_SPARC_WDISP16
341489857Sobrien      && code != BFD_RELOC_SPARC_WDISP19
341589857Sobrien      && code != BFD_RELOC_SPARC_WPLT30)
341659024Sobrien    reloc->addend = fixp->fx_addnumber;
341760484Sobrien  else if (symbol_section_p (fixp->fx_addsy))
341859024Sobrien    reloc->addend = (section->vma
341959024Sobrien		     + fixp->fx_addnumber
342059024Sobrien		     + md_pcrel_from (fixp));
342159024Sobrien  else
342259024Sobrien    reloc->addend = fixp->fx_offset;
342359024Sobrien#endif
342459024Sobrien
342560484Sobrien  /* We expand R_SPARC_OLO10 to R_SPARC_LO10 and R_SPARC_13
342660484Sobrien     on the same location.  */
342760484Sobrien  if (code == BFD_RELOC_SPARC_OLO10)
342860484Sobrien    {
342960484Sobrien      relocs[1] = reloc = (arelent *) xmalloc (sizeof (arelent));
343060484Sobrien      relocs[2] = NULL;
343160484Sobrien
343260484Sobrien      reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
343377298Sobrien      *reloc->sym_ptr_ptr
343477298Sobrien	= symbol_get_bfdsym (section_symbol (absolute_section));
343560484Sobrien      reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
343660484Sobrien      reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_SPARC13);
343760484Sobrien      reloc->addend = fixp->tc_fix_data;
343860484Sobrien    }
343960484Sobrien
344060484Sobrien  return relocs;
344159024Sobrien}
344259024Sobrien
344377298Sobrien/* We have no need to default values of symbols.  */
344459024Sobrien
344559024SobriensymbolS *
344659024Sobrienmd_undefined_symbol (name)
344777298Sobrien     char *name ATTRIBUTE_UNUSED;
344859024Sobrien{
344959024Sobrien  return 0;
345077298Sobrien}
345159024Sobrien
345277298Sobrien/* Round up a section size to the appropriate boundary.  */
345377298Sobrien
345459024SobrienvalueT
345559024Sobrienmd_section_align (segment, size)
345677298Sobrien     segT segment ATTRIBUTE_UNUSED;
345759024Sobrien     valueT size;
345859024Sobrien{
345959024Sobrien#ifndef OBJ_ELF
346059024Sobrien  /* This is not right for ELF; a.out wants it, and COFF will force
346159024Sobrien     the alignment anyways.  */
346259024Sobrien  valueT align = ((valueT) 1
346359024Sobrien		  << (valueT) bfd_get_section_alignment (stdoutput, segment));
346459024Sobrien  valueT newsize;
346577298Sobrien
346677298Sobrien  /* Turn alignment value into a mask.  */
346759024Sobrien  align--;
346859024Sobrien  newsize = (size + align) & ~align;
346959024Sobrien  return newsize;
347059024Sobrien#else
347159024Sobrien  return size;
347259024Sobrien#endif
347359024Sobrien}
347459024Sobrien
347559024Sobrien/* Exactly what point is a PC-relative offset relative TO?
347659024Sobrien   On the sparc, they're relative to the address of the offset, plus
347759024Sobrien   its size.  This gets us to the following instruction.
347877298Sobrien   (??? Is this right?  FIXME-SOON)  */
347977298Sobrienlong
348059024Sobrienmd_pcrel_from (fixP)
348159024Sobrien     fixS *fixP;
348259024Sobrien{
348359024Sobrien  long ret;
348459024Sobrien
348559024Sobrien  ret = fixP->fx_where + fixP->fx_frag->fr_address;
348659024Sobrien  if (! sparc_pic_code
348759024Sobrien      || fixP->fx_addsy == NULL
348860484Sobrien      || symbol_section_p (fixP->fx_addsy))
348959024Sobrien    ret += fixP->fx_size;
349059024Sobrien  return ret;
349159024Sobrien}
349259024Sobrien
349360484Sobrien/* Return log2 (VALUE), or -1 if VALUE is not an exact positive power
349460484Sobrien   of two.  */
349560484Sobrien
349660484Sobrienstatic int
349760484Sobrienlog2 (value)
349860484Sobrien     int value;
349960484Sobrien{
350060484Sobrien  int shift;
350160484Sobrien
350260484Sobrien  if (value <= 0)
350360484Sobrien    return -1;
350460484Sobrien
350560484Sobrien  for (shift = 0; (value & 1) == 0; value >>= 1)
350660484Sobrien    ++shift;
350760484Sobrien
350860484Sobrien  return (value == 1) ? shift : -1;
350960484Sobrien}
351060484Sobrien
351177298Sobrien/* Sort of like s_lcomm.  */
351259024Sobrien
351359024Sobrien#ifndef OBJ_ELF
351459024Sobrienstatic int max_alignment = 15;
351559024Sobrien#endif
351659024Sobrien
351759024Sobrienstatic void
351859024Sobriens_reserve (ignore)
351977298Sobrien     int ignore ATTRIBUTE_UNUSED;
352059024Sobrien{
352159024Sobrien  char *name;
352259024Sobrien  char *p;
352359024Sobrien  char c;
352459024Sobrien  int align;
352559024Sobrien  int size;
352659024Sobrien  int temp;
352759024Sobrien  symbolS *symbolP;
352859024Sobrien
352959024Sobrien  name = input_line_pointer;
353059024Sobrien  c = get_symbol_end ();
353159024Sobrien  p = input_line_pointer;
353259024Sobrien  *p = c;
353359024Sobrien  SKIP_WHITESPACE ();
353459024Sobrien
353559024Sobrien  if (*input_line_pointer != ',')
353659024Sobrien    {
353760484Sobrien      as_bad (_("Expected comma after name"));
353859024Sobrien      ignore_rest_of_line ();
353959024Sobrien      return;
354059024Sobrien    }
354159024Sobrien
354259024Sobrien  ++input_line_pointer;
354359024Sobrien
354459024Sobrien  if ((size = get_absolute_expression ()) < 0)
354559024Sobrien    {
354660484Sobrien      as_bad (_("BSS length (%d.) <0! Ignored."), size);
354759024Sobrien      ignore_rest_of_line ();
354859024Sobrien      return;
354977298Sobrien    }				/* Bad length.  */
355059024Sobrien
355159024Sobrien  *p = 0;
355259024Sobrien  symbolP = symbol_find_or_make (name);
355359024Sobrien  *p = c;
355459024Sobrien
355559024Sobrien  if (strncmp (input_line_pointer, ",\"bss\"", 6) != 0
355659024Sobrien      && strncmp (input_line_pointer, ",\".bss\"", 7) != 0)
355759024Sobrien    {
355860484Sobrien      as_bad (_("bad .reserve segment -- expected BSS segment"));
355959024Sobrien      return;
356059024Sobrien    }
356159024Sobrien
356259024Sobrien  if (input_line_pointer[2] == '.')
356359024Sobrien    input_line_pointer += 7;
356459024Sobrien  else
356559024Sobrien    input_line_pointer += 6;
356659024Sobrien  SKIP_WHITESPACE ();
356759024Sobrien
356859024Sobrien  if (*input_line_pointer == ',')
356959024Sobrien    {
357059024Sobrien      ++input_line_pointer;
357159024Sobrien
357259024Sobrien      SKIP_WHITESPACE ();
357359024Sobrien      if (*input_line_pointer == '\n')
357459024Sobrien	{
357560484Sobrien	  as_bad (_("missing alignment"));
357660484Sobrien	  ignore_rest_of_line ();
357759024Sobrien	  return;
357859024Sobrien	}
357959024Sobrien
358060484Sobrien      align = (int) get_absolute_expression ();
358160484Sobrien
358259024Sobrien#ifndef OBJ_ELF
358359024Sobrien      if (align > max_alignment)
358459024Sobrien	{
358559024Sobrien	  align = max_alignment;
358660484Sobrien	  as_warn (_("alignment too large; assuming %d"), align);
358759024Sobrien	}
358859024Sobrien#endif
358960484Sobrien
359059024Sobrien      if (align < 0)
359159024Sobrien	{
359260484Sobrien	  as_bad (_("negative alignment"));
359360484Sobrien	  ignore_rest_of_line ();
359460484Sobrien	  return;
359559024Sobrien	}
359659024Sobrien
359760484Sobrien      if (align != 0)
359860484Sobrien	{
359960484Sobrien	  temp = log2 (align);
360060484Sobrien	  if (temp < 0)
360160484Sobrien	    {
360260484Sobrien	      as_bad (_("alignment not a power of 2"));
360360484Sobrien	      ignore_rest_of_line ();
360460484Sobrien	      return;
360560484Sobrien	    }
360659024Sobrien
360760484Sobrien	  align = temp;
360860484Sobrien	}
360959024Sobrien
361060484Sobrien      record_alignment (bss_section, align);
361160484Sobrien    }
361259024Sobrien  else
361359024Sobrien    align = 0;
361459024Sobrien
361559024Sobrien  if (!S_IS_DEFINED (symbolP)
361659024Sobrien#ifdef OBJ_AOUT
361759024Sobrien      && S_GET_OTHER (symbolP) == 0
361859024Sobrien      && S_GET_DESC (symbolP) == 0
361959024Sobrien#endif
362059024Sobrien      )
362159024Sobrien    {
362259024Sobrien      if (! need_pass_2)
362359024Sobrien	{
362459024Sobrien	  char *pfrag;
362559024Sobrien	  segT current_seg = now_seg;
362659024Sobrien	  subsegT current_subseg = now_subseg;
362759024Sobrien
362877298Sobrien	  /* Switch to bss.  */
362977298Sobrien	  subseg_set (bss_section, 1);
363059024Sobrien
363159024Sobrien	  if (align)
363277298Sobrien	    /* Do alignment.  */
363377298Sobrien	    frag_align (align, 0, 0);
363459024Sobrien
363577298Sobrien	  /* Detach from old frag.  */
363677298Sobrien	  if (S_GET_SEGMENT (symbolP) == bss_section)
363760484Sobrien	    symbol_get_frag (symbolP)->fr_symbol = NULL;
363859024Sobrien
363960484Sobrien	  symbol_set_frag (symbolP, frag_now);
364077298Sobrien	  pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
364177298Sobrien			    (offsetT) size, (char *) 0);
364259024Sobrien	  *pfrag = 0;
364359024Sobrien
364459024Sobrien	  S_SET_SEGMENT (symbolP, bss_section);
364559024Sobrien
364659024Sobrien	  subseg_set (current_seg, current_subseg);
364760484Sobrien
364860484Sobrien#ifdef OBJ_ELF
364960484Sobrien	  S_SET_SIZE (symbolP, size);
365060484Sobrien#endif
365159024Sobrien	}
365259024Sobrien    }
365359024Sobrien  else
365459024Sobrien    {
365577298Sobrien      as_warn ("Ignoring attempt to re-define symbol %s",
365677298Sobrien	       S_GET_NAME (symbolP));
365777298Sobrien    }				/* if not redefining.  */
365859024Sobrien
365959024Sobrien  demand_empty_rest_of_line ();
366059024Sobrien}
366159024Sobrien
366259024Sobrienstatic void
366359024Sobriens_common (ignore)
366477298Sobrien     int ignore ATTRIBUTE_UNUSED;
366559024Sobrien{
366659024Sobrien  char *name;
366759024Sobrien  char c;
366859024Sobrien  char *p;
366959024Sobrien  int temp, size;
367059024Sobrien  symbolS *symbolP;
367159024Sobrien
367259024Sobrien  name = input_line_pointer;
367359024Sobrien  c = get_symbol_end ();
367477298Sobrien  /* Just after name is now '\0'.  */
367559024Sobrien  p = input_line_pointer;
367659024Sobrien  *p = c;
367759024Sobrien  SKIP_WHITESPACE ();
367859024Sobrien  if (*input_line_pointer != ',')
367959024Sobrien    {
368060484Sobrien      as_bad (_("Expected comma after symbol-name"));
368159024Sobrien      ignore_rest_of_line ();
368259024Sobrien      return;
368359024Sobrien    }
368477298Sobrien
368577298Sobrien  /* Skip ','.  */
368677298Sobrien  input_line_pointer++;
368777298Sobrien
368859024Sobrien  if ((temp = get_absolute_expression ()) < 0)
368959024Sobrien    {
369060484Sobrien      as_bad (_(".COMMon length (%d.) <0! Ignored."), temp);
369159024Sobrien      ignore_rest_of_line ();
369259024Sobrien      return;
369359024Sobrien    }
369459024Sobrien  size = temp;
369559024Sobrien  *p = 0;
369659024Sobrien  symbolP = symbol_find_or_make (name);
369759024Sobrien  *p = c;
369859024Sobrien  if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
369959024Sobrien    {
370060484Sobrien      as_bad (_("Ignoring attempt to re-define symbol"));
370159024Sobrien      ignore_rest_of_line ();
370259024Sobrien      return;
370359024Sobrien    }
370459024Sobrien  if (S_GET_VALUE (symbolP) != 0)
370559024Sobrien    {
370659024Sobrien      if (S_GET_VALUE (symbolP) != (valueT) size)
370759024Sobrien	{
370860484Sobrien	  as_warn (_("Length of .comm \"%s\" is already %ld. Not changed to %d."),
370959024Sobrien		   S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size);
371059024Sobrien	}
371159024Sobrien    }
371259024Sobrien  else
371359024Sobrien    {
371459024Sobrien#ifndef OBJ_ELF
371559024Sobrien      S_SET_VALUE (symbolP, (valueT) size);
371659024Sobrien      S_SET_EXTERNAL (symbolP);
371759024Sobrien#endif
371859024Sobrien    }
371960484Sobrien  know (symbol_get_frag (symbolP) == &zero_address_frag);
372059024Sobrien  if (*input_line_pointer != ',')
372159024Sobrien    {
372260484Sobrien      as_bad (_("Expected comma after common length"));
372359024Sobrien      ignore_rest_of_line ();
372459024Sobrien      return;
372559024Sobrien    }
372659024Sobrien  input_line_pointer++;
372759024Sobrien  SKIP_WHITESPACE ();
372859024Sobrien  if (*input_line_pointer != '"')
372959024Sobrien    {
373059024Sobrien      temp = get_absolute_expression ();
373160484Sobrien
373259024Sobrien#ifndef OBJ_ELF
373359024Sobrien      if (temp > max_alignment)
373459024Sobrien	{
373559024Sobrien	  temp = max_alignment;
373660484Sobrien	  as_warn (_("alignment too large; assuming %d"), temp);
373759024Sobrien	}
373859024Sobrien#endif
373960484Sobrien
374059024Sobrien      if (temp < 0)
374159024Sobrien	{
374260484Sobrien	  as_bad (_("negative alignment"));
374360484Sobrien	  ignore_rest_of_line ();
374460484Sobrien	  return;
374559024Sobrien	}
374660484Sobrien
374759024Sobrien#ifdef OBJ_ELF
374860484Sobrien      if (symbol_get_obj (symbolP)->local)
374959024Sobrien	{
375059024Sobrien	  segT old_sec;
375159024Sobrien	  int old_subsec;
375259024Sobrien	  char *p;
375359024Sobrien	  int align;
375459024Sobrien
375559024Sobrien	  old_sec = now_seg;
375659024Sobrien	  old_subsec = now_subseg;
375760484Sobrien
375860484Sobrien	  if (temp == 0)
375960484Sobrien	    align = 0;
376060484Sobrien	  else
376160484Sobrien	    align = log2 (temp);
376260484Sobrien
376360484Sobrien	  if (align < 0)
376460484Sobrien	    {
376560484Sobrien	      as_bad (_("alignment not a power of 2"));
376660484Sobrien	      ignore_rest_of_line ();
376760484Sobrien	      return;
376860484Sobrien	    }
376960484Sobrien
377059024Sobrien	  record_alignment (bss_section, align);
377159024Sobrien	  subseg_set (bss_section, 0);
377259024Sobrien	  if (align)
377359024Sobrien	    frag_align (align, 0, 0);
377459024Sobrien	  if (S_GET_SEGMENT (symbolP) == bss_section)
377560484Sobrien	    symbol_get_frag (symbolP)->fr_symbol = 0;
377660484Sobrien	  symbol_set_frag (symbolP, frag_now);
377759024Sobrien	  p = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
377859024Sobrien			(offsetT) size, (char *) 0);
377959024Sobrien	  *p = 0;
378059024Sobrien	  S_SET_SEGMENT (symbolP, bss_section);
378159024Sobrien	  S_CLEAR_EXTERNAL (symbolP);
378260484Sobrien	  S_SET_SIZE (symbolP, size);
378359024Sobrien	  subseg_set (old_sec, old_subsec);
378459024Sobrien	}
378559024Sobrien      else
378677298Sobrien#endif /* OBJ_ELF  */
378759024Sobrien	{
378859024Sobrien	allocate_common:
378959024Sobrien	  S_SET_VALUE (symbolP, (valueT) size);
379059024Sobrien#ifdef OBJ_ELF
379159024Sobrien	  S_SET_ALIGN (symbolP, temp);
379260484Sobrien	  S_SET_SIZE (symbolP, size);
379359024Sobrien#endif
379459024Sobrien	  S_SET_EXTERNAL (symbolP);
379559024Sobrien	  S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
379659024Sobrien	}
379759024Sobrien    }
379859024Sobrien  else
379959024Sobrien    {
380059024Sobrien      input_line_pointer++;
380159024Sobrien      /* @@ Some use the dot, some don't.  Can we get some consistency??  */
380259024Sobrien      if (*input_line_pointer == '.')
380359024Sobrien	input_line_pointer++;
380459024Sobrien      /* @@ Some say data, some say bss.  */
380559024Sobrien      if (strncmp (input_line_pointer, "bss\"", 4)
380659024Sobrien	  && strncmp (input_line_pointer, "data\"", 5))
380759024Sobrien	{
380859024Sobrien	  while (*--input_line_pointer != '"')
380959024Sobrien	    ;
381059024Sobrien	  input_line_pointer--;
381159024Sobrien	  goto bad_common_segment;
381259024Sobrien	}
381359024Sobrien      while (*input_line_pointer++ != '"')
381459024Sobrien	;
381559024Sobrien      goto allocate_common;
381659024Sobrien    }
381759024Sobrien
381859024Sobrien#ifdef BFD_ASSEMBLER
381960484Sobrien  symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
382059024Sobrien#endif
382159024Sobrien
382259024Sobrien  demand_empty_rest_of_line ();
382359024Sobrien  return;
382459024Sobrien
382559024Sobrien  {
382659024Sobrien  bad_common_segment:
382759024Sobrien    p = input_line_pointer;
382859024Sobrien    while (*p && *p != '\n')
382959024Sobrien      p++;
383059024Sobrien    c = *p;
383159024Sobrien    *p = '\0';
383260484Sobrien    as_bad (_("bad .common segment %s"), input_line_pointer + 1);
383359024Sobrien    *p = c;
383459024Sobrien    input_line_pointer = p;
383559024Sobrien    ignore_rest_of_line ();
383659024Sobrien    return;
383759024Sobrien  }
383859024Sobrien}
383959024Sobrien
384059024Sobrien/* Handle the .empty pseudo-op.  This supresses the warnings about
384159024Sobrien   invalid delay slot usage.  */
384259024Sobrien
384359024Sobrienstatic void
384459024Sobriens_empty (ignore)
384577298Sobrien     int ignore ATTRIBUTE_UNUSED;
384659024Sobrien{
384759024Sobrien  /* The easy way to implement is to just forget about the last
384859024Sobrien     instruction.  */
384959024Sobrien  last_insn = NULL;
385059024Sobrien}
385159024Sobrien
385259024Sobrienstatic void
385359024Sobriens_seg (ignore)
385477298Sobrien     int ignore ATTRIBUTE_UNUSED;
385559024Sobrien{
385659024Sobrien
385759024Sobrien  if (strncmp (input_line_pointer, "\"text\"", 6) == 0)
385859024Sobrien    {
385959024Sobrien      input_line_pointer += 6;
386059024Sobrien      s_text (0);
386159024Sobrien      return;
386259024Sobrien    }
386359024Sobrien  if (strncmp (input_line_pointer, "\"data\"", 6) == 0)
386459024Sobrien    {
386559024Sobrien      input_line_pointer += 6;
386659024Sobrien      s_data (0);
386759024Sobrien      return;
386859024Sobrien    }
386959024Sobrien  if (strncmp (input_line_pointer, "\"data1\"", 7) == 0)
387059024Sobrien    {
387159024Sobrien      input_line_pointer += 7;
387259024Sobrien      s_data1 ();
387359024Sobrien      return;
387459024Sobrien    }
387559024Sobrien  if (strncmp (input_line_pointer, "\"bss\"", 5) == 0)
387659024Sobrien    {
387759024Sobrien      input_line_pointer += 5;
387859024Sobrien      /* We only support 2 segments -- text and data -- for now, so
387959024Sobrien	 things in the "bss segment" will have to go into data for now.
388077298Sobrien	 You can still allocate SEG_BSS stuff with .lcomm or .reserve.  */
388177298Sobrien      subseg_set (data_section, 255);	/* FIXME-SOMEDAY.  */
388259024Sobrien      return;
388359024Sobrien    }
388460484Sobrien  as_bad (_("Unknown segment type"));
388559024Sobrien  demand_empty_rest_of_line ();
388659024Sobrien}
388759024Sobrien
388859024Sobrienstatic void
388959024Sobriens_data1 ()
389059024Sobrien{
389159024Sobrien  subseg_set (data_section, 1);
389259024Sobrien  demand_empty_rest_of_line ();
389359024Sobrien}
389459024Sobrien
389559024Sobrienstatic void
389659024Sobriens_proc (ignore)
389777298Sobrien     int ignore ATTRIBUTE_UNUSED;
389859024Sobrien{
389959024Sobrien  while (!is_end_of_line[(unsigned char) *input_line_pointer])
390059024Sobrien    {
390159024Sobrien      ++input_line_pointer;
390259024Sobrien    }
390359024Sobrien  ++input_line_pointer;
390459024Sobrien}
390559024Sobrien
390659024Sobrien/* This static variable is set by s_uacons to tell sparc_cons_align
390759024Sobrien   that the expession does not need to be aligned.  */
390859024Sobrien
390959024Sobrienstatic int sparc_no_align_cons = 0;
391059024Sobrien
391189857Sobrien/* This static variable is set by sparc_cons to emit requested types
391289857Sobrien   of relocations in cons_fix_new_sparc.  */
391389857Sobrien
391489857Sobrienstatic const char *sparc_cons_special_reloc;
391589857Sobrien
391659024Sobrien/* This handles the unaligned space allocation pseudo-ops, such as
391759024Sobrien   .uaword.  .uaword is just like .word, but the value does not need
391859024Sobrien   to be aligned.  */
391959024Sobrien
392059024Sobrienstatic void
392159024Sobriens_uacons (bytes)
392259024Sobrien     int bytes;
392359024Sobrien{
392459024Sobrien  /* Tell sparc_cons_align not to align this value.  */
392559024Sobrien  sparc_no_align_cons = 1;
392659024Sobrien  cons (bytes);
392789857Sobrien  sparc_no_align_cons = 0;
392859024Sobrien}
392959024Sobrien
393060484Sobrien/* This handles the native word allocation pseudo-op .nword.
393160484Sobrien   For sparc_arch_size 32 it is equivalent to .word,  for
393260484Sobrien   sparc_arch_size 64 it is equivalent to .xword.  */
393360484Sobrien
393460484Sobrienstatic void
393560484Sobriens_ncons (bytes)
393677298Sobrien     int bytes ATTRIBUTE_UNUSED;
393760484Sobrien{
393860484Sobrien  cons (sparc_arch_size == 32 ? 4 : 8);
393960484Sobrien}
394060484Sobrien
394160484Sobrien#ifdef OBJ_ELF
394260484Sobrien/* Handle the SPARC ELF .register pseudo-op.  This sets the binding of a
394360484Sobrien   global register.
394460484Sobrien   The syntax is:
394577298Sobrien
394660484Sobrien   .register %g[2367],{#scratch|symbolname|#ignore}
394777298Sobrien*/
394860484Sobrien
394960484Sobrienstatic void
395060484Sobriens_register (ignore)
395177298Sobrien     int ignore ATTRIBUTE_UNUSED;
395260484Sobrien{
395360484Sobrien  char c;
395460484Sobrien  int reg;
395560484Sobrien  int flags;
395660484Sobrien  const char *regname;
395760484Sobrien
395860484Sobrien  if (input_line_pointer[0] != '%'
395960484Sobrien      || input_line_pointer[1] != 'g'
396060484Sobrien      || ((input_line_pointer[2] & ~1) != '2'
396160484Sobrien	  && (input_line_pointer[2] & ~1) != '6')
396260484Sobrien      || input_line_pointer[3] != ',')
396360484Sobrien    as_bad (_("register syntax is .register %%g[2367],{#scratch|symbolname|#ignore}"));
396460484Sobrien  reg = input_line_pointer[2] - '0';
396560484Sobrien  input_line_pointer += 4;
396660484Sobrien
396760484Sobrien  if (*input_line_pointer == '#')
396860484Sobrien    {
396960484Sobrien      ++input_line_pointer;
397060484Sobrien      regname = input_line_pointer;
397160484Sobrien      c = get_symbol_end ();
397260484Sobrien      if (strcmp (regname, "scratch") && strcmp (regname, "ignore"))
397360484Sobrien	as_bad (_("register syntax is .register %%g[2367],{#scratch|symbolname|#ignore}"));
397477298Sobrien      if (regname[0] == 'i')
397560484Sobrien	regname = NULL;
397660484Sobrien      else
397760484Sobrien	regname = "";
397860484Sobrien    }
397960484Sobrien  else
398060484Sobrien    {
398160484Sobrien      regname = input_line_pointer;
398260484Sobrien      c = get_symbol_end ();
398360484Sobrien    }
398460484Sobrien  if (sparc_arch_size == 64)
398560484Sobrien    {
398677298Sobrien      if (globals[reg])
398760484Sobrien	{
398877298Sobrien	  if ((regname && globals[reg] != (symbolS *) 1
398977298Sobrien	       && strcmp (S_GET_NAME (globals[reg]), regname))
399077298Sobrien	      || ((regname != NULL) ^ (globals[reg] != (symbolS *) 1)))
399160484Sobrien	    as_bad (_("redefinition of global register"));
399260484Sobrien	}
399360484Sobrien      else
399460484Sobrien	{
399560484Sobrien	  if (regname == NULL)
399677298Sobrien	    globals[reg] = (symbolS *) 1;
399760484Sobrien	  else
399860484Sobrien	    {
399960484Sobrien	      if (*regname)
400060484Sobrien		{
400160484Sobrien		  if (symbol_find (regname))
400260484Sobrien		    as_bad (_("Register symbol %s already defined."),
400360484Sobrien			    regname);
400460484Sobrien		}
400577298Sobrien	      globals[reg] = symbol_make (regname);
400677298Sobrien	      flags = symbol_get_bfdsym (globals[reg])->flags;
400760484Sobrien	      if (! *regname)
400860484Sobrien		flags = flags & ~(BSF_GLOBAL|BSF_LOCAL|BSF_WEAK);
400960484Sobrien	      if (! (flags & (BSF_GLOBAL|BSF_LOCAL|BSF_WEAK)))
401060484Sobrien		flags |= BSF_GLOBAL;
401177298Sobrien	      symbol_get_bfdsym (globals[reg])->flags = flags;
401277298Sobrien	      S_SET_VALUE (globals[reg], (valueT) reg);
401377298Sobrien	      S_SET_ALIGN (globals[reg], reg);
401477298Sobrien	      S_SET_SIZE (globals[reg], 0);
401560484Sobrien	      /* Although we actually want undefined_section here,
401660484Sobrien		 we have to use absolute_section, because otherwise
401760484Sobrien		 generic as code will make it a COM section.
401860484Sobrien		 We fix this up in sparc_adjust_symtab.  */
401977298Sobrien	      S_SET_SEGMENT (globals[reg], absolute_section);
402077298Sobrien	      S_SET_OTHER (globals[reg], 0);
402177298Sobrien	      elf_symbol (symbol_get_bfdsym (globals[reg]))
402260484Sobrien		->internal_elf_sym.st_info =
402360484Sobrien		  ELF_ST_INFO(STB_GLOBAL, STT_REGISTER);
402477298Sobrien	      elf_symbol (symbol_get_bfdsym (globals[reg]))
402560484Sobrien		->internal_elf_sym.st_shndx = SHN_UNDEF;
402660484Sobrien	    }
402760484Sobrien	}
402860484Sobrien    }
402960484Sobrien
403060484Sobrien  *input_line_pointer = c;
403160484Sobrien
403260484Sobrien  demand_empty_rest_of_line ();
403360484Sobrien}
403460484Sobrien
403560484Sobrien/* Adjust the symbol table.  We set undefined sections for STT_REGISTER
403660484Sobrien   symbols which need it.  */
403777298Sobrien
403860484Sobrienvoid
403960484Sobriensparc_adjust_symtab ()
404060484Sobrien{
404160484Sobrien  symbolS *sym;
404277298Sobrien
404360484Sobrien  for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
404460484Sobrien    {
404560484Sobrien      if (ELF_ST_TYPE (elf_symbol (symbol_get_bfdsym (sym))
404660484Sobrien		       ->internal_elf_sym.st_info) != STT_REGISTER)
404760484Sobrien	continue;
404860484Sobrien
404960484Sobrien      if (ELF_ST_TYPE (elf_symbol (symbol_get_bfdsym (sym))
405060484Sobrien		       ->internal_elf_sym.st_shndx != SHN_UNDEF))
405160484Sobrien	continue;
405260484Sobrien
405360484Sobrien      S_SET_SEGMENT (sym, undefined_section);
405460484Sobrien    }
405560484Sobrien}
405660484Sobrien#endif
405760484Sobrien
405859024Sobrien/* If the --enforce-aligned-data option is used, we require .word,
405959024Sobrien   et. al., to be aligned correctly.  We do it by setting up an
406059024Sobrien   rs_align_code frag, and checking in HANDLE_ALIGN to make sure that
406159024Sobrien   no unexpected alignment was introduced.
406259024Sobrien
406359024Sobrien   The SunOS and Solaris native assemblers enforce aligned data by
406459024Sobrien   default.  We don't want to do that, because gcc can deliberately
406559024Sobrien   generate misaligned data if the packed attribute is used.  Instead,
406659024Sobrien   we permit misaligned data by default, and permit the user to set an
406759024Sobrien   option to check for it.  */
406859024Sobrien
406959024Sobrienvoid
407059024Sobriensparc_cons_align (nbytes)
407159024Sobrien     int nbytes;
407259024Sobrien{
407359024Sobrien  int nalign;
407459024Sobrien  char *p;
407559024Sobrien
407659024Sobrien  /* Only do this if we are enforcing aligned data.  */
407759024Sobrien  if (! enforce_aligned_data)
407859024Sobrien    return;
407959024Sobrien
408078828Sobrien  /* Don't align if this is an unaligned pseudo-op.  */
408159024Sobrien  if (sparc_no_align_cons)
408278828Sobrien    return;
408359024Sobrien
408460484Sobrien  nalign = log2 (nbytes);
408559024Sobrien  if (nalign == 0)
408659024Sobrien    return;
408759024Sobrien
408860484Sobrien  assert (nalign > 0);
408960484Sobrien
409059024Sobrien  if (now_seg == absolute_section)
409159024Sobrien    {
409259024Sobrien      if ((abs_section_offset & ((1 << nalign) - 1)) != 0)
409360484Sobrien	as_bad (_("misaligned data"));
409459024Sobrien      return;
409559024Sobrien    }
409659024Sobrien
409777298Sobrien  p = frag_var (rs_align_test, 1, 1, (relax_substateT) 0,
409859024Sobrien		(symbolS *) NULL, (offsetT) nalign, (char *) NULL);
409959024Sobrien
410059024Sobrien  record_alignment (now_seg, nalign);
410159024Sobrien}
410259024Sobrien
410377298Sobrien/* This is called from HANDLE_ALIGN in tc-sparc.h.  */
410459024Sobrien
410559024Sobrienvoid
410659024Sobriensparc_handle_align (fragp)
410759024Sobrien     fragS *fragp;
410859024Sobrien{
410977298Sobrien  int count, fix;
411077298Sobrien  char *p;
411177298Sobrien
411277298Sobrien  count = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
411377298Sobrien
411477298Sobrien  switch (fragp->fr_type)
411559024Sobrien    {
411677298Sobrien    case rs_align_test:
411777298Sobrien      if (count != 0)
411877298Sobrien	as_bad_where (fragp->fr_file, fragp->fr_line, _("misaligned data"));
411977298Sobrien      break;
412060484Sobrien
412177298Sobrien    case rs_align_code:
412277298Sobrien      p = fragp->fr_literal + fragp->fr_fix;
412377298Sobrien      fix = 0;
412477298Sobrien
412577298Sobrien      if (count & 3)
412677298Sobrien	{
412777298Sobrien	  fix = count & 3;
412877298Sobrien	  memset (p, 0, fix);
412977298Sobrien	  p += fix;
413077298Sobrien	  count -= fix;
413177298Sobrien	}
413277298Sobrien
413377298Sobrien      if (SPARC_OPCODE_ARCH_V9_P (max_architecture) && count > 8)
413477298Sobrien	{
413577298Sobrien	  unsigned wval = (0x30680000 | count >> 2); /* ba,a,pt %xcc, 1f  */
413677298Sobrien	  if (INSN_BIG_ENDIAN)
413777298Sobrien	    number_to_chars_bigendian (p, wval, 4);
413877298Sobrien	  else
413977298Sobrien	    number_to_chars_littleendian (p, wval, 4);
414077298Sobrien	  p += 4;
414177298Sobrien	  count -= 4;
414277298Sobrien	  fix += 4;
414377298Sobrien	}
414477298Sobrien
414577298Sobrien      if (INSN_BIG_ENDIAN)
414677298Sobrien	number_to_chars_bigendian (p, 0x01000000, 4);
414777298Sobrien      else
414877298Sobrien	number_to_chars_littleendian (p, 0x01000000, 4);
414977298Sobrien
415077298Sobrien      fragp->fr_fix += fix;
415177298Sobrien      fragp->fr_var = 4;
415277298Sobrien      break;
415377298Sobrien
415477298Sobrien    default:
415577298Sobrien      break;
415659024Sobrien    }
415759024Sobrien}
415859024Sobrien
415959024Sobrien#ifdef OBJ_ELF
416059024Sobrien/* Some special processing for a Sparc ELF file.  */
416159024Sobrien
416259024Sobrienvoid
416359024Sobriensparc_elf_final_processing ()
416459024Sobrien{
416559024Sobrien  /* Set the Sparc ELF flag bits.  FIXME: There should probably be some
416659024Sobrien     sort of BFD interface for this.  */
416759024Sobrien  if (sparc_arch_size == 64)
416860484Sobrien    {
416960484Sobrien      switch (sparc_memory_model)
417060484Sobrien	{
417160484Sobrien	case MM_RMO:
417260484Sobrien	  elf_elfheader (stdoutput)->e_flags |= EF_SPARCV9_RMO;
417360484Sobrien	  break;
417460484Sobrien	case MM_PSO:
417560484Sobrien	  elf_elfheader (stdoutput)->e_flags |= EF_SPARCV9_PSO;
417660484Sobrien	  break;
417760484Sobrien	default:
417860484Sobrien	  break;
417960484Sobrien	}
418060484Sobrien    }
418159024Sobrien  else if (current_architecture >= SPARC_OPCODE_ARCH_V9)
418259024Sobrien    elf_elfheader (stdoutput)->e_flags |= EF_SPARC_32PLUS;
418359024Sobrien  if (current_architecture == SPARC_OPCODE_ARCH_V9A)
418459024Sobrien    elf_elfheader (stdoutput)->e_flags |= EF_SPARC_SUN_US1;
418577298Sobrien  else if (current_architecture == SPARC_OPCODE_ARCH_V9B)
418677298Sobrien    elf_elfheader (stdoutput)->e_flags |= EF_SPARC_SUN_US1|EF_SPARC_SUN_US3;
418759024Sobrien}
418889857Sobrien
418989857Sobrienvoid
419089857Sobriensparc_cons (exp, size)
419189857Sobrien     expressionS *exp;
419289857Sobrien     int size;
419389857Sobrien{
419489857Sobrien  char *save;
419589857Sobrien
419689857Sobrien  SKIP_WHITESPACE ();
419789857Sobrien  sparc_cons_special_reloc = NULL;
419889857Sobrien  save = input_line_pointer;
419989857Sobrien  if (input_line_pointer[0] == '%'
420089857Sobrien      && input_line_pointer[1] == 'r'
420189857Sobrien      && input_line_pointer[2] == '_')
420289857Sobrien    {
420389857Sobrien      if (strncmp (input_line_pointer + 3, "disp", 4) == 0)
420489857Sobrien	{
420589857Sobrien	  input_line_pointer += 7;
420689857Sobrien	  sparc_cons_special_reloc = "disp";
420789857Sobrien	}
420889857Sobrien      else if (strncmp (input_line_pointer + 3, "plt", 3) == 0)
420989857Sobrien	{
421089857Sobrien	  if (size != 4 && size != 8)
421189857Sobrien	    as_bad (_("Illegal operands: %%r_plt in %d-byte data field"), size);
421289857Sobrien	  else
421389857Sobrien	    {
421489857Sobrien	      input_line_pointer += 6;
421589857Sobrien	      sparc_cons_special_reloc = "plt";
421689857Sobrien	    }
421789857Sobrien	}
421889857Sobrien      if (sparc_cons_special_reloc)
421989857Sobrien	{
422089857Sobrien	  int bad = 0;
422189857Sobrien
422289857Sobrien	  switch (size)
422389857Sobrien	    {
422489857Sobrien	    case 1:
422589857Sobrien	      if (*input_line_pointer != '8')
422689857Sobrien		bad = 1;
422789857Sobrien	      input_line_pointer--;
422889857Sobrien	      break;
422989857Sobrien	    case 2:
423089857Sobrien	      if (input_line_pointer[0] != '1' || input_line_pointer[1] != '6')
423189857Sobrien		bad = 1;
423289857Sobrien	      break;
423389857Sobrien	    case 4:
423489857Sobrien	      if (input_line_pointer[0] != '3' || input_line_pointer[1] != '2')
423589857Sobrien		bad = 1;
423689857Sobrien	      break;
423789857Sobrien	    case 8:
423889857Sobrien	      if (input_line_pointer[0] != '6' || input_line_pointer[1] != '4')
423989857Sobrien		bad = 1;
424089857Sobrien	      break;
424189857Sobrien	    default:
424289857Sobrien	      bad = 1;
424389857Sobrien	      break;
424489857Sobrien	    }
424589857Sobrien
424689857Sobrien	  if (bad)
424789857Sobrien	    {
424889857Sobrien	      as_bad (_("Illegal operands: Only %%r_%s%d allowed in %d-byte data fields"),
424989857Sobrien		      sparc_cons_special_reloc, size * 8, size);
425089857Sobrien	    }
425189857Sobrien	  else
425289857Sobrien	    {
425389857Sobrien	      input_line_pointer += 2;
425489857Sobrien	      if (*input_line_pointer != '(')
425589857Sobrien		{
425689857Sobrien		  as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
425789857Sobrien			  sparc_cons_special_reloc, size * 8);
425889857Sobrien		  bad = 1;
425989857Sobrien		}
426089857Sobrien	    }
426189857Sobrien
426289857Sobrien	  if (bad)
426389857Sobrien	    {
426489857Sobrien	      input_line_pointer = save;
426589857Sobrien	      sparc_cons_special_reloc = NULL;
426689857Sobrien	    }
426789857Sobrien	  else
426889857Sobrien	    {
426989857Sobrien	      int c;
427089857Sobrien	      char *end = ++input_line_pointer;
427189857Sobrien	      int npar = 0;
427289857Sobrien
427389857Sobrien	      while (! is_end_of_line[(c = *end)])
427489857Sobrien		{
427589857Sobrien		  if (c == '(')
427689857Sobrien	  	    npar++;
427789857Sobrien		  else if (c == ')')
427889857Sobrien	  	    {
427989857Sobrien		      if (!npar)
428089857Sobrien	      		break;
428189857Sobrien		      npar--;
428289857Sobrien		    }
428389857Sobrien	    	  end++;
428489857Sobrien		}
428589857Sobrien
428689857Sobrien	      if (c != ')')
428789857Sobrien		as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
428889857Sobrien			sparc_cons_special_reloc, size * 8);
428989857Sobrien	      else
429089857Sobrien		{
429189857Sobrien		  *end = '\0';
429289857Sobrien		  expression (exp);
429389857Sobrien		  *end = c;
429489857Sobrien		  if (input_line_pointer != end)
429589857Sobrien		    {
429689857Sobrien		      as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
429789857Sobrien			      sparc_cons_special_reloc, size * 8);
429889857Sobrien		    }
429989857Sobrien		  else
430089857Sobrien		    {
430189857Sobrien		      input_line_pointer++;
430289857Sobrien		      SKIP_WHITESPACE ();
430389857Sobrien		      c = *input_line_pointer;
430489857Sobrien		      if (! is_end_of_line[c] && c != ',')
430589857Sobrien			as_bad (_("Illegal operands: garbage after %%r_%s%d()"),
430689857Sobrien			        sparc_cons_special_reloc, size * 8);
430789857Sobrien		    }
430889857Sobrien		}
430989857Sobrien	    }
431089857Sobrien	}
431189857Sobrien    }
431289857Sobrien  if (sparc_cons_special_reloc == NULL)
431389857Sobrien    expression (exp);
431489857Sobrien}
431589857Sobrien
431659024Sobrien#endif
431760484Sobrien
431860484Sobrien/* This is called by emit_expr via TC_CONS_FIX_NEW when creating a
431960484Sobrien   reloc for a cons.  We could use the definition there, except that
432060484Sobrien   we want to handle little endian relocs specially.  */
432160484Sobrien
432260484Sobrienvoid
432360484Sobriencons_fix_new_sparc (frag, where, nbytes, exp)
432460484Sobrien     fragS *frag;
432560484Sobrien     int where;
432660484Sobrien     unsigned int nbytes;
432760484Sobrien     expressionS *exp;
432860484Sobrien{
432960484Sobrien  bfd_reloc_code_real_type r;
433060484Sobrien
433160484Sobrien  r = (nbytes == 1 ? BFD_RELOC_8 :
433260484Sobrien       (nbytes == 2 ? BFD_RELOC_16 :
433360484Sobrien	(nbytes == 4 ? BFD_RELOC_32 : BFD_RELOC_64)));
433460484Sobrien
433578828Sobrien  if (target_little_endian_data
433678828Sobrien      && nbytes == 4
433777298Sobrien      && now_seg->flags & SEC_ALLOC)
433860484Sobrien    r = BFD_RELOC_SPARC_REV32;
433978828Sobrien
434089857Sobrien  if (sparc_cons_special_reloc)
434178828Sobrien    {
434289857Sobrien      if (*sparc_cons_special_reloc == 'd')
434389857Sobrien	switch (nbytes)
434489857Sobrien	  {
434589857Sobrien	  case 1: r = BFD_RELOC_8_PCREL; break;
434689857Sobrien	  case 2: r = BFD_RELOC_16_PCREL; break;
434789857Sobrien	  case 4: r = BFD_RELOC_32_PCREL; break;
434889857Sobrien	  case 8: r = BFD_RELOC_64_PCREL; break;
434989857Sobrien	  default: abort ();
435089857Sobrien	  }
435189857Sobrien      else
435289857Sobrien	switch (nbytes)
435389857Sobrien	  {
435489857Sobrien	  case 4: r = BFD_RELOC_SPARC_PLT32; break;
435589857Sobrien	  case 8: r = BFD_RELOC_SPARC_PLT64; break;
435689857Sobrien	  }
435789857Sobrien    }
435889857Sobrien  else if (sparc_no_align_cons)
435989857Sobrien    {
436078828Sobrien      switch (nbytes)
436178828Sobrien	{
436278828Sobrien	case 2: r = BFD_RELOC_SPARC_UA16; break;
436378828Sobrien	case 4: r = BFD_RELOC_SPARC_UA32; break;
436478828Sobrien	case 8: r = BFD_RELOC_SPARC_UA64; break;
436578828Sobrien	default: abort ();
436678828Sobrien	}
436789857Sobrien   }
436878828Sobrien
436960484Sobrien  fix_new_exp (frag, where, (int) nbytes, exp, 0, r);
437060484Sobrien}
437160484Sobrien
437260484Sobrien#ifdef OBJ_ELF
437360484Sobrienint
437460484Sobrienelf32_sparc_force_relocation (fixp)
437577298Sobrien     struct fix *fixp;
437660484Sobrien{
437760484Sobrien  if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
437860484Sobrien      || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
437960484Sobrien    return 1;
438077298Sobrien
438160484Sobrien  return 0;
438260484Sobrien}
438360484Sobrien#endif
4384