tc-sparc.c revision 59024
177218Sphk/* tc-sparc.c -- Assemble for the SPARC
277218Sphk   Copyright (C) 1989, 90-96, 97, 1998 Free Software Foundation, Inc.
377218Sphk   This file is part of GAS, the GNU Assembler.
477218Sphk
577218Sphk   GAS is free software; you can redistribute it and/or modify
677218Sphk   it under the terms of the GNU General Public License as published by
777218Sphk   the Free Software Foundation; either version 2, or (at your option)
877218Sphk   any later version.
977218Sphk
1077218Sphk   GAS is distributed in the hope that it will be useful,
1177218Sphk   but WITHOUT ANY WARRANTY; without even the implied warranty of
1291454Sbrooks   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1391454Sbrooks   GNU General Public License for more details.
1477218Sphk
1577218Sphk   You should have received a copy of the GNU General Public
1677218Sphk   License along with GAS; see the file COPYING.  If not, write
1777218Sphk   to the Free Software Foundation, 59 Temple Place - Suite 330,
1877218Sphk   Boston, MA 02111-1307, USA. */
1977218Sphk
2077218Sphk#include <stdio.h>
2177218Sphk#include <ctype.h>
2277218Sphk
2377218Sphk#include "as.h"
2477218Sphk#include "subsegs.h"
2577218Sphk
2677218Sphk#include "opcode/sparc.h"
2777218Sphk
2877218Sphk#ifdef OBJ_ELF
2977218Sphk#include "elf/sparc.h"
3077218Sphk#endif
3177218Sphk
3277218Sphkstatic struct sparc_arch *lookup_arch PARAMS ((char *));
3377218Sphkstatic void init_default_arch PARAMS ((void));
3477218Sphkstatic void sparc_ip PARAMS ((char *, const struct sparc_opcode **));
3577218Sphkstatic int in_signed_range PARAMS ((bfd_signed_vma, bfd_signed_vma));
3677218Sphkstatic int in_unsigned_range PARAMS ((bfd_vma, bfd_vma));
3777218Sphkstatic int in_bitfield_range PARAMS ((bfd_signed_vma, bfd_signed_vma));
3877218Sphkstatic int sparc_ffs PARAMS ((unsigned int));
3977218Sphkstatic bfd_vma BSR PARAMS ((bfd_vma, int));
4077218Sphkstatic int cmp_reg_entry PARAMS ((const PTR, const PTR));
4177218Sphkstatic int parse_keyword_arg PARAMS ((int (*) (const char *), char **, int *));
4277218Sphkstatic int parse_const_expr_arg PARAMS ((char **, int *));
4377218Sphkstatic int get_expression PARAMS ((char *str));
4477218Sphk
4577218Sphk/* Default architecture.  */
4677218Sphk/* ??? The default value should be V8, but sparclite support was added
4777218Sphk   by making it the default.  GCC now passes -Asparclite, so maybe sometime in
4877218Sphk   the future we can set this to V8.  */
4977218Sphk#ifndef DEFAULT_ARCH
5077218Sphk#define DEFAULT_ARCH "sparclite"
5177218Sphk#endif
5277218Sphkstatic char *default_arch = DEFAULT_ARCH;
5377218Sphk
5477218Sphk/* Non-zero if the initial values of `max_architecture' and `sparc_arch_size'
5577218Sphk   have been set.  */
5677218Sphkstatic int default_init_p;
5777218Sphk
5877218Sphk/* Current architecture.  We don't bump up unless necessary.  */
5977218Sphkstatic enum sparc_opcode_arch_val current_architecture = SPARC_OPCODE_ARCH_V6;
6077218Sphk
6177218Sphk/* The maximum architecture level we can bump up to.
6277218Sphk   In a 32 bit environment, don't allow bumping up to v9 by default.
6377218Sphk   The native assembler works this way.  The user is required to pass
6477218Sphk   an explicit argument before we'll create v9 object files.  However, if
6577218Sphk   we don't see any v9 insns, a v8plus object file is not created.  */
6677218Sphkstatic enum sparc_opcode_arch_val max_architecture;
6777218Sphk
6877218Sphk/* Either 32 or 64, selects file format.  */
6977218Sphkstatic int sparc_arch_size;
7077218Sphk/* Initial (default) value, recorded separately in case a user option
7177218Sphk   changes the value before md_show_usage is called.  */
7277218Sphkstatic int default_arch_size;
7377218Sphk
7477218Sphk#ifdef OBJ_ELF
7577218Sphk/* The currently selected v9 memory model.  Currently only used for
7677218Sphk   ELF.  */
77138593Ssamstatic enum { MM_TSO, MM_PSO, MM_RMO } sparc_memory_model = MM_RMO;
7877218Sphk#endif
79138593Ssam
80116957Ssamstatic int architecture_requested;
81190456Ssamstatic int warn_on_bump;
82190456Ssam
83190456Ssam/* If warn_on_bump and the needed architecture is higher than this
8477218Sphk   architecture, issue a warning.  */
85187801Ssamstatic enum sparc_opcode_arch_val warn_after_architecture;
8677218Sphk
8777218Sphk/* Non-zero if we are generating PIC code.  */
8877218Sphkint sparc_pic_code;
8977218Sphk
90146873Sjhb/* Non-zero if we should give an error when misaligned data is seen.  */
9177218Sphkstatic int enforce_aligned_data;
9277218Sphk
9377218Sphkextern int target_big_endian;
9477218Sphk
95155931Ssam/* V9 has big and little endian data, but instructions are always big endian.
96173275Ssam   The sparclet has bi-endian support but both data and insns have the same
9777218Sphk   endianness.  Global `target_big_endian' is used for data.  The following
9877218Sphk   macro is used for instructions.  */
99178354Ssam#define INSN_BIG_ENDIAN (target_big_endian \
10077218Sphk			 || SPARC_OPCODE_ARCH_V9_P (max_architecture))
101178354Ssam
102178354Ssam/* handle of the OPCODE hash table */
103178354Ssamstatic struct hash_control *op_hash;
104178354Ssam
105178354Ssamstatic void s_data1 PARAMS ((void));
106178354Ssamstatic void s_seg PARAMS ((int));
107178354Ssamstatic void s_proc PARAMS ((int));
108178354Ssamstatic void s_reserve PARAMS ((int));
109178354Ssamstatic void s_common PARAMS ((int));
110178354Ssamstatic void s_empty PARAMS ((int));
111178354Ssamstatic void s_uacons PARAMS ((int));
112178354Ssam
113178354Ssamconst pseudo_typeS md_pseudo_table[] =
114178354Ssam{
115183261Ssam  {"align", s_align_bytes, 0},	/* Defaulting is invalid (0) */
116183261Ssam  {"common", s_common, 0},
117183261Ssam  {"empty", s_empty, 0},
118183261Ssam  {"global", s_globl, 0},
119183261Ssam  {"half", cons, 2},
120178354Ssam  {"optim", s_ignore, 0},
121178354Ssam  {"proc", s_proc, 0},
122187801Ssam  {"reserve", s_reserve, 0},
123187801Ssam  {"seg", s_seg, 0},
124173275Ssam  {"skip", s_space, 0},
125173275Ssam  {"word", cons, 4},
126173275Ssam  {"xword", cons, 8},
127173275Ssam  {"uahalf", s_uacons, 2},
128173275Ssam  {"uaword", s_uacons, 4},
129173275Ssam  {"uaxword", s_uacons, 8},
130173275Ssam#ifdef OBJ_ELF
131173275Ssam  /* these are specific to sparc/svr4 */
132188784Ssam  {"pushsection", obj_elf_section, 0},
133188784Ssam  {"popsection", obj_elf_previous, 0},
134188784Ssam  {"2byte", s_uacons, 2},
135188784Ssam  {"4byte", s_uacons, 4},
136188784Ssam  {"8byte", s_uacons, 8},
137188784Ssam#endif
138188784Ssam  {NULL, 0, 0},
139188784Ssam};
140188784Ssam
141188784Ssamconst int md_reloc_size = 12;	/* Size of relocation record */
142188784Ssam
143188784Ssam/* This array holds the chars that always start a comment.  If the
144188784Ssam   pre-processor is disabled, these aren't very useful */
145173275Ssamconst char comment_chars[] = "!";	/* JF removed '|' from comment_chars */
146173275Ssam
147178354Ssam/* This array holds the chars that only start a comment at the beginning of
148173275Ssam   a line.  If the line seems to have the form '# 123 filename'
149173275Ssam   .line and .file directives will appear in the pre-processed output */
150173275Ssam/* Note that input_file.c hand checks for '#' at the beginning of the
15177218Sphk   first line of the input file.  This is because the compiler outputs
15277218Sphk   #NO_APP at the beginning of its output. */
15377218Sphk/* Also note that comments started like this one will always
154178354Ssam   work if '/' isn't otherwise defined. */
155178354Ssamconst char line_comment_chars[] = "#";
156178354Ssam
157178354Ssamconst char line_separator_chars[] = "";
158178354Ssam
15977218Sphk/* Chars that can be used to separate mant from exp in floating point nums */
160187801Ssamconst char EXP_CHARS[] = "eE";
161178354Ssam
162178354Ssam/* Chars that mean this number is a floating point constant */
163178354Ssam/* As in 0f12.456 */
164178354Ssam/* or    0d1.2345e12 */
165178354Ssamconst char FLT_CHARS[] = "rRsSfFdDxXpP";
166178354Ssam
167173275Ssam/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
168173275Ssam   changed in read.c.  Ideally it shouldn't have to know about it at all,
169178354Ssam   but nothing is ideal around here.  */
170173275Ssam
171173275Ssamstatic unsigned char octal[256];
172170531Ssam#define isoctal(c)  octal[(unsigned char) (c)]
173173275Ssamstatic unsigned char toHex[256];
174173275Ssam
175173275Ssamstruct sparc_it
176173275Ssam  {
177173275Ssam    char *error;
178173275Ssam    unsigned long opcode;
179173275Ssam    struct nlist *nlistp;
180173275Ssam    expressionS exp;
181173275Ssam    int pcrel;
182173275Ssam    bfd_reloc_code_real_type reloc;
183170531Ssam  };
184170531Ssam
185170531Ssamstruct sparc_it the_insn, set_insn;
186170531Ssam
187170531Ssamstatic void output_insn
188170531Ssam  PARAMS ((const struct sparc_opcode *, struct sparc_it *));
189170531Ssam
190187801Ssam/* Table of arguments to -A.
191170531Ssam   The sparc_opcode_arch table in sparc-opc.c is insufficient and incorrect
192187801Ssam   for this use.  That table is for opcodes only.  This table is for opcodes
193187801Ssam   and file formats.  */
194187801Ssam
195187801Ssamstatic struct sparc_arch {
196187801Ssam  char *name;
197187801Ssam  char *opcode_arch;
198170531Ssam  /* Default word size, as specified during configuration.
199173275Ssam     A value of zero means can't be used to specify default architecture.  */
200170531Ssam  int default_arch_size;
201170531Ssam  /* Allowable arg to -A?  */
202178354Ssam  int user_option_p;
203178354Ssam} sparc_arch_table[] = {
204178354Ssam  { "v6", "v6", 0, 1 },
205178354Ssam  { "v7", "v7", 0, 1 },
206178354Ssam  { "v8", "v8", 32, 1 },
207178354Ssam  { "sparclet", "sparclet", 32, 1 },
208178354Ssam  { "sparclite", "sparclite", 32, 1 },
209181198Ssam  { "v8plus", "v9", 0, 1 },
210178354Ssam  { "v8plusa", "v9a", 0, 1 },
211178354Ssam  { "v9", "v9", 0, 1 },
212178354Ssam  { "v9a", "v9a", 0, 1 },
213178354Ssam  /* This exists to allow configure.in/Makefile.in to pass one
214170531Ssam     value to specify both the default machine and default word size.  */
215170531Ssam  { "v9-64", "v9", 64, 0 },
216170531Ssam  { NULL, NULL, 0 }
217170531Ssam};
218170531Ssam
219170531Ssamstatic struct sparc_arch *
220170531Ssamlookup_arch (name)
221138593Ssam     char *name;
222170531Ssam{
223170531Ssam  struct sparc_arch *sa;
224187801Ssam
225170531Ssam  for (sa = &sparc_arch_table[0]; sa->name != NULL; sa++)
226170531Ssam    if (strcmp (sa->name, name) == 0)
227170531Ssam      break;
228170531Ssam  if (sa->name == NULL)
229170531Ssam    return NULL;
230187801Ssam  return sa;
231187801Ssam}
232187801Ssam
233170531Ssam/* Initialize the default opcode arch and word size from the default
234170531Ssam   architecture name.  */
235187801Ssam
236187801Ssamstatic void
237170531Ssaminit_default_arch ()
238170531Ssam{
239170531Ssam  struct sparc_arch *sa = lookup_arch (default_arch);
240170531Ssam
241170531Ssam  if (sa == NULL
242170531Ssam      || sa->default_arch_size == 0)
243170531Ssam    as_fatal ("Invalid default architecture, broken assembler.");
244170531Ssam
245170531Ssam  max_architecture = sparc_opcode_lookup_arch (sa->opcode_arch);
246170531Ssam  if (max_architecture == SPARC_OPCODE_ARCH_BAD)
247170531Ssam    as_fatal ("Bad opcode table, broken assembler.");
248170531Ssam  default_arch_size = sparc_arch_size = sa->default_arch_size;
249170531Ssam  default_init_p = 1;
250170531Ssam}
251170531Ssam
252170531Ssam/* Called by TARGET_FORMAT.  */
253170531Ssam
254170531Ssamconst char *
255170531Ssamsparc_target_format ()
256170531Ssam{
257170531Ssam  /* We don't get a chance to initialize anything before we're called,
258170531Ssam     so handle that now.  */
259170531Ssam  if (! default_init_p)
260170531Ssam    init_default_arch ();
261170531Ssam
262170531Ssam#ifdef OBJ_AOUT
263170531Ssam#ifdef TE_NetBSD
264170531Ssam  return "a.out-sparc-netbsd";
265170531Ssam#else
266170531Ssam#ifdef TE_SPARCAOUT
267170531Ssam  return target_big_endian ? "a.out-sunos-big" : "a.out-sparc-little";
268170531Ssam#else
269170531Ssam  return "a.out-sunos-big";
270170531Ssam#endif
271170531Ssam#endif
272170531Ssam#endif
273170531Ssam
274170531Ssam#ifdef OBJ_BOUT
275170531Ssam  return "b.out.big";
276170531Ssam#endif
277170531Ssam
278173275Ssam#ifdef OBJ_COFF
279170531Ssam#ifdef TE_LYNX
280170531Ssam  return "coff-sparc-lynx";
281173275Ssam#else
282173275Ssam  return "coff-sparc";
283173275Ssam#endif
284173275Ssam#endif
285173275Ssam
286173275Ssam#ifdef OBJ_ELF
287170531Ssam  return sparc_arch_size == 64 ? "elf64-sparc" : "elf32-sparc";
288173275Ssam#endif
289170531Ssam
290170531Ssam  abort ();
291173275Ssam}
292173275Ssam
293173275Ssam/*
294173275Ssam * md_parse_option
295173275Ssam *	Invocation line includes a switch not recognized by the base assembler.
296173275Ssam *	See if it's a processor-specific option.  These are:
297170531Ssam *
298170531Ssam *	-bump
299170531Ssam *		Warn on architecture bumps.  See also -A.
300170531Ssam *
301170531Ssam *	-Av6, -Av7, -Av8, -Asparclite, -Asparclet
302170531Ssam *		Standard 32 bit architectures.
303170531Ssam *	-Av8plus, -Av8plusa
304170531Ssam *		Sparc64 in a 32 bit world.
305170531Ssam *	-Av9, -Av9a
306187801Ssam *		Sparc64 in either a 32 or 64 bit world (-32/-64 says which).
307187801Ssam *		This used to only mean 64 bits, but properly specifying it
308170531Ssam *		complicated gcc's ASM_SPECs, so now opcode selection is
309170531Ssam *		specified orthogonally to word size (except when specifying
310170531Ssam *		the default, but that is an internal implementation detail).
311170531Ssam *	-xarch=v8plus, -xarch=v8plusa
312187801Ssam *		Same as -Av8plus{,a}, for compatibility with Sun's assembler.
313170531Ssam *
314170531Ssam *		Select the architecture and possibly the file format.
315170531Ssam *		Instructions or features not supported by the selected
316170531Ssam *		architecture cause fatal errors.
317170531Ssam *
318170531Ssam *		The default is to start at v6, and bump the architecture up
319170531Ssam *		whenever an instruction is seen at a higher level.  In 32 bit
320170531Ssam *		environments, v9 is not bumped up to, the user must pass
321170531Ssam * 		-Av8plus{,a}.
322170531Ssam *
323170531Ssam *		If -bump is specified, a warning is printing when bumping to
324170531Ssam *		higher levels.
325170531Ssam *
326187801Ssam *		If an architecture is specified, all instructions must match
327187801Ssam *		that architecture.  Any higher level instructions are flagged
328170531Ssam *		as errors.  Note that in the 32 bit environment specifying
329170531Ssam *		-Av8plus does not automatically create a v8plus object file, a
330170531Ssam *		v9 insn must be seen.
331170531Ssam *
332187801Ssam *		If both an architecture and -bump are specified, the
333170531Ssam *		architecture starts at the specified level, but bumps are
334170531Ssam *		warnings.  Note that we can't set `current_architecture' to
335170531Ssam *		the requested level in this case: in the 32 bit environment,
336170531Ssam *		we still must avoid creating v8plus object files unless v9
337170531Ssam * 		insns are seen.
338173275Ssam *
339170531Ssam * Note:
340170531Ssam *		Bumping between incompatible architectures is always an
341173275Ssam *		error.  For example, from sparclite to v9.
342173275Ssam */
343173275Ssam
344173275Ssam#ifdef OBJ_ELF
345173275SsamCONST char *md_shortopts = "A:K:VQ:sq";
346173275Ssam#else
347173275Ssam#ifdef OBJ_AOUT
348173275SsamCONST char *md_shortopts = "A:k";
349173275Ssam#else
350187801SsamCONST char *md_shortopts = "A:";
351173275Ssam#endif
352173275Ssam#endif
353173275Ssamstruct option md_longopts[] = {
354173275Ssam#define OPTION_BUMP (OPTION_MD_BASE)
355173275Ssam  {"bump", no_argument, NULL, OPTION_BUMP},
356173275Ssam#define OPTION_SPARC (OPTION_MD_BASE + 1)
357173275Ssam  {"sparc", no_argument, NULL, OPTION_SPARC},
358178354Ssam#define OPTION_XARCH (OPTION_MD_BASE + 2)
359178354Ssam  {"xarch", required_argument, NULL, OPTION_XARCH},
360178354Ssam#ifdef OBJ_ELF
361178354Ssam#define OPTION_32 (OPTION_MD_BASE + 3)
362178354Ssam  {"32", no_argument, NULL, OPTION_32},
363178354Ssam#define OPTION_64 (OPTION_MD_BASE + 4)
364178354Ssam  {"64", no_argument, NULL, OPTION_64},
365178354Ssam#define OPTION_TSO (OPTION_MD_BASE + 5)
366178354Ssam  {"TSO", no_argument, NULL, OPTION_TSO},
367178354Ssam#define OPTION_PSO (OPTION_MD_BASE + 6)
368178354Ssam  {"PSO", no_argument, NULL, OPTION_PSO},
369178354Ssam#define OPTION_RMO (OPTION_MD_BASE + 7)
370178354Ssam  {"RMO", no_argument, NULL, OPTION_RMO},
371178354Ssam#endif
372178354Ssam#ifdef SPARC_BIENDIAN
373188784Ssam#define OPTION_LITTLE_ENDIAN (OPTION_MD_BASE + 8)
374188784Ssam  {"EL", no_argument, NULL, OPTION_LITTLE_ENDIAN},
375188784Ssam#define OPTION_BIG_ENDIAN (OPTION_MD_BASE + 9)
376188784Ssam  {"EB", no_argument, NULL, OPTION_BIG_ENDIAN},
377178354Ssam#endif
378178354Ssam#define OPTION_ENFORCE_ALIGNED_DATA (OPTION_MD_BASE + 10)
379178354Ssam  {"enforce-aligned-data", no_argument, NULL, OPTION_ENFORCE_ALIGNED_DATA},
380178354Ssam  {NULL, no_argument, NULL, 0}
381178354Ssam};
382178354Ssamsize_t md_longopts_size = sizeof(md_longopts);
383178354Ssam
384178354Ssamint
385178354Ssammd_parse_option (c, arg)
386178354Ssam     int c;
387178354Ssam     char *arg;
388178354Ssam{
389178354Ssam  /* We don't get a chance to initialize anything before we're called,
390178354Ssam     so handle that now.  */
391178354Ssam  if (! default_init_p)
392178354Ssam    init_default_arch ();
393187801Ssam
394178354Ssam  switch (c)
395178354Ssam    {
396178354Ssam    case OPTION_BUMP:
397178354Ssam      warn_on_bump = 1;
398178354Ssam      warn_after_architecture = SPARC_OPCODE_ARCH_V6;
399178354Ssam      break;
400178354Ssam
401178354Ssam    case OPTION_XARCH:
402178354Ssam      /* This is for compatibility with Sun's assembler.  */
403178354Ssam      if (strcmp (arg, "v8plus") != 0
404178354Ssam	  && strcmp (arg, "v8plusa") != 0)
405178354Ssam	{
406178354Ssam	  as_bad ("invalid architecture -xarch=%s", arg);
407178354Ssam	  return 0;
408178354Ssam	}
409178354Ssam
410178354Ssam      /* fall through */
411187801Ssam
412178354Ssam    case 'A':
413178354Ssam      {
414178354Ssam	struct sparc_arch *sa;
415178354Ssam	enum sparc_opcode_arch_val opcode_arch;
416178354Ssam
417178354Ssam	sa = lookup_arch (arg);
418178354Ssam	if (sa == NULL
419178354Ssam	    || ! sa->user_option_p)
420178354Ssam	  {
421178354Ssam	    as_bad ("invalid architecture -A%s", arg);
422178354Ssam	    return 0;
423178354Ssam	  }
424178354Ssam
425178354Ssam	opcode_arch = sparc_opcode_lookup_arch (sa->opcode_arch);
426178354Ssam	if (opcode_arch == SPARC_OPCODE_ARCH_BAD)
427178354Ssam	  as_fatal ("Bad opcode table, broken assembler.");
428178354Ssam
429187801Ssam	max_architecture = opcode_arch;
430178354Ssam	architecture_requested = 1;
431178354Ssam      }
432178354Ssam      break;
433178354Ssam
434178354Ssam    case OPTION_SPARC:
435178354Ssam      /* Ignore -sparc, used by SunOS make default .s.o rule.  */
436187801Ssam      break;
437187801Ssam
438187801Ssam    case OPTION_ENFORCE_ALIGNED_DATA:
439178354Ssam      enforce_aligned_data = 1;
440178354Ssam      break;
441178354Ssam
442178354Ssam#ifdef SPARC_BIENDIAN
443178354Ssam    case OPTION_LITTLE_ENDIAN:
444187801Ssam      target_big_endian = 0;
445178354Ssam      break;
446187801Ssam    case OPTION_BIG_ENDIAN:
447178354Ssam      target_big_endian = 1;
448178354Ssam      break;
449186102Ssam#endif
450178354Ssam
451178354Ssam#ifdef OBJ_AOUT
452178354Ssam    case 'k':
453178354Ssam      sparc_pic_code = 1;
454178354Ssam      break;
455178354Ssam#endif
456178354Ssam
457178354Ssam#ifdef OBJ_ELF
458178354Ssam    case OPTION_32:
459178354Ssam    case OPTION_64:
460178354Ssam      {
461178354Ssam	const char **list, **l;
462178354Ssam
463178354Ssam	sparc_arch_size = c == OPTION_32 ? 32 : 64;
464178354Ssam	list = bfd_target_list ();
465178354Ssam	for (l = list; *l != NULL; l++)
466178354Ssam	  {
467178354Ssam	    if (sparc_arch_size == 32)
468178354Ssam	      {
469178354Ssam		if (strcmp (*l, "elf32-sparc") == 0)
470178354Ssam		  break;
471178354Ssam	      }
472178354Ssam	    else
473178354Ssam	      {
474178354Ssam		if (strcmp (*l, "elf64-sparc") == 0)
475178354Ssam		  break;
476178354Ssam	      }
477178354Ssam	  }
478178354Ssam	if (*l == NULL)
479178354Ssam	  as_fatal ("No compiled in support for %d bit object file format",
480186102Ssam		    sparc_arch_size);
481178354Ssam	free (list);
482178354Ssam      }
483178354Ssam      break;
484178354Ssam
485178354Ssam    case OPTION_TSO:
486178354Ssam      sparc_memory_model = MM_TSO;
487178354Ssam      break;
488178354Ssam
489178354Ssam    case OPTION_PSO:
490178354Ssam      sparc_memory_model = MM_PSO;
491178354Ssam      break;
492187801Ssam
493187801Ssam    case OPTION_RMO:
494187801Ssam      sparc_memory_model = MM_RMO;
495187801Ssam      break;
496187801Ssam
497178354Ssam    case 'V':
498178354Ssam      print_version_id ();
499187801Ssam      break;
500187801Ssam
501187801Ssam    case 'Q':
502187801Ssam      /* Qy - do emit .comment
503187801Ssam	 Qn - do not emit .comment */
504187801Ssam      break;
505178354Ssam
506178354Ssam    case 's':
507187801Ssam      /* use .stab instead of .stab.excl */
508187801Ssam      break;
509187801Ssam
510187801Ssam    case 'q':
511187801Ssam      /* quick -- native assembler does fewer checks */
512178354Ssam      break;
513178354Ssam
514178354Ssam    case 'K':
515178354Ssam      if (strcmp (arg, "PIC") != 0)
516187801Ssam	as_warn ("Unrecognized option following -K");
517187801Ssam      else
518187801Ssam	sparc_pic_code = 1;
519187801Ssam      break;
520187801Ssam#endif
521187801Ssam
522187801Ssam    default:
523187801Ssam      return 0;
524187801Ssam    }
525178354Ssam
526187801Ssam  return 1;
527178354Ssam}
528187801Ssam
529187801Ssamvoid
530187801Ssammd_show_usage (stream)
531187801Ssam     FILE *stream;
532178354Ssam{
533178354Ssam  const struct sparc_arch *arch;
534170531Ssam
535170531Ssam  /* We don't get a chance to initialize anything before we're called,
536170531Ssam     so handle that now.  */
537170531Ssam  if (! default_init_p)
538170531Ssam    init_default_arch ();
539170531Ssam
540170531Ssam  fprintf(stream, "SPARC options:\n");
541170531Ssam  for (arch = &sparc_arch_table[0]; arch->name; arch++)
542170531Ssam    {
543138593Ssam      if (arch != &sparc_arch_table[0])
544138593Ssam	fprintf (stream, " | ");
545173275Ssam      if (arch->user_option_p)
546173275Ssam	fprintf (stream, "-A%s", arch->name);
547138593Ssam    }
548138593Ssam  fprintf (stream, "\n-xarch=v8plus | -xarch=v8plusa\n");
549138593Ssam  fprintf (stream, "\
55077218Sphk			specify variant of SPARC architecture\n\
55177218Sphk-bump			warn when assembler switches architectures\n\
55277218Sphk-sparc			ignored\n\
55377218Sphk--enforce-aligned-data	force .long, etc., to be aligned correctly\n");
554151883Sbrooks#ifdef OBJ_AOUT
55577218Sphk  fprintf (stream, "\
55677218Sphk-k			generate PIC\n");
557121827Sbrooks#endif
558178354Ssam#ifdef OBJ_ELF
55988748Sambrisko  fprintf (stream, "\
56088748Sambrisko-32			create 32 bit object file\n\
56188748Sambrisko-64			create 64 bit object file\n");
56277218Sphk  fprintf (stream, "\
56377218Sphk			[default is %d]\n", default_arch_size);
56477218Sphk  fprintf (stream, "\
565151883Sbrooks-TSO			use Total Store Ordering\n\
566151883Sbrooks-PSO			use Partial Store Ordering\n\
56777218Sphk-RMO			use Relaxed Memory Ordering\n");
56877218Sphk  fprintf (stream, "\
56977218Sphk			[default is %s]\n", (default_arch_size == 64) ? "RMO" : "TSO");
57077218Sphk  fprintf (stream, "\
571138593Ssam-KPIC			generate PIC\n\
57277218Sphk-V			print assembler version number\n\
57377218Sphk-q			ignored\n\
57477218Sphk-Qy, -Qn		ignored\n\
57577218Sphk-s			ignored\n");
57677218Sphk#endif
57777218Sphk#ifdef SPARC_BIENDIAN
57877218Sphk  fprintf (stream, "\
57977218Sphk-EL			generate code for a little endian machine\n\
58077218Sphk-EB			generate code for a big endian machine\n");
58177218Sphk#endif
58277218Sphk}
58377218Sphk
584138593Ssam/* sparc64 priviledged registers */
585170531Ssam
586170531Ssamstruct priv_reg_entry
587170531Ssam  {
588170531Ssam    char *name;
589170531Ssam    int regnum;
590170531Ssam  };
591170531Ssam
592170531Ssamstruct priv_reg_entry priv_reg_table[] =
593170531Ssam{
594170531Ssam  {"tpc", 0},
595170531Ssam  {"tnpc", 1},
596170531Ssam  {"tstate", 2},
597173275Ssam  {"tt", 3},
598138593Ssam  {"tick", 4},
599170531Ssam  {"tba", 5},
600170531Ssam  {"pstate", 6},
601170531Ssam  {"tl", 7},
602138593Ssam  {"pil", 8},
603170531Ssam  {"cwp", 9},
604166015Ssam  {"cansave", 10},
605170531Ssam  {"canrestore", 11},
606170531Ssam  {"cleanwin", 12},
607170531Ssam  {"otherwin", 13},
608170531Ssam  {"wstate", 14},
609170531Ssam  {"fq", 15},
610170531Ssam  {"ver", 31},
611170531Ssam  {"", -1},			/* end marker */
612170531Ssam};
613170531Ssam
614170531Ssam/* v9a specific asrs */
615170531Ssam
616170531Ssamstruct priv_reg_entry v9a_asr_table[] =
617170531Ssam{
618170531Ssam  {"tick_cmpr", 23},
619170531Ssam  {"softint", 22},
620170531Ssam  {"set_softint", 20},
621170531Ssam  {"pic", 17},
622170531Ssam  {"pcr", 16},
623170531Ssam  {"gsr", 19},
624170531Ssam  {"dcr", 18},
625170531Ssam  {"clear_softint", 21},
626170531Ssam  {"", -1},			/* end marker */
627170531Ssam};
628170531Ssam
629170531Ssamstatic int
630170531Ssamcmp_reg_entry (parg, qarg)
631170531Ssam     const PTR parg;
632170531Ssam     const PTR qarg;
633170531Ssam{
634170531Ssam  const struct priv_reg_entry *p = (const struct priv_reg_entry *) parg;
635170531Ssam  const struct priv_reg_entry *q = (const struct priv_reg_entry *) qarg;
636170531Ssam
637170531Ssam  return strcmp (q->name, p->name);
638173275Ssam}
639170531Ssam
640170531Ssam/* This function is called once, at assembler startup time.  It should
641170531Ssam   set up all the tables, etc. that the MD part of the assembler will need. */
642170531Ssam
643170531Ssamvoid
644170531Ssammd_begin ()
645170531Ssam{
646170531Ssam  register const char *retval = NULL;
647166015Ssam  int lose = 0;
648170531Ssam  register unsigned int i = 0;
649170531Ssam
650170531Ssam  /* We don't get a chance to initialize anything before md_parse_option
651170531Ssam     is called, and it may not be called, so handle default initialization
652170531Ssam     now if not already done.  */
653170531Ssam  if (! default_init_p)
654170531Ssam    init_default_arch ();
655170531Ssam
656170531Ssam  op_hash = hash_new ();
657170531Ssam
658170531Ssam  while (i < (unsigned int) sparc_num_opcodes)
659170531Ssam    {
660170531Ssam      const char *name = sparc_opcodes[i].name;
661170531Ssam      retval = hash_insert (op_hash, name, (PTR) &sparc_opcodes[i]);
662170531Ssam      if (retval != NULL)
663170531Ssam	{
664170531Ssam	  fprintf (stderr, "internal error: can't hash `%s': %s\n",
665170531Ssam		   sparc_opcodes[i].name, retval);
666173275Ssam	  lose = 1;
667170531Ssam	}
668165570Ssam      do
669170531Ssam	{
670170531Ssam	  if (sparc_opcodes[i].match & sparc_opcodes[i].lose)
671170531Ssam	    {
672170531Ssam	      fprintf (stderr, "internal error: losing opcode: `%s' \"%s\"\n",
673170531Ssam		       sparc_opcodes[i].name, sparc_opcodes[i].args);
674170531Ssam	      lose = 1;
675170531Ssam	    }
676170531Ssam	  ++i;
677170531Ssam	}
678170531Ssam      while (i < (unsigned int) sparc_num_opcodes
679170531Ssam	     && !strcmp (sparc_opcodes[i].name, name));
680170531Ssam    }
681170531Ssam
682170531Ssam  if (lose)
683170531Ssam    as_fatal ("Broken assembler.  No assembly attempted.");
684170531Ssam
685170531Ssam  for (i = '0'; i < '8'; ++i)
686170531Ssam    octal[i] = 1;
687170531Ssam  for (i = '0'; i <= '9'; ++i)
688173275Ssam    toHex[i] = i - '0';
689173275Ssam  for (i = 'a'; i <= 'f'; ++i)
690173275Ssam    toHex[i] = i + 10 - 'a';
691173275Ssam  for (i = 'A'; i <= 'F'; ++i)
692173275Ssam    toHex[i] = i + 10 - 'A';
693173275Ssam
694173275Ssam  qsort (priv_reg_table, sizeof (priv_reg_table) / sizeof (priv_reg_table[0]),
695173275Ssam	 sizeof (priv_reg_table[0]), cmp_reg_entry);
696173275Ssam
697173275Ssam  /* If -bump, record the architecture level at which we start issuing
698173275Ssam     warnings.  The behaviour is different depending upon whether an
699173275Ssam     architecture was explicitly specified.  If it wasn't, we issue warnings
700170531Ssam     for all upwards bumps.  If it was, we don't start issuing warnings until
701170531Ssam     we need to bump beyond the requested architecture or when we bump between
702170531Ssam     conflicting architectures.  */
703138593Ssam
704138593Ssam  if (warn_on_bump
705138593Ssam      && architecture_requested)
706186105Ssam    {
707186105Ssam      /* `max_architecture' records the requested architecture.
708186105Ssam	 Issue warnings if we go above it.  */
709186105Ssam      warn_after_architecture = max_architecture;
710186105Ssam
711186105Ssam      /* Find the highest architecture level that doesn't conflict with
712186105Ssam	 the requested one.  */
713186105Ssam      for (max_architecture = SPARC_OPCODE_ARCH_MAX;
714186105Ssam	   max_architecture > warn_after_architecture;
715186105Ssam	   --max_architecture)
716186105Ssam	if (! SPARC_OPCODE_CONFLICT_P (max_architecture,
717186105Ssam				       warn_after_architecture))
718186105Ssam	  break;
719186105Ssam    }
720186105Ssam}
721186105Ssam
722186105Ssam/* Called after all assembly has been done.  */
723186105Ssam
724186105Ssamvoid
725186105Ssamsparc_md_end ()
726186105Ssam{
727186105Ssam  if (sparc_arch_size == 64)
728186105Ssam    {
729186105Ssam      if (current_architecture == SPARC_OPCODE_ARCH_V9A)
730186105Ssam	bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v9a);
731186105Ssam      else
732186105Ssam	bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v9);
73377218Sphk    }
73477218Sphk  else
735170531Ssam    {
736170531Ssam      if (current_architecture == SPARC_OPCODE_ARCH_V9)
737186105Ssam	bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v8plus);
738170531Ssam      else if (current_architecture == SPARC_OPCODE_ARCH_V9A)
73977218Sphk	bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v8plusa);
74077218Sphk      else if (current_architecture == SPARC_OPCODE_ARCH_SPARCLET)
741138593Ssam	bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_sparclet);
742178354Ssam      else
743178354Ssam	{
744178354Ssam	  /* The sparclite is treated like a normal sparc.  Perhaps it shouldn't
745178354Ssam	     be but for now it is (since that's the way it's always been
746186105Ssam	     treated).  */
747178354Ssam	  bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc);
748178354Ssam	}
749178354Ssam    }
750178354Ssam}
751178354Ssam
752178354Ssam/* Return non-zero if VAL is in the range -(MAX+1) to MAX.  */
75377218Sphk
75477218Sphkstatic INLINE int
75577218Sphkin_signed_range (val, max)
75677218Sphk     bfd_signed_vma val, max;
75791454Sbrooks{
75877218Sphk  if (max <= 0)
75991454Sbrooks    abort ();
76077218Sphk  if (val > max)
76191454Sbrooks    return 0;
76277218Sphk  if (val < ~max)
763138593Ssam    return 0;
764138593Ssam  return 1;
765138593Ssam}
766138593Ssam
76777218Sphk/* Return non-zero if VAL is in the range 0 to MAX.  */
768150708Sru
76977218Sphkstatic INLINE int
77077218Sphkin_unsigned_range (val, max)
77177218Sphk     bfd_vma val, max;
77277218Sphk{
77377218Sphk  if (val > max)
774138593Ssam    return 0;
77577218Sphk  return 1;
77677218Sphk}
77777218Sphk
77877218Sphk/* Return non-zero if VAL is in the range -(MAX/2+1) to MAX.
77991454Sbrooks   (e.g. -15 to +31).  */
78077218Sphk
78191454Sbrooksstatic INLINE int
78277218Sphkin_bitfield_range (val, max)
78391454Sbrooks     bfd_signed_vma val, max;
78477218Sphk{
78591454Sbrooks  if (max <= 0)
78677218Sphk    abort ();
78791454Sbrooks  if (val > max)
78877218Sphk    return 0;
78977218Sphk  if (val < ~(max >> 1))
790150708Sru    return 0;
79177218Sphk  return 1;
79277218Sphk}
79377218Sphk
79477218Sphkstatic int
79577218Sphksparc_ffs (mask)
796138593Ssam     unsigned int mask;
79777218Sphk{
79877218Sphk  int i;
79977218Sphk
80077218Sphk  if (mask == 0)
80177218Sphk    return -1;
80277218Sphk
80377218Sphk  for (i = 0; (mask & 1) == 0; ++i)
80477218Sphk    mask >>= 1;
80577218Sphk  return i;
80677218Sphk}
807138593Ssam
80877218Sphk/* Implement big shift right.  */
80977218Sphkstatic bfd_vma
81077218SphkBSR (val, amount)
81177218Sphk     bfd_vma val;
81277218Sphk     int amount;
813138593Ssam{
81477218Sphk  if (sizeof (bfd_vma) <= 4 && amount >= 32)
81577218Sphk    as_fatal ("Support for 64-bit arithmetic not compiled in.");
81677218Sphk  return val >> amount;
81777218Sphk}
81891454Sbrooks
81977218Sphk/* For communication between sparc_ip and get_expression.  */
82091454Sbrooksstatic char *expr_end;
82177218Sphk
82291454Sbrooks/* For communication between md_assemble and sparc_ip.  */
82377218Sphkstatic int special_case;
82477218Sphk
825150708Sru/* Values for `special_case'.
82677218Sphk   Instructions that require wierd handling because they're longer than
82777218Sphk   4 bytes.  */
82877218Sphk#define SPECIAL_CASE_NONE	0
82977218Sphk#define	SPECIAL_CASE_SET	1
83077218Sphk#define SPECIAL_CASE_SETSW	2
831138593Ssam#define SPECIAL_CASE_SETX	3
83277218Sphk/* FIXME: sparc-opc.c doesn't have necessary "S" trigger to enable this.  */
83377218Sphk#define	SPECIAL_CASE_FDIV	4
83477218Sphk
83577218Sphk/* Bit masks of various insns.  */
83677218Sphk#define NOP_INSN 0x01000000
837139493Ssam#define OR_INSN 0x80100000
838139493Ssam#define FMOVS_INSN 0x81A00020
839139493Ssam#define SETHI_INSN 0x01000000
840139493Ssam#define SLLX_INSN 0x81281000
841139493Ssam#define SRA_INSN 0x81380000
842139493Ssam
843138593Ssam/* The last instruction to be assembled.  */
84477218Sphkstatic const struct sparc_opcode *last_insn;
84577218Sphk/* The assembled opcode of `last_insn'.  */
846139493Ssamstatic unsigned long last_opcode;
847139493Ssam
848139493Ssam/* Main entry point to assemble one instruction.  */
849139493Ssam
85077218Sphkvoid
85177218Sphkmd_assemble (str)
852138593Ssam     char *str;
85377218Sphk{
85477218Sphk  const struct sparc_opcode *insn;
85577218Sphk
85677218Sphk  know (str);
857120178Ssam  special_case = SPECIAL_CASE_NONE;
85877218Sphk  sparc_ip (str, &insn);
859178354Ssam
86077218Sphk  /* We warn about attempts to put a floating point branch in a delay slot,
86177218Sphk     unless the delay slot has been annulled.  */
86277218Sphk  if (insn != NULL
86377218Sphk      && last_insn != NULL
86477218Sphk      && (insn->flags & F_FBR) != 0
86577218Sphk      && (last_insn->flags & F_DELAYED) != 0
86677218Sphk      /* ??? This test isn't completely accurate.  We assume anything with
86777218Sphk	 F_{UNBR,CONDBR,FBR} set is annullable.  */
86877218Sphk      && ((last_insn->flags & (F_UNBR | F_CONDBR | F_FBR)) == 0
86977218Sphk	  || (last_opcode & ANNUL) == 0))
87077218Sphk    as_warn ("FP branch in delay slot");
87177218Sphk
872148686Sstefanf  /* SPARC before v9 requires a nop instruction between a floating
873148686Sstefanf     point instruction and a floating point branch.  We insert one
87477218Sphk     automatically, with a warning.  */
87577218Sphk  if (max_architecture < SPARC_OPCODE_ARCH_V9
876138593Ssam      && insn != NULL
87777218Sphk      && last_insn != NULL
87877218Sphk      && (insn->flags & F_FBR) != 0
87977218Sphk      && (last_insn->flags & F_FLOAT) != 0)
88077218Sphk    {
881120178Ssam      struct sparc_it nop_insn;
88277218Sphk
88377218Sphk      nop_insn.opcode = NOP_INSN;
88477218Sphk      nop_insn.reloc = BFD_RELOC_NONE;
885178354Ssam      output_insn (insn, &nop_insn);
88677218Sphk      as_warn ("FP branch preceded by FP instruction; NOP inserted");
88777218Sphk    }
88877218Sphk
88991454Sbrooks  switch (special_case)
89077218Sphk    {
89177218Sphk    case SPECIAL_CASE_NONE:
89277218Sphk      /* normal insn */
893151827Sbrooks      output_insn (insn, &the_insn);
894151827Sbrooks      break;
89577218Sphk
89677218Sphk    case SPECIAL_CASE_SET:
89777218Sphk      {
89877218Sphk	int need_hi22_p = 0;
89977218Sphk
90077218Sphk	/* "set" is not defined for negative numbers in v9: it doesn't yield
90177218Sphk	   what you expect it to.  */
90277218Sphk	if (SPARC_OPCODE_ARCH_V9_P (max_architecture)
90377218Sphk	    && the_insn.exp.X_op == O_constant)
90477218Sphk	  {
90577218Sphk	    if (the_insn.exp.X_add_number < 0)
90677218Sphk	      as_warn ("set: used with negative number");
90791454Sbrooks	    else if (the_insn.exp.X_add_number > (offsetT) 0xffffffff)
90877218Sphk	      as_warn ("set: number larger than 4294967295");
90977218Sphk	  }
91077218Sphk
91177218Sphk	/* See if operand is absolute and small; skip sethi if so.  */
91277218Sphk	if (the_insn.exp.X_op != O_constant
91377218Sphk	    || the_insn.exp.X_add_number >= (1 << 12)
914138593Ssam	    || the_insn.exp.X_add_number < -(1 << 12))
915127649Ssam	  {
916127649Ssam	    output_insn (insn, &the_insn);
917148416Ssam	    need_hi22_p = 1;
918148416Ssam	  }
919127649Ssam	/* See if operand has no low-order bits; skip OR if so.  */
920127649Ssam	if (the_insn.exp.X_op != O_constant
921138593Ssam	    || (need_hi22_p && (the_insn.exp.X_add_number & 0x3FF) != 0)
922127649Ssam	    || ! need_hi22_p)
923127649Ssam	  {
924127649Ssam	    int rd = (the_insn.opcode & RD (~0)) >> 25;
925127649Ssam	    the_insn.opcode = (OR_INSN | (need_hi22_p ? RS1 (rd) : 0)
926127649Ssam			       | RD (rd)
927127649Ssam			       | IMMED
928127649Ssam			       | (the_insn.exp.X_add_number
929127649Ssam				  & (need_hi22_p ? 0x3ff : 0x1fff)));
930173275Ssam	    the_insn.reloc = (the_insn.exp.X_op != O_constant
931127649Ssam			      ? BFD_RELOC_LO10
932127649Ssam			      : BFD_RELOC_NONE);
933150708Sru	    output_insn (insn, &the_insn);
934127649Ssam	  }
935127649Ssam	break;
936127649Ssam      }
937127649Ssam
938127649Ssam    case SPECIAL_CASE_SETSW:
939138593Ssam      {
940173275Ssam	/* FIXME: Not finished.  */
941173275Ssam	break;
942173275Ssam      }
943173275Ssam
944173275Ssam    case SPECIAL_CASE_SETX:
945173275Ssam      {
946173275Ssam#define SIGNEXT32(x) ((((x) & 0xffffffff) ^ 0x80000000) - 0x80000000)
947173275Ssam	int upper32 = SIGNEXT32 (BSR (the_insn.exp.X_add_number, 32));
948173275Ssam	int lower32 = SIGNEXT32 (the_insn.exp.X_add_number);
949173275Ssam#undef SIGNEXT32
950173275Ssam	int tmpreg = (the_insn.opcode & RS1 (~0)) >> 14;
951173275Ssam	int dstreg = (the_insn.opcode & RD (~0)) >> 25;
952173275Ssam	/* Output directly to dst reg if lower 32 bits are all zero.  */
953173275Ssam	int upper_dstreg = (the_insn.exp.X_op == O_constant
954173275Ssam			    && lower32 == 0) ? dstreg : tmpreg;
955173275Ssam	int need_hh22_p = 0, need_hm10_p = 0, need_hi22_p = 0, need_lo10_p = 0;
956127649Ssam
957127649Ssam	/* The tmp reg should not be the dst reg.  */
958173275Ssam	if (tmpreg == dstreg)
959173275Ssam	  as_warn ("setx: temporary register same as destination register");
960173275Ssam
961173275Ssam	/* Reset X_add_number, we've extracted it as upper32/lower32.
962173275Ssam	   Otherwise fixup_segment will complain about not being able to
963173275Ssam	   write an 8 byte number in a 4 byte field.  */
964173275Ssam	the_insn.exp.X_add_number = 0;
965127649Ssam
966127649Ssam	/* ??? Obviously there are other optimizations we can do
967138593Ssam	   (e.g. sethi+shift for 0x1f0000000) and perhaps we shouldn't be
968138593Ssam	   doing some of these.  Later.  If you do change things, try to
969138593Ssam	   change all of this to be table driven as well.  */
970138593Ssam
971138593Ssam	/* What to output depends on the number if it's constant.
972138593Ssam	   Compute that first, then output what we've decided upon.  */
97377218Sphk	if (the_insn.exp.X_op != O_constant)
974138593Ssam	  need_hh22_p = need_hm10_p = need_hi22_p = need_lo10_p = 1;
97577218Sphk	else
976138593Ssam	  {
977138593Ssam	    /* Only need hh22 if `or' insn can't handle constant.  */
978138593Ssam	    if (upper32 < -(1 << 12) || upper32 >= (1 << 12))
979138593Ssam	      need_hh22_p = 1;
980138593Ssam
981138593Ssam	    /* Does bottom part (after sethi) have bits?  */
982138593Ssam	    if ((need_hh22_p && (upper32 & 0x3ff) != 0)
983150708Sru		/* No hh22, but does upper32 still have bits we can't set
984138593Ssam		   from lower32?  */
985138593Ssam		|| (! need_hh22_p
986138593Ssam		    && upper32 != 0
987138593Ssam		    && (upper32 != -1 || lower32 >= 0)))
988138593Ssam	      need_hm10_p = 1;
989138593Ssam
990138593Ssam	    /* If the lower half is all zero, we build the upper half directly
991138593Ssam	       into the dst reg.  */
992138593Ssam	    if (lower32 != 0
993138593Ssam		/* Need lower half if number is zero.  */
994138593Ssam		|| (! need_hh22_p && ! need_hm10_p))
995138593Ssam	      {
996138593Ssam		/* No need for sethi if `or' insn can handle constant.  */
997138593Ssam		if (lower32 < -(1 << 12) || lower32 >= (1 << 12)
998138593Ssam		    /* Note that we can't use a negative constant in the `or'
999138593Ssam		       insn unless the upper 32 bits are all ones.  */
1000138593Ssam		    || (lower32 < 0 && upper32 != -1))
1001138593Ssam		  need_hi22_p = 1;
1002138593Ssam
1003138593Ssam		/* Does bottom part (after sethi) have bits?  */
1004138593Ssam		if ((need_hi22_p && (lower32 & 0x3ff) != 0)
1005138593Ssam		    /* No sethi.  */
1006138593Ssam		    || (! need_hi22_p && (lower32 & 0x1fff) != 0)
1007170531Ssam		    /* Need `or' if we didn't set anything else.  */
1008170531Ssam		    || (! need_hi22_p && ! need_hh22_p && ! need_hm10_p))
1009170531Ssam		  need_lo10_p = 1;
1010170531Ssam	      }
1011170531Ssam	  }
1012170531Ssam
1013170531Ssam	if (need_hh22_p)
1014170531Ssam	  {
1015170531Ssam	    the_insn.opcode = (SETHI_INSN | RD (upper_dstreg)
1016170531Ssam			       | ((upper32 >> 10) & 0x3fffff));
1017170531Ssam	    the_insn.reloc = (the_insn.exp.X_op != O_constant
1018170531Ssam			      ? BFD_RELOC_SPARC_HH22 : BFD_RELOC_NONE);
1019138593Ssam	    output_insn (insn, &the_insn);
1020138593Ssam	  }
1021138593Ssam
1022138593Ssam	if (need_hm10_p)
1023138593Ssam	  {
1024138593Ssam	    the_insn.opcode = (OR_INSN
1025138593Ssam			       | (need_hh22_p ? RS1 (upper_dstreg) : 0)
1026138593Ssam			       | RD (upper_dstreg)
1027138593Ssam			       | IMMED
1028138593Ssam			       | (upper32
1029138593Ssam				  & (need_hh22_p ? 0x3ff : 0x1fff)));
1030138593Ssam	    the_insn.reloc = (the_insn.exp.X_op != O_constant
1031173275Ssam			      ? BFD_RELOC_SPARC_HM10 : BFD_RELOC_NONE);
1032138593Ssam	    output_insn (insn, &the_insn);
1033138593Ssam	  }
1034138593Ssam
1035138593Ssam	if (need_hi22_p)
1036138593Ssam	  {
1037138593Ssam	    the_insn.opcode = (SETHI_INSN | RD (dstreg)
1038187801Ssam			       | ((lower32 >> 10) & 0x3fffff));
1039188038Sdelphij	    the_insn.reloc = BFD_RELOC_HI22;
1040187801Ssam	    output_insn (insn, &the_insn);
1041138593Ssam	  }
1042138593Ssam
1043138593Ssam	if (need_lo10_p)
1044187801Ssam	  {
1045188038Sdelphij	    /* FIXME: One nice optimization to do here is to OR the low part
1046187801Ssam	       with the highpart if hi22 isn't needed and the low part is
1047187801Ssam	       positive.  */
1048188038Sdelphij	    the_insn.opcode = (OR_INSN | (need_hi22_p ? RS1 (dstreg) : 0)
1049187801Ssam			       | RD (dstreg)
1050138593Ssam			       | IMMED
1051138593Ssam			       | (lower32
1052138593Ssam				  & (need_hi22_p ? 0x3ff : 0x1fff)));
1053138593Ssam	    the_insn.reloc = BFD_RELOC_LO10;
1054138593Ssam	    output_insn (insn, &the_insn);
1055138593Ssam	  }
1056138593Ssam
1057138593Ssam	/* If we needed to build the upper part, shift it into place.  */
1058138593Ssam	if (need_hh22_p || need_hm10_p)
1059173275Ssam	  {
1060173275Ssam	    the_insn.opcode = (SLLX_INSN | RS1 (upper_dstreg) | RD (upper_dstreg)
1061138593Ssam			       | IMMED | 32);
1062173275Ssam	    the_insn.reloc = BFD_RELOC_NONE;
1063138593Ssam	    output_insn (insn, &the_insn);
1064138593Ssam	  }
1065138593Ssam
1066170531Ssam	/* If we needed to build both upper and lower parts, OR them together.  */
1067138593Ssam	if ((need_hh22_p || need_hm10_p)
1068138593Ssam	    && (need_hi22_p || need_lo10_p))
1069138593Ssam	  {
1070138593Ssam	    the_insn.opcode = (OR_INSN | RS1 (dstreg) | RS2 (upper_dstreg)
1071138593Ssam			       | RD (dstreg));
1072138593Ssam	    the_insn.reloc = BFD_RELOC_NONE;
1073138593Ssam	    output_insn (insn, &the_insn);
1074138593Ssam	  }
1075138593Ssam	/* We didn't need both regs, but we may have to sign extend lower32.  */
1076138593Ssam	else if (need_hi22_p && upper32 == -1)
1077155702Ssam	  {
1078138593Ssam	    the_insn.opcode = (SRA_INSN | RS1 (dstreg) | RD (dstreg)
1079138593Ssam			       | IMMED | 0);
1080138593Ssam	    the_insn.reloc = BFD_RELOC_NONE;
1081138593Ssam	    output_insn (insn, &the_insn);
1082138593Ssam	  }
1083138593Ssam	break;
1084138593Ssam      }
1085138593Ssam
1086138593Ssam    case SPECIAL_CASE_FDIV:
1087138593Ssam      {
1088138593Ssam	int rd = (the_insn.opcode >> 25) & 0x1f;
1089138593Ssam
1090138593Ssam	output_insn (insn, &the_insn);
1091138593Ssam
1092138593Ssam	/* According to information leaked from Sun, the "fdiv" instructions
1093138593Ssam	   on early SPARC machines would produce incorrect results sometimes.
1094138593Ssam	   The workaround is to add an fmovs of the destination register to
1095138593Ssam	   itself just after the instruction.  This was true on machines
1096138593Ssam	   with Weitek 1165 float chips, such as the Sun-4/260 and /280. */
1097138593Ssam	assert (the_insn.reloc == BFD_RELOC_NONE);
1098138593Ssam	the_insn.opcode = FMOVS_INSN | rd | RD (rd);
1099138593Ssam	output_insn (insn, &the_insn);
1100138593Ssam	break;
1101138593Ssam      }
1102138593Ssam
1103138593Ssam    default:
1104138593Ssam      as_fatal ("failed special case insn sanity check");
1105138593Ssam    }
1106138593Ssam}
1107138593Ssam
1108138593Ssam/* Subroutine of md_assemble to do the actual parsing.  */
1109138593Ssam
1110138593Ssamstatic void
1111138593Ssamsparc_ip (str, pinsn)
1112138593Ssam     char *str;
1113138593Ssam     const struct sparc_opcode **pinsn;
1114138593Ssam{
1115138593Ssam  char *error_message = "";
1116138593Ssam  char *s;
1117138593Ssam  const char *args;
1118138593Ssam  char c;
1119138593Ssam  const struct sparc_opcode *insn;
1120138593Ssam  char *argsStart;
1121138593Ssam  unsigned long opcode;
1122138593Ssam  unsigned int mask = 0;
1123138593Ssam  int match = 0;
1124138593Ssam  int comma = 0;
1125138593Ssam  int v9_arg_p;
1126138593Ssam
1127138593Ssam  for (s = str; islower ((unsigned char) *s) || (*s >= '0' && *s <= '3'); ++s)
1128138593Ssam    ;
1129138593Ssam
1130138593Ssam  switch (*s)
1131138593Ssam    {
1132138593Ssam    case '\0':
1133138593Ssam      break;
1134138593Ssam
1135138593Ssam    case ',':
1136148621Ssam      comma = 1;
1137138593Ssam
1138148621Ssam      /*FALLTHROUGH */
1139138593Ssam
1140148621Ssam    case ' ':
1141148621Ssam      *s++ = '\0';
1142148621Ssam      break;
1143148621Ssam
1144148621Ssam    default:
1145138593Ssam      as_fatal ("Unknown opcode: `%s'", str);
1146138593Ssam    }
1147148621Ssam  insn = (struct sparc_opcode *) hash_find (op_hash, str);
1148138593Ssam  *pinsn = insn;
1149148621Ssam  if (insn == NULL)
1150138593Ssam    {
1151148621Ssam      as_bad ("Unknown opcode: `%s'", str);
1152148621Ssam      return;
1153148621Ssam    }
1154148621Ssam  if (comma)
1155148621Ssam    {
1156138593Ssam      *--s = ',';
1157138593Ssam    }
1158138593Ssam
1159138593Ssam  argsStart = s;
1160138593Ssam  for (;;)
1161138593Ssam    {
1162138593Ssam      opcode = insn->match;
1163138593Ssam      memset (&the_insn, '\0', sizeof (the_insn));
1164138593Ssam      the_insn.reloc = BFD_RELOC_NONE;
1165138593Ssam      v9_arg_p = 0;
1166138593Ssam
1167138593Ssam      /*
1168138593Ssam       * Build the opcode, checking as we go to make
1169138593Ssam       * sure that the operands match
1170138593Ssam       */
1171138593Ssam      for (args = insn->args;; ++args)
1172138593Ssam	{
1173138593Ssam	  switch (*args)
1174138593Ssam	    {
1175138593Ssam	    case 'K':
1176138593Ssam	      {
1177138593Ssam		int kmask = 0;
1178138593Ssam
1179138593Ssam		/* Parse a series of masks.  */
1180138593Ssam		if (*s == '#')
1181138593Ssam		  {
1182138593Ssam		    while (*s == '#')
1183138593Ssam		      {
1184138593Ssam			int mask;
1185138593Ssam
1186138593Ssam			if (! parse_keyword_arg (sparc_encode_membar, &s,
1187138593Ssam						 &mask))
1188138593Ssam			  {
1189138593Ssam			    error_message = ": invalid membar mask name";
1190138593Ssam			    goto error;
1191138593Ssam			  }
1192138593Ssam			kmask |= mask;
1193138593Ssam			while (*s == ' ') { ++s; continue; }
1194138593Ssam			if (*s == '|' || *s == '+')
1195138593Ssam			  ++s;
1196138593Ssam			while (*s == ' ') { ++s; continue; }
1197138593Ssam		      }
1198138593Ssam		  }
1199138593Ssam		else
1200138593Ssam		  {
1201138593Ssam		    if (! parse_const_expr_arg (&s, &kmask))
1202138593Ssam		      {
1203155702Ssam			error_message = ": invalid membar mask expression";
1204138593Ssam			goto error;
1205138593Ssam		      }
1206138593Ssam		    if (kmask < 0 || kmask > 127)
1207138593Ssam		      {
1208138593Ssam			error_message = ": invalid membar mask number";
1209138593Ssam			goto error;
1210138593Ssam		      }
1211138593Ssam		  }
1212138593Ssam
1213138593Ssam		opcode |= MEMBAR (kmask);
1214138593Ssam		continue;
1215138593Ssam	      }
1216138593Ssam
1217138593Ssam	    case '*':
1218138593Ssam	      {
1219138593Ssam		int fcn = 0;
1220138593Ssam
1221138593Ssam		/* Parse a prefetch function.  */
1222138593Ssam		if (*s == '#')
1223138593Ssam		  {
1224138593Ssam		    if (! parse_keyword_arg (sparc_encode_prefetch, &s, &fcn))
1225138593Ssam		      {
1226138593Ssam			error_message = ": invalid prefetch function name";
1227138593Ssam			goto error;
1228138593Ssam		      }
1229149029Ssam		  }
1230149029Ssam		else
1231149029Ssam		  {
1232149029Ssam		    if (! parse_const_expr_arg (&s, &fcn))
1233149029Ssam		      {
1234149029Ssam			error_message = ": invalid prefetch function expression";
1235155702Ssam			goto error;
1236149029Ssam		      }
1237149029Ssam		    if (fcn < 0 || fcn > 31)
1238149029Ssam		      {
1239149029Ssam			error_message = ": invalid prefetch function number";
1240149029Ssam			goto error;
1241149029Ssam		      }
1242149029Ssam		  }
1243149029Ssam		opcode |= RD (fcn);
1244149029Ssam		continue;
1245149029Ssam	      }
1246149029Ssam
1247149029Ssam	    case '!':
1248149029Ssam	    case '?':
1249170531Ssam	      /* Parse a sparc64 privileged register.  */
1250149029Ssam	      if (*s == '%')
1251149029Ssam		{
1252149029Ssam		  struct priv_reg_entry *p = priv_reg_table;
1253138593Ssam		  unsigned int len = 9999999; /* init to make gcc happy */
1254138593Ssam
1255138593Ssam		  s += 1;
1256138593Ssam		  while (p->name[0] > s[0])
1257138593Ssam		    p++;
1258147795Ssam		  while (p->name[0] == s[0])
1259147795Ssam		    {
1260147795Ssam		      len = strlen (p->name);
1261147795Ssam		      if (strncmp (p->name, s, len) == 0)
1262147795Ssam			break;
1263147795Ssam		      p++;
1264153422Ssam		    }
1265170531Ssam		  if (p->name[0] != s[0])
1266153422Ssam		    {
1267170531Ssam		      error_message = ": unrecognizable privileged register";
1268153422Ssam		      goto error;
1269153422Ssam		    }
1270148416Ssam		  if (*args == '?')
1271170531Ssam		    opcode |= (p->regnum << 14);
1272170531Ssam		  else
1273170531Ssam		    opcode |= (p->regnum << 25);
1274170531Ssam		  s += len;
1275170531Ssam		  continue;
1276170531Ssam		}
1277170531Ssam	      else
1278170531Ssam		{
1279170531Ssam		  error_message = ": unrecognizable privileged register";
1280170531Ssam		  goto error;
1281170531Ssam		}
1282170531Ssam
1283170531Ssam	    case '_':
1284170531Ssam	    case '/':
1285170531Ssam	      /* Parse a v9a ancillary state register.  */
1286170531Ssam	      if (*s == '%')
1287170531Ssam		{
1288178354Ssam		  struct priv_reg_entry *p = v9a_asr_table;
1289178354Ssam		  unsigned int len = 9999999; /* init to make gcc happy */
1290178354Ssam
1291178354Ssam		  s += 1;
1292178354Ssam		  while (p->name[0] > s[0])
1293178354Ssam		    p++;
1294178354Ssam		  while (p->name[0] == s[0])
1295178354Ssam		    {
1296178354Ssam		      len = strlen (p->name);
1297178354Ssam		      if (strncmp (p->name, s, len) == 0)
1298178354Ssam			break;
1299178354Ssam		      p++;
1300170531Ssam		    }
1301178354Ssam		  if (p->name[0] != s[0])
1302178354Ssam		    {
1303178354Ssam		      error_message = ": unrecognizable v9a ancillary state register";
1304178354Ssam		      goto error;
1305178354Ssam		    }
1306178354Ssam		  if (*args == '/' && (p->regnum == 20 || p->regnum == 21))
1307178354Ssam		    {
1308178354Ssam		      error_message = ": rd on write only ancillary state register";
1309178354Ssam		      goto error;
1310178354Ssam		    }
1311178354Ssam		  if (*args == '/')
1312178354Ssam		    opcode |= (p->regnum << 14);
1313178354Ssam		  else
1314178354Ssam		    opcode |= (p->regnum << 25);
1315178354Ssam		  s += len;
1316178354Ssam		  continue;
1317178354Ssam		}
1318178354Ssam	      else
1319178354Ssam		{
1320178354Ssam		  error_message = ": unrecognizable v9a ancillary state register";
1321178354Ssam		  goto error;
1322178354Ssam		}
1323178354Ssam
1324178354Ssam	    case 'M':
1325178354Ssam	    case 'm':
1326178354Ssam	      if (strncmp (s, "%asr", 4) == 0)
1327178354Ssam		{
1328178354Ssam		  s += 4;
1329178354Ssam
1330178354Ssam		  if (isdigit ((unsigned char) *s))
1331178354Ssam		    {
1332178354Ssam		      long num = 0;
1333178354Ssam
1334178354Ssam		      while (isdigit ((unsigned char) *s))
1335178354Ssam			{
1336178354Ssam			  num = num * 10 + *s - '0';
1337188784Ssam			  ++s;
1338188784Ssam			}
1339188784Ssam
1340188784Ssam		      if (current_architecture >= SPARC_OPCODE_ARCH_V9)
1341188784Ssam			{
1342188784Ssam			  if (num < 16 || 31 < num)
1343178354Ssam			    {
1344178354Ssam			      error_message = ": asr number must be between 16 and 31";
1345178354Ssam			      goto error;
1346178354Ssam			    }
1347178354Ssam			}
1348178354Ssam		      else
1349178354Ssam			{
1350170531Ssam			  if (num < 0 || 31 < num)
1351170531Ssam			    {
1352178354Ssam			      error_message = ": asr number must be between 0 and 31";
1353178354Ssam			      goto error;
1354178354Ssam			    }
1355178354Ssam			}
1356178354Ssam
1357178354Ssam		      opcode |= (*args == 'M' ? RS1 (num) : RD (num));
1358178354Ssam		      continue;
1359178354Ssam		    }
1360178354Ssam		  else
1361178354Ssam		    {
1362178354Ssam		      error_message = ": expecting %asrN";
1363178354Ssam		      goto error;
1364178354Ssam		    }
1365178354Ssam		} /* if %asr */
1366178354Ssam	      break;
1367178354Ssam
1368178354Ssam	    case 'I':
1369178354Ssam	      the_insn.reloc = BFD_RELOC_SPARC_11;
1370178354Ssam	      goto immediate;
1371178354Ssam
1372178354Ssam	    case 'j':
1373178354Ssam	      the_insn.reloc = BFD_RELOC_SPARC_10;
1374178354Ssam	      goto immediate;
1375178354Ssam
1376178354Ssam	    case 'X':
1377178354Ssam	      /* V8 systems don't understand BFD_RELOC_SPARC_5.  */
1378178354Ssam	      if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
1379178354Ssam		the_insn.reloc = BFD_RELOC_SPARC_5;
1380178354Ssam	      else
1381178354Ssam		the_insn.reloc = BFD_RELOC_SPARC13;
1382188784Ssam	      /* These fields are unsigned, but for upward compatibility,
1383188784Ssam		 allow negative values as well.  */
1384188784Ssam	      goto immediate;
1385188784Ssam
1386178354Ssam	    case 'Y':
1387178354Ssam	      /* V8 systems don't understand BFD_RELOC_SPARC_6.  */
1388178354Ssam	      if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
1389178354Ssam		the_insn.reloc = BFD_RELOC_SPARC_6;
1390178354Ssam	      else
1391178354Ssam		the_insn.reloc = BFD_RELOC_SPARC13;
1392178354Ssam	      /* These fields are unsigned, but for upward compatibility,
1393178354Ssam		 allow negative values as well.  */
1394178354Ssam	      goto immediate;
1395178354Ssam
1396178354Ssam	    case 'k':
1397178354Ssam	      the_insn.reloc = /* RELOC_WDISP2_14 */ BFD_RELOC_SPARC_WDISP16;
1398178354Ssam	      the_insn.pcrel = 1;
1399188784Ssam	      goto immediate;
1400188784Ssam
1401188784Ssam	    case 'G':
1402188784Ssam	      the_insn.reloc = BFD_RELOC_SPARC_WDISP19;
1403178354Ssam	      the_insn.pcrel = 1;
1404178354Ssam	      goto immediate;
1405178354Ssam
1406178354Ssam	    case 'N':
1407178354Ssam	      if (*s == 'p' && s[1] == 'n')
1408178354Ssam		{
1409178354Ssam		  s += 2;
1410178354Ssam		  continue;
1411178354Ssam		}
1412188784Ssam	      break;
1413178354Ssam
1414188784Ssam	    case 'T':
1415178354Ssam	      if (*s == 'p' && s[1] == 't')
1416178354Ssam		{
1417178354Ssam		  s += 2;
1418188784Ssam		  continue;
1419188784Ssam		}
1420188784Ssam	      break;
1421178354Ssam
1422178354Ssam	    case 'z':
1423170531Ssam	      if (*s == ' ')
1424178354Ssam		{
1425170531Ssam		  ++s;
1426178354Ssam		}
1427178354Ssam	      if (strncmp (s, "%icc", 4) == 0)
1428178354Ssam		{
1429178354Ssam		  s += 4;
1430178354Ssam		  continue;
1431178354Ssam		}
1432178354Ssam	      break;
1433178354Ssam
1434178354Ssam	    case 'Z':
1435178354Ssam	      if (*s == ' ')
1436178354Ssam		{
1437178354Ssam		  ++s;
1438178354Ssam		}
1439178354Ssam	      if (strncmp (s, "%xcc", 4) == 0)
1440170531Ssam		{
1441170531Ssam		  s += 4;
1442188784Ssam		  continue;
1443188784Ssam		}
1444188784Ssam	      break;
1445188784Ssam
1446188784Ssam	    case '6':
1447188784Ssam	      if (*s == ' ')
1448188784Ssam		{
1449188784Ssam		  ++s;
1450188784Ssam		}
1451188784Ssam	      if (strncmp (s, "%fcc0", 5) == 0)
1452188784Ssam		{
1453188784Ssam		  s += 5;
1454170531Ssam		  continue;
1455178354Ssam		}
1456170531Ssam	      break;
1457188784Ssam
1458178354Ssam	    case '7':
1459188784Ssam	      if (*s == ' ')
1460178354Ssam		{
1461178354Ssam		  ++s;
1462178354Ssam		}
1463178354Ssam	      if (strncmp (s, "%fcc1", 5) == 0)
1464188784Ssam		{
1465178354Ssam		  s += 5;
1466188784Ssam		  continue;
1467178354Ssam		}
1468170531Ssam	      break;
1469170531Ssam
1470170531Ssam	    case '8':
1471178354Ssam	      if (*s == ' ')
1472170531Ssam		{
1473188784Ssam		  ++s;
1474178354Ssam		}
1475188784Ssam	      if (strncmp (s, "%fcc2", 5) == 0)
1476178354Ssam		{
1477178354Ssam		  s += 5;
1478178354Ssam		  continue;
1479178354Ssam		}
1480188784Ssam	      break;
1481178354Ssam
1482188784Ssam	    case '9':
1483178354Ssam	      if (*s == ' ')
1484170531Ssam		{
1485170531Ssam		  ++s;
1486170531Ssam		}
1487178354Ssam	      if (strncmp (s, "%fcc3", 5) == 0)
1488170531Ssam		{
1489188784Ssam		  s += 5;
1490178354Ssam		  continue;
1491188784Ssam		}
1492178354Ssam	      break;
1493178354Ssam
1494178354Ssam	    case 'P':
1495178354Ssam	      if (strncmp (s, "%pc", 3) == 0)
1496188784Ssam		{
1497178354Ssam		  s += 3;
1498188784Ssam		  continue;
1499178354Ssam		}
1500170531Ssam	      break;
1501170531Ssam
1502170531Ssam	    case 'W':
1503178354Ssam	      if (strncmp (s, "%tick", 5) == 0)
1504170531Ssam		{
1505188784Ssam		  s += 5;
1506178354Ssam		  continue;
1507178354Ssam		}
1508178354Ssam	      break;
1509178354Ssam
1510178354Ssam	    case '\0':		/* end of args */
1511178354Ssam	      if (*s == '\0')
1512178354Ssam		{
1513178354Ssam		  match = 1;
1514178354Ssam		}
1515178354Ssam	      break;
1516178354Ssam
1517178354Ssam	    case '+':
1518188784Ssam	      if (*s == '+')
1519178354Ssam		{
1520178354Ssam		  ++s;
1521188784Ssam		  continue;
1522178354Ssam		}
1523188784Ssam	      if (*s == '-')
1524178354Ssam		{
1525178354Ssam		  continue;
1526170531Ssam		}
1527170531Ssam	      break;
1528170531Ssam
1529178354Ssam	    case '[':		/* these must match exactly */
1530153354Ssam	    case ']':
1531178354Ssam	    case ',':
1532178354Ssam	    case ' ':
1533178354Ssam	      if (*s++ == *args)
1534178354Ssam		continue;
1535178354Ssam	      break;
1536178354Ssam
1537178354Ssam	    case '#':		/* must be at least one digit */
1538178354Ssam	      if (isdigit ((unsigned char) *s++))
1539178354Ssam		{
1540178354Ssam		  while (isdigit ((unsigned char) *s))
1541153354Ssam		    {
1542178354Ssam		      ++s;
1543178354Ssam		    }
1544178354Ssam		  continue;
1545178354Ssam		}
1546153354Ssam	      break;
1547153354Ssam
1548148416Ssam	    case 'C':		/* coprocessor state register */
1549148416Ssam	      if (strncmp (s, "%csr", 4) == 0)
1550148416Ssam		{
1551148416Ssam		  s += 4;
1552148416Ssam		  continue;
1553148416Ssam		}
1554160687Ssam	      break;
1555160687Ssam
1556160687Ssam	    case 'b':		/* next operand is a coprocessor register */
1557160687Ssam	    case 'c':
1558160687Ssam	    case 'D':
1559160687Ssam	      if (*s++ == '%' && *s++ == 'c' && isdigit ((unsigned char) *s))
1560160687Ssam		{
1561170531Ssam		  mask = *s++;
1562170531Ssam		  if (isdigit ((unsigned char) *s))
1563170531Ssam		    {
1564170531Ssam		      mask = 10 * (mask - '0') + (*s++ - '0');
1565170531Ssam		      if (mask >= 32)
1566170531Ssam			{
1567170531Ssam			  break;
1568170531Ssam			}
1569170531Ssam		    }
1570170531Ssam		  else
1571170531Ssam		    {
1572170531Ssam		      mask -= '0';
1573173275Ssam		    }
1574178354Ssam		  switch (*args)
1575178354Ssam		    {
1576178354Ssam
1577178354Ssam		    case 'b':
1578178354Ssam		      opcode |= mask << 14;
1579178354Ssam		      continue;
1580173275Ssam
1581173275Ssam		    case 'c':
1582173275Ssam		      opcode |= mask;
1583173275Ssam		      continue;
1584173275Ssam
1585173275Ssam		    case 'D':
1586173275Ssam		      opcode |= mask << 25;
1587173275Ssam		      continue;
1588173275Ssam		    }
1589173275Ssam		}
1590173275Ssam	      break;
1591173275Ssam
1592173275Ssam	    case 'r':		/* next operand must be a register */
1593173275Ssam	    case 'O':
1594173275Ssam	    case '1':
1595173275Ssam	    case '2':
1596173275Ssam	    case 'd':
1597173275Ssam	      if (*s++ == '%')
1598173275Ssam		{
1599173275Ssam		  switch (c = *s++)
1600173275Ssam		    {
1601173275Ssam
1602173275Ssam		    case 'f':	/* frame pointer */
1603173275Ssam		      if (*s++ == 'p')
1604173275Ssam			{
1605173275Ssam			  mask = 0x1e;
1606173275Ssam			  break;
1607173275Ssam			}
1608173275Ssam		      goto error;
1609173275Ssam
1610173275Ssam		    case 'g':	/* global register */
1611173275Ssam		      if (isoctal (c = *s++))
1612173275Ssam			{
1613173275Ssam			  mask = c - '0';
1614173275Ssam			  break;
1615173275Ssam			}
1616173275Ssam		      goto error;
1617173275Ssam
1618173275Ssam		    case 'i':	/* in register */
1619173275Ssam		      if (isoctal (c = *s++))
1620173275Ssam			{
1621173275Ssam			  mask = c - '0' + 24;
1622173275Ssam			  break;
1623173275Ssam			}
1624173275Ssam		      goto error;
1625173275Ssam
1626173275Ssam		    case 'l':	/* local register */
1627173275Ssam		      if (isoctal (c = *s++))
1628173275Ssam			{
1629173275Ssam			  mask = (c - '0' + 16);
1630173275Ssam			  break;
1631173275Ssam			}
1632173275Ssam		      goto error;
1633173275Ssam
1634173275Ssam		    case 'o':	/* out register */
1635183260Ssam		      if (isoctal (c = *s++))
1636173275Ssam			{
1637173275Ssam			  mask = (c - '0' + 8);
1638173275Ssam			  break;
1639173275Ssam			}
1640173275Ssam		      goto error;
1641173275Ssam
1642173275Ssam		    case 's':	/* stack pointer */
1643173275Ssam		      if (*s++ == 'p')
1644173275Ssam			{
1645173275Ssam			  mask = 0xe;
1646173275Ssam			  break;
1647173275Ssam			}
1648173275Ssam		      goto error;
1649173275Ssam
1650173275Ssam		    case 'r':	/* any register */
1651173275Ssam		      if (!isdigit ((unsigned char) (c = *s++)))
1652173275Ssam			{
1653173275Ssam			  goto error;
1654173275Ssam			}
1655173275Ssam		      /* FALLTHROUGH */
1656173275Ssam		    case '0':
1657173275Ssam		    case '1':
1658173275Ssam		    case '2':
1659173275Ssam		    case '3':
1660173275Ssam		    case '4':
1661173275Ssam		    case '5':
1662173275Ssam		    case '6':
1663173275Ssam		    case '7':
1664173275Ssam		    case '8':
1665173275Ssam		    case '9':
1666173275Ssam		      if (isdigit ((unsigned char) *s))
1667173275Ssam			{
1668173275Ssam			  if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32)
1669173275Ssam			    {
1670173275Ssam			      goto error;
1671173275Ssam			    }
1672173275Ssam			}
1673173275Ssam		      else
1674187801Ssam			{
1675173275Ssam			  c -= '0';
1676173275Ssam			}
1677173275Ssam		      mask = c;
1678173275Ssam		      break;
1679173275Ssam
1680173275Ssam		    default:
1681173275Ssam		      goto error;
1682173275Ssam		    }
1683173275Ssam
1684173275Ssam		  /* Got the register, now figure out where
1685173275Ssam		     it goes in the opcode.  */
1686173275Ssam		  switch (*args)
1687173275Ssam		    {
1688173275Ssam		    case '1':
1689173275Ssam		      opcode |= mask << 14;
1690173275Ssam		      continue;
1691173275Ssam
1692173275Ssam		    case '2':
1693173275Ssam		      opcode |= mask;
1694173275Ssam		      continue;
1695173275Ssam
1696173275Ssam		    case 'd':
1697173275Ssam		      opcode |= mask << 25;
1698173275Ssam		      continue;
1699173275Ssam
1700173275Ssam		    case 'r':
1701173275Ssam		      opcode |= (mask << 25) | (mask << 14);
1702173275Ssam		      continue;
1703173275Ssam
1704173275Ssam		    case 'O':
1705173275Ssam		      opcode |= (mask << 25) | (mask << 0);
1706173275Ssam		      continue;
1707173275Ssam		    }
1708173275Ssam		}
1709178354Ssam	      break;
1710178354Ssam
1711178354Ssam	    case 'e':		/* next operand is a floating point register */
1712178354Ssam	    case 'v':
1713178354Ssam	    case 'V':
1714178354Ssam
1715173275Ssam	    case 'f':
1716173275Ssam	    case 'B':
1717173275Ssam	    case 'R':
1718173275Ssam
1719173275Ssam	    case 'g':
1720173275Ssam	    case 'H':
1721178354Ssam	    case 'J':
1722178354Ssam	      {
1723178354Ssam		char format;
1724178354Ssam
1725178354Ssam		if (*s++ == '%'
1726178354Ssam		    && ((format = *s) == 'f')
1727178354Ssam		    && isdigit ((unsigned char) *++s))
1728178354Ssam		  {
1729178354Ssam		    for (mask = 0; isdigit ((unsigned char) *s); ++s)
1730178354Ssam		      {
1731178354Ssam			mask = 10 * mask + (*s - '0');
1732183261Ssam		      }		/* read the number */
1733183261Ssam
1734183261Ssam		    if ((*args == 'v'
1735183261Ssam			 || *args == 'B'
1736183261Ssam			 || *args == 'H')
1737183261Ssam			&& (mask & 1))
1738183261Ssam		      {
1739183261Ssam			break;
1740183261Ssam		      }		/* register must be even numbered */
1741183261Ssam
1742183261Ssam		    if ((*args == 'V'
1743183261Ssam			 || *args == 'R'
1744186904Ssam			 || *args == 'J')
1745186904Ssam			&& (mask & 3))
1746186904Ssam		      {
1747186904Ssam			break;
1748186904Ssam		      }		/* register must be multiple of 4 */
1749186904Ssam
1750186904Ssam		    if (mask >= 64)
1751186904Ssam		      {
1752186904Ssam			if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
1753186904Ssam			  error_message = ": There are only 64 f registers; [0-63]";
1754186904Ssam			else
1755186904Ssam			  error_message = ": There are only 32 f registers; [0-31]";
1756186904Ssam			goto error;
1757186904Ssam		      }	/* on error */
1758186904Ssam		    else if (mask >= 32)
1759186904Ssam		      {
1760186904Ssam			if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
1761186904Ssam			  {
1762186904Ssam			    v9_arg_p = 1;
1763186904Ssam			    mask -= 31;	/* wrap high bit */
1764186904Ssam			  }
1765186904Ssam			else
1766186904Ssam			  {
1767186904Ssam			    error_message = ": There are only 32 f registers; [0-31]";
1768178354Ssam			    goto error;
1769178354Ssam			  }
1770178354Ssam		      }
1771178354Ssam		  }
1772178354Ssam		else
1773178354Ssam		  {
1774178354Ssam		    break;
1775178354Ssam		  }	/* if not an 'f' register. */
1776178354Ssam
1777178354Ssam		switch (*args)
1778178354Ssam		  {
1779178354Ssam		  case 'v':
1780178354Ssam		  case 'V':
1781178354Ssam		  case 'e':
1782178354Ssam		    opcode |= RS1 (mask);
1783178354Ssam		    continue;
1784178354Ssam
1785178354Ssam
1786178354Ssam		  case 'f':
1787178354Ssam		  case 'B':
1788178354Ssam		  case 'R':
1789178354Ssam		    opcode |= RS2 (mask);
1790178354Ssam		    continue;
1791178354Ssam
1792178354Ssam		  case 'g':
1793178354Ssam		  case 'H':
1794178354Ssam		  case 'J':
1795178354Ssam		    opcode |= RD (mask);
1796178354Ssam		    continue;
1797178354Ssam		  }		/* pack it in. */
1798187841Ssam
1799187841Ssam		know (0);
1800187841Ssam		break;
1801187841Ssam	      }			/* float arg */
1802187841Ssam
1803187841Ssam	    case 'F':
1804187841Ssam	      if (strncmp (s, "%fsr", 4) == 0)
1805187841Ssam		{
1806187841Ssam		  s += 4;
1807187841Ssam		  continue;
1808187841Ssam		}
1809187841Ssam	      break;
1810187841Ssam
1811188258Ssam	    case '0':		/* 64 bit immediate (setx insn) */
1812188258Ssam	      the_insn.reloc = BFD_RELOC_NONE; /* reloc handled elsewhere */
1813188258Ssam	      goto immediate;
1814188258Ssam
1815188258Ssam	    case 'h':		/* high 22 bits */
1816188258Ssam	      the_insn.reloc = BFD_RELOC_HI22;
1817188258Ssam	      goto immediate;
1818188258Ssam
1819188258Ssam	    case 'l':		/* 22 bit PC relative immediate */
1820188258Ssam	      the_insn.reloc = BFD_RELOC_SPARC_WDISP22;
1821188258Ssam	      the_insn.pcrel = 1;
1822188258Ssam	      goto immediate;
1823188258Ssam
1824188258Ssam	    case 'L':		/* 30 bit immediate */
1825188258Ssam	      the_insn.reloc = BFD_RELOC_32_PCREL_S2;
1826188258Ssam	      the_insn.pcrel = 1;
1827188258Ssam	      goto immediate;
1828188258Ssam
1829188258Ssam	    case 'n':		/* 22 bit immediate */
1830188258Ssam	      the_insn.reloc = BFD_RELOC_SPARC22;
1831188258Ssam	      goto immediate;
1832188258Ssam
1833188258Ssam	    case 'i':		/* 13 bit immediate */
1834188258Ssam	      the_insn.reloc = BFD_RELOC_SPARC13;
1835188258Ssam
1836188258Ssam	      /* fallthrough */
1837188258Ssam
1838188258Ssam	    immediate:
1839188258Ssam	      if (*s == ' ')
1840188258Ssam		s++;
1841188258Ssam
1842188258Ssam	      /* Check for %hi, etc.  */
1843188258Ssam	      if (*s == '%')
1844188258Ssam		{
1845188258Ssam		  static struct ops {
1846188258Ssam		    /* The name as it appears in assembler.  */
1847188258Ssam		    char *name;
1848188258Ssam		    /* strlen (name), precomputed for speed */
1849188258Ssam		    int len;
1850188258Ssam		    /* The reloc this pseudo-op translates to.  */
1851188258Ssam		    int reloc;
1852188258Ssam		    /* Non-zero if for v9 only.  */
1853188258Ssam		    int v9_p;
1854188258Ssam		    /* Non-zero if can be used in pc-relative contexts.  */
1855188258Ssam		    int pcrel_p;/*FIXME:wip*/
1856188258Ssam		  } ops[] = {
1857188258Ssam		    /* hix/lox must appear before hi/lo so %hix won't be
1858188258Ssam		       mistaken for %hi.  */
1859188258Ssam		    { "hix", 3, BFD_RELOC_SPARC_HIX22, 1, 0 },
1860188258Ssam		    { "lox", 3, BFD_RELOC_SPARC_LOX10, 1, 0 },
1861188258Ssam		    { "hi", 2, BFD_RELOC_HI22, 0, 1 },
1862178354Ssam		    { "lo", 2, BFD_RELOC_LO10, 0, 1 },
1863178354Ssam		    { "hh", 2, BFD_RELOC_SPARC_HH22, 1, 1 },
1864178354Ssam		    { "hm", 2, BFD_RELOC_SPARC_HM10, 1, 1 },
1865178354Ssam		    { "lm", 2, BFD_RELOC_SPARC_LM22, 1, 1 },
1866178354Ssam		    { "h44", 3, BFD_RELOC_SPARC_H44, 1, 0 },
1867178354Ssam		    { "m44", 3, BFD_RELOC_SPARC_M44, 1, 0 },
1868178354Ssam		    { "l44", 3, BFD_RELOC_SPARC_L44, 1, 0 },
1869178354Ssam		    { "uhi", 3, BFD_RELOC_SPARC_HH22, 1, 0 },
1870178354Ssam		    { "ulo", 3, BFD_RELOC_SPARC_HM10, 1, 0 },
1871178354Ssam		    { NULL }
1872188258Ssam		  };
1873188258Ssam		  struct ops *o;
1874178354Ssam
1875188258Ssam		  for (o = ops; o->name; o++)
1876188258Ssam		    if (strncmp (s + 1, o->name, o->len) == 0)
1877178354Ssam		      break;
1878178354Ssam		  if (o->name == NULL)
1879178354Ssam		    break;
1880187842Ssam
1881187842Ssam		  the_insn.reloc = o->reloc;
1882187842Ssam		  s += o->len + 1;
1883187842Ssam		  v9_arg_p = o->v9_p;
1884187842Ssam		}
1885187842Ssam
1886187842Ssam	      /* Note that if the get_expression() fails, we will still
1887178354Ssam		 have created U entries in the symbol table for the
1888188258Ssam		 'symbols' in the input string.  Try not to create U
1889188258Ssam		 symbols for registers, etc.  */
1890187841Ssam	      {
1891188258Ssam		/* This stuff checks to see if the expression ends in
1892188258Ssam		   +%reg.  If it does, it removes the register from
1893188258Ssam		   the expression, and re-sets 's' to point to the
1894188258Ssam		   right place.  */
1895188258Ssam
1896187841Ssam		char *s1;
1897188258Ssam
1898188258Ssam		for (s1 = s; *s1 && *s1 != ',' && *s1 != ']'; s1++) ;
1899188258Ssam
1900188258Ssam		if (s1 != s && isdigit ((unsigned char) s1[-1]))
1901188258Ssam		  {
1902188258Ssam		    if (s1[-2] == '%' && s1[-3] == '+')
1903188258Ssam		      {
1904188258Ssam			s1 -= 3;
1905188258Ssam			*s1 = '\0';
1906188258Ssam			(void) get_expression (s);
1907188258Ssam			*s1 = '+';
1908188258Ssam			s = s1;
1909188258Ssam			continue;
1910188258Ssam		      }
1911188258Ssam		    else if (strchr ("goli0123456789", s1[-2]) && s1[-3] == '%' && s1[-4] == '+')
1912188258Ssam		      {
1913188258Ssam			s1 -= 4;
1914188258Ssam			*s1 = '\0';
1915188258Ssam			(void) get_expression (s);
1916188258Ssam			*s1 = '+';
1917188258Ssam			s = s1;
1918188258Ssam			continue;
1919188258Ssam		      }
1920188258Ssam		  }
1921188258Ssam	      }
1922188258Ssam	      (void) get_expression (s);
1923188258Ssam	      s = expr_end;
1924188258Ssam
1925188258Ssam	      /* Check for constants that don't require emitting a reloc.  */
1926188258Ssam	      if (the_insn.exp.X_op == O_constant
1927188258Ssam		  && the_insn.exp.X_add_symbol == 0
1928188258Ssam		  && the_insn.exp.X_op_symbol == 0)
1929188258Ssam		{
1930188258Ssam		  /* For pc-relative call instructions, we reject
1931188258Ssam		     constants to get better code.  */
1932188258Ssam		  if (the_insn.pcrel
1933188258Ssam		      && the_insn.reloc == BFD_RELOC_32_PCREL_S2
1934188258Ssam		      && in_signed_range (the_insn.exp.X_add_number, 0x3fff))
1935188258Ssam		    {
1936188258Ssam		      error_message = ": PC-relative operand can't be a constant";
1937188258Ssam		      goto error;
1938188258Ssam		    }
1939187842Ssam
1940187842Ssam		  /* Constants that won't fit are checked in md_apply_fix3
1941188258Ssam		     and bfd_install_relocation.
1942187842Ssam		     ??? It would be preferable to install the constants
1943187842Ssam		     into the insn here and save having to create a fixS
1944187842Ssam		     for each one.  There already exists code to handle
1945178354Ssam		     all the various cases (e.g. in md_apply_fix3 and
1946178354Ssam		     bfd_install_relocation) so duplicating all that code
1947188258Ssam		     here isn't right.  */
1948178354Ssam		}
1949188258Ssam
1950178354Ssam	      continue;
1951178354Ssam
1952188258Ssam	    case 'a':
1953178354Ssam	      if (*s++ == 'a')
1954188258Ssam		{
1955187841Ssam		  opcode |= ANNUL;
1956178354Ssam		  continue;
1957178354Ssam		}
1958178354Ssam	      break;
1959178354Ssam
1960188258Ssam	    case 'A':
1961188258Ssam	      {
1962178354Ssam		int asi = 0;
1963178354Ssam
1964178354Ssam		/* Parse an asi.  */
1965178354Ssam		if (*s == '#')
1966178354Ssam		  {
1967178354Ssam		    if (! parse_keyword_arg (sparc_encode_asi, &s, &asi))
1968178354Ssam		      {
1969178354Ssam			error_message = ": invalid ASI name";
1970178354Ssam			goto error;
1971178354Ssam		      }
1972178354Ssam		  }
1973178354Ssam		else
1974187842Ssam		  {
1975187842Ssam		    if (! parse_const_expr_arg (&s, &asi))
1976178354Ssam		      {
1977178354Ssam			error_message = ": invalid ASI expression";
1978178354Ssam			goto error;
1979187801Ssam		      }
1980178354Ssam		    if (asi < 0 || asi > 255)
1981188258Ssam		      {
1982178354Ssam			error_message = ": invalid ASI number";
1983178354Ssam			goto error;
1984178354Ssam		      }
1985178354Ssam		  }
1986187842Ssam		opcode |= ASI (asi);
1987187842Ssam		continue;
1988187842Ssam	      }			/* alternate space */
1989187842Ssam
1990187842Ssam	    case 'p':
1991187842Ssam	      if (strncmp (s, "%psr", 4) == 0)
1992178354Ssam		{
1993178354Ssam		  s += 4;
1994178354Ssam		  continue;
1995178354Ssam		}
1996178354Ssam	      break;
1997178354Ssam
1998178354Ssam	    case 'q':		/* floating point queue */
1999178354Ssam	      if (strncmp (s, "%fq", 3) == 0)
2000178354Ssam		{
2001178354Ssam		  s += 3;
2002178354Ssam		  continue;
2003178354Ssam		}
2004178354Ssam	      break;
2005178354Ssam
2006178354Ssam	    case 'Q':		/* coprocessor queue */
2007178354Ssam	      if (strncmp (s, "%cq", 3) == 0)
2008178354Ssam		{
2009178354Ssam		  s += 3;
2010178354Ssam		  continue;
2011178354Ssam		}
2012178354Ssam	      break;
2013178354Ssam
2014178354Ssam	    case 'S':
2015178354Ssam	      if (strcmp (str, "set") == 0
2016178354Ssam		  || strcmp (str, "setuw") == 0)
2017178354Ssam		{
2018178354Ssam		  special_case = SPECIAL_CASE_SET;
2019178354Ssam		  continue;
2020178354Ssam		}
2021178354Ssam	      else if (strcmp (str, "setsw") == 0)
2022178354Ssam		{
2023178354Ssam		  special_case = SPECIAL_CASE_SETSW;
2024178354Ssam		  continue;
2025178354Ssam		}
2026178354Ssam	      else if (strcmp (str, "setx") == 0)
2027178354Ssam		{
2028178354Ssam		  special_case = SPECIAL_CASE_SETX;
2029187801Ssam		  continue;
2030187801Ssam		}
2031187801Ssam	      else if (strncmp (str, "fdiv", 4) == 0)
2032187801Ssam		{
2033187801Ssam		  special_case = SPECIAL_CASE_FDIV;
2034187801Ssam		  continue;
2035187801Ssam		}
2036187801Ssam	      break;
2037178354Ssam
2038178354Ssam	    case 'o':
2039178354Ssam	      if (strncmp (s, "%asi", 4) != 0)
2040187841Ssam		break;
2041178354Ssam	      s += 4;
2042178354Ssam	      continue;
2043187841Ssam
2044178354Ssam	    case 's':
2045178354Ssam	      if (strncmp (s, "%fprs", 5) != 0)
2046188258Ssam		break;
2047178354Ssam	      s += 5;
2048178354Ssam	      continue;
2049178354Ssam
2050188258Ssam	    case 'E':
2051188258Ssam	      if (strncmp (s, "%ccr", 4) != 0)
2052188258Ssam		break;
2053188258Ssam	      s += 4;
2054188258Ssam	      continue;
2055188258Ssam
2056188258Ssam	    case 't':
2057188258Ssam	      if (strncmp (s, "%tbr", 4) != 0)
2058178354Ssam		break;
2059188258Ssam	      s += 4;
2060178354Ssam	      continue;
2061178354Ssam
2062178354Ssam	    case 'w':
2063188258Ssam	      if (strncmp (s, "%wim", 4) != 0)
2064188258Ssam		break;
2065188258Ssam	      s += 4;
2066188258Ssam	      continue;
2067188258Ssam
2068188258Ssam	    case 'x':
2069188258Ssam	      {
2070188258Ssam		char *push = input_line_pointer;
2071178354Ssam		expressionS e;
2072178354Ssam
2073178354Ssam		input_line_pointer = s;
2074178354Ssam		expression (&e);
2075187801Ssam		if (e.X_op == O_constant)
2076187801Ssam		  {
2077178354Ssam		    int n = e.X_add_number;
2078178354Ssam		    if (n != e.X_add_number || (n & ~0x1ff) != 0)
2079178354Ssam		      as_bad ("OPF immediate operand out of range (0-0x1ff)");
2080178354Ssam		    else
2081178354Ssam		      opcode |= e.X_add_number << 5;
2082178354Ssam		  }
2083178354Ssam		else
2084178354Ssam		  as_bad ("non-immediate OPF operand, ignored");
2085178354Ssam		s = input_line_pointer;
2086178354Ssam		input_line_pointer = push;
2087178354Ssam		continue;
2088178354Ssam	      }
2089178354Ssam
2090178354Ssam	    case 'y':
2091178354Ssam	      if (strncmp (s, "%y", 2) != 0)
2092178354Ssam		break;
2093178354Ssam	      s += 2;
2094178354Ssam	      continue;
2095178354Ssam
2096178354Ssam	    case 'u':
2097178354Ssam	    case 'U':
2098178354Ssam	      {
2099178354Ssam		/* Parse a sparclet cpreg.  */
2100178354Ssam		int cpreg;
2101178354Ssam		if (! parse_keyword_arg (sparc_encode_sparclet_cpreg, &s, &cpreg))
2102178354Ssam		  {
2103178354Ssam		    error_message = ": invalid cpreg name";
2104178354Ssam		    goto error;
2105178354Ssam		  }
2106178354Ssam		opcode |= (*args == 'U' ? RS1 (cpreg) : RD (cpreg));
2107178354Ssam		continue;
2108178354Ssam	      }
2109178354Ssam
2110178354Ssam	    default:
2111178354Ssam	      as_fatal ("failed sanity check.");
2112178354Ssam	    }			/* switch on arg code */
2113178354Ssam
2114178354Ssam	  /* Break out of for() loop.  */
2115178354Ssam	  break;
2116178354Ssam	}			/* for each arg that we expect */
2117178354Ssam
2118178354Ssam    error:
2119178354Ssam      if (match == 0)
2120178354Ssam	{
2121178354Ssam	  /* Args don't match. */
2122178354Ssam	  if (&insn[1] - sparc_opcodes < sparc_num_opcodes
2123178354Ssam	      && (insn->name == insn[1].name
2124178354Ssam		  || !strcmp (insn->name, insn[1].name)))
2125178354Ssam	    {
2126186104Ssam	      ++insn;
2127186104Ssam	      s = argsStart;
2128186104Ssam	      continue;
2129186104Ssam	    }
2130186104Ssam	  else
2131186104Ssam	    {
2132178354Ssam	      as_bad ("Illegal operands%s", error_message);
2133178354Ssam	      return;
2134178354Ssam	    }
2135178354Ssam	}
2136178354Ssam      else
2137178354Ssam	{
2138178354Ssam	  /* We have a match.  Now see if the architecture is ok.  */
2139178354Ssam	  int needed_arch_mask = insn->architecture;
2140178354Ssam
2141178354Ssam	  if (v9_arg_p)
2142178354Ssam	    {
2143178354Ssam	      needed_arch_mask &= ~ ((1 << SPARC_OPCODE_ARCH_V9)
2144178354Ssam				     | (1 << SPARC_OPCODE_ARCH_V9A));
2145178354Ssam	      needed_arch_mask |= (1 << SPARC_OPCODE_ARCH_V9);
2146178354Ssam	    }
2147178354Ssam
2148178354Ssam	  if (needed_arch_mask & SPARC_OPCODE_SUPPORTED (current_architecture))
2149178354Ssam	    ; /* ok */
2150178354Ssam	  /* Can we bump up the architecture?  */
2151178354Ssam	  else if (needed_arch_mask & SPARC_OPCODE_SUPPORTED (max_architecture))
2152178354Ssam	    {
2153178354Ssam	      enum sparc_opcode_arch_val needed_architecture =
2154186103Ssam		sparc_ffs (SPARC_OPCODE_SUPPORTED (max_architecture)
2155186103Ssam			   & needed_arch_mask);
2156186103Ssam
2157186103Ssam	      assert (needed_architecture <= SPARC_OPCODE_ARCH_MAX);
2158186103Ssam	      if (warn_on_bump
2159186103Ssam		  && needed_architecture > warn_after_architecture)
2160178354Ssam		{
2161178354Ssam		  as_warn ("architecture bumped from \"%s\" to \"%s\" on \"%s\"",
2162178354Ssam			   sparc_opcode_archs[current_architecture].name,
2163178354Ssam			   sparc_opcode_archs[needed_architecture].name,
2164178354Ssam			   str);
2165178354Ssam		  warn_after_architecture = needed_architecture;
2166178354Ssam		}
2167178354Ssam	      current_architecture = needed_architecture;
2168178354Ssam	    }
2169178354Ssam	  /* Conflict.  */
2170178354Ssam	  /* ??? This seems to be a bit fragile.  What if the next entry in
2171178354Ssam	     the opcode table is the one we want and it is supported?
2172178354Ssam	     It is possible to arrange the table today so that this can't
2173178354Ssam	     happen but what about tomorrow?  */
2174178354Ssam	  else
2175178354Ssam	    {
2176178354Ssam	      int arch,printed_one_p = 0;
2177178354Ssam	      char *p;
2178178354Ssam	      char required_archs[SPARC_OPCODE_ARCH_MAX * 16];
2179178354Ssam
2180178354Ssam	      /* Create a list of the architectures that support the insn.  */
2181178354Ssam	      needed_arch_mask &= ~ SPARC_OPCODE_SUPPORTED (max_architecture);
2182178354Ssam	      p = required_archs;
2183178354Ssam	      arch = sparc_ffs (needed_arch_mask);
2184178354Ssam	      while ((1 << arch) <= needed_arch_mask)
2185178354Ssam		{
2186178354Ssam		  if ((1 << arch) & needed_arch_mask)
2187173275Ssam		    {
2188173275Ssam		      if (printed_one_p)
2189173275Ssam			*p++ = '|';
2190173275Ssam		      strcpy (p, sparc_opcode_archs[arch].name);
2191173275Ssam		      p += strlen (p);
2192173275Ssam		      printed_one_p = 1;
2193173275Ssam		    }
2194173275Ssam		  ++arch;
2195173275Ssam		}
2196173275Ssam
2197173275Ssam	      as_bad ("Architecture mismatch on \"%s\".", str);
2198173275Ssam	      as_tsktsk (" (Requires %s; requested architecture is %s.)",
2199173275Ssam			 required_archs,
2200173275Ssam			 sparc_opcode_archs[max_architecture].name);
2201173275Ssam	      return;
2202173275Ssam	    }
2203173275Ssam	} /* if no match */
2204173275Ssam
2205173275Ssam      break;
2206173275Ssam    } /* forever looking for a match */
2207173275Ssam
2208173275Ssam  the_insn.opcode = opcode;
2209173275Ssam}
2210173275Ssam
2211173275Ssam/* Parse an argument that can be expressed as a keyword.
2212173275Ssam   (eg: #StoreStore or %ccfr).
2213173275Ssam   The result is a boolean indicating success.
2214173275Ssam   If successful, INPUT_POINTER is updated.  */
2215173275Ssam
2216173275Ssamstatic int
2217173275Ssamparse_keyword_arg (lookup_fn, input_pointerP, valueP)
2218173275Ssam     int (*lookup_fn) PARAMS ((const char *));
2219173275Ssam     char **input_pointerP;
2220173275Ssam     int *valueP;
2221173275Ssam{
2222173275Ssam  int value;
2223173275Ssam  char c, *p, *q;
2224173275Ssam
2225173275Ssam  p = *input_pointerP;
2226138593Ssam  for (q = p + (*p == '#' || *p == '%');
2227170531Ssam       isalnum ((unsigned char) *q) || *q == '_';
2228138593Ssam       ++q)
2229138593Ssam    continue;
2230138593Ssam  c = *q;
2231138593Ssam  *q = 0;
2232138593Ssam  value = (*lookup_fn) (p);
2233138593Ssam  *q = c;
2234138593Ssam  if (value == -1)
2235138593Ssam    return 0;
2236138593Ssam  *valueP = value;
2237138593Ssam  *input_pointerP = q;
2238138593Ssam  return 1;
2239138593Ssam}
2240138593Ssam
2241138593Ssam/* Parse an argument that is a constant expression.
2242138593Ssam   The result is a boolean indicating success.  */
2243138593Ssam
2244138593Ssamstatic int
2245138593Ssamparse_const_expr_arg (input_pointerP, valueP)
2246138593Ssam     char **input_pointerP;
2247138593Ssam     int *valueP;
2248138593Ssam{
2249138593Ssam  char *save = input_line_pointer;
2250138593Ssam  expressionS exp;
2251138593Ssam
2252138593Ssam  input_line_pointer = *input_pointerP;
2253138593Ssam  /* The next expression may be something other than a constant
2254138593Ssam     (say if we're not processing the right variant of the insn).
2255138593Ssam     Don't call expression unless we're sure it will succeed as it will
2256138593Ssam     signal an error (which we want to defer until later).  */
2257138593Ssam  /* FIXME: It might be better to define md_operand and have it recognize
2258138593Ssam     things like %asi, etc. but continuing that route through to the end
2259138593Ssam     is a lot of work.  */
2260138593Ssam  if (*input_line_pointer == '%')
2261138593Ssam    {
2262138593Ssam      input_line_pointer = save;
2263138593Ssam      return 0;
2264138593Ssam    }
2265138593Ssam  expression (&exp);
2266138593Ssam  *input_pointerP = input_line_pointer;
2267138593Ssam  input_line_pointer = save;
2268138593Ssam  if (exp.X_op != O_constant)
2269138593Ssam    return 0;
2270138593Ssam  *valueP = exp.X_add_number;
2271159885Ssam  return 1;
2272159885Ssam}
2273159885Ssam
2274159885Ssam/* Subroutine of sparc_ip to parse an expression.  */
2275159885Ssam
2276159885Ssamstatic int
2277159885Ssamget_expression (str)
2278159885Ssam     char *str;
2279159885Ssam{
2280159885Ssam  char *save_in;
2281159885Ssam  segT seg;
2282159885Ssam
2283159885Ssam  save_in = input_line_pointer;
2284159885Ssam  input_line_pointer = str;
2285173275Ssam  seg = expression (&the_insn.exp);
2286170531Ssam  if (seg != absolute_section
2287173275Ssam      && seg != text_section
2288173275Ssam      && seg != data_section
2289173275Ssam      && seg != bss_section
2290173275Ssam      && seg != undefined_section)
2291173275Ssam    {
2292173275Ssam      the_insn.error = "bad segment";
2293183261Ssam      expr_end = input_line_pointer;
2294183261Ssam      input_line_pointer = save_in;
2295173275Ssam      return 1;
2296183261Ssam    }
2297183261Ssam  expr_end = input_line_pointer;
2298183261Ssam  input_line_pointer = save_in;
2299183261Ssam  return 0;
2300183261Ssam}
2301183261Ssam
2302183261Ssam/* Subroutine of md_assemble to output one insn.  */
2303183261Ssam
2304183261Ssamstatic void
2305159885Ssamoutput_insn (insn, the_insn)
2306159885Ssam     const struct sparc_opcode *insn;
2307159885Ssam     struct sparc_it *the_insn;
2308159885Ssam{
2309138593Ssam  char *toP = frag_more (4);
2310138593Ssam
2311138593Ssam  /* put out the opcode */
2312138593Ssam  if (INSN_BIG_ENDIAN)
2313138593Ssam    number_to_chars_bigendian (toP, (valueT) the_insn->opcode, 4);
2314138593Ssam  else
2315138593Ssam    number_to_chars_littleendian (toP, (valueT) the_insn->opcode, 4);
2316138593Ssam
2317138593Ssam  /* put out the symbol-dependent stuff */
2318138593Ssam  if (the_insn->reloc != BFD_RELOC_NONE)
2319138593Ssam    {
2320138593Ssam      fixS *fixP =  fix_new_exp (frag_now,	/* which frag */
2321138593Ssam				 (toP - frag_now->fr_literal),	/* where */
2322138593Ssam				 4,		/* size */
2323138593Ssam				 &the_insn->exp,
2324138593Ssam				 the_insn->pcrel,
2325138593Ssam				 the_insn->reloc);
2326138593Ssam      /* Turn off overflow checking in fixup_segment.  We'll do our
2327138593Ssam	 own overflow checking in md_apply_fix3.  This is necessary because
2328138593Ssam	 the insn size is 4 and fixup_segment will signal an overflow for
2329170531Ssam	 large 8 byte quantities.  */
2330170531Ssam      fixP->fx_no_overflow = 1;
2331170531Ssam    }
2332170531Ssam
2333170531Ssam  last_insn = insn;
2334170531Ssam  last_opcode = the_insn->opcode;
2335170531Ssam}
2336170531Ssam
2337170531Ssam/*
2338170531Ssam  This is identical to the md_atof in m68k.c.  I think this is right,
2339170531Ssam  but I'm not sure.
2340138593Ssam
2341170531Ssam  Turn a string in input_line_pointer into a floating point constant of type
2342170531Ssam  type, and store the appropriate bytes in *litP.  The number of LITTLENUMS
2343170531Ssam  emitted is stored in *sizeP .  An error message is returned, or NULL on OK.
2344170531Ssam  */
2345170531Ssam
2346170531Ssam/* Equal to MAX_PRECISION in atof-ieee.c */
2347173275Ssam#define MAX_LITTLENUMS 6
2348170531Ssam
2349170531Ssamchar *
2350170531Ssammd_atof (type, litP, sizeP)
2351173275Ssam     char type;
2352173275Ssam     char *litP;
2353170531Ssam     int *sizeP;
2354170531Ssam{
2355170531Ssam  int i,prec;
2356173275Ssam  LITTLENUM_TYPE words[MAX_LITTLENUMS];
2357173275Ssam  char *t;
2358173275Ssam
2359173275Ssam  switch (type)
2360173275Ssam    {
2361173275Ssam    case 'f':
2362173275Ssam    case 'F':
2363173275Ssam    case 's':
2364173275Ssam    case 'S':
2365173275Ssam      prec = 2;
2366173275Ssam      break;
2367173275Ssam
2368173275Ssam    case 'd':
2369173275Ssam    case 'D':
2370173275Ssam    case 'r':
2371173275Ssam    case 'R':
2372170531Ssam      prec = 4;
2373173275Ssam      break;
2374170531Ssam
2375170531Ssam    case 'x':
2376170531Ssam    case 'X':
2377170531Ssam      prec = 6;
2378173275Ssam      break;
2379173275Ssam
2380173275Ssam    case 'p':
2381173275Ssam    case 'P':
2382173275Ssam      prec = 6;
2383173275Ssam      break;
2384173275Ssam
2385173275Ssam    default:
2386173275Ssam      *sizeP = 0;
2387173275Ssam      return "Bad call to MD_ATOF()";
2388173275Ssam    }
2389173275Ssam
2390173275Ssam  t = atof_ieee (input_line_pointer, type, words);
2391173275Ssam  if (t)
2392173275Ssam    input_line_pointer = t;
2393173275Ssam  *sizeP = prec * sizeof (LITTLENUM_TYPE);
2394173275Ssam
2395173275Ssam  if (target_big_endian)
2396173275Ssam    {
2397173275Ssam      for (i = 0; i < prec; i++)
2398173275Ssam	{
2399173275Ssam	  md_number_to_chars (litP, (valueT) words[i], sizeof (LITTLENUM_TYPE));
2400173275Ssam	  litP += sizeof (LITTLENUM_TYPE);
2401173275Ssam	}
2402173275Ssam    }
2403173275Ssam  else
2404173275Ssam    {
2405173275Ssam      for (i = prec - 1; i >= 0; i--)
2406173275Ssam	{
2407173275Ssam	  md_number_to_chars (litP, (valueT) words[i], sizeof (LITTLENUM_TYPE));
2408173275Ssam	  litP += sizeof (LITTLENUM_TYPE);
2409173275Ssam	}
2410173275Ssam    }
2411173275Ssam
2412173275Ssam  return 0;
2413173275Ssam}
2414173275Ssam
2415173275Ssam/* Write a value out to the object file, using the appropriate
2416173275Ssam   endianness.  */
2417173275Ssam
2418173275Ssamvoid
2419173275Ssammd_number_to_chars (buf, val, n)
2420173275Ssam     char *buf;
2421173275Ssam     valueT val;
2422173275Ssam     int n;
2423173275Ssam{
2424173275Ssam  if (target_big_endian)
2425173275Ssam    number_to_chars_bigendian (buf, val, n);
2426173275Ssam  else
2427173275Ssam    number_to_chars_littleendian (buf, val, n);
2428173275Ssam}
2429173275Ssam
2430173275Ssam/* Apply a fixS to the frags, now that we know the value it ought to
2431173275Ssam   hold. */
2432173275Ssam
2433173275Ssamint
2434173275Ssammd_apply_fix3 (fixP, value, segment)
2435173275Ssam     fixS *fixP;
2436173275Ssam     valueT *value;
2437173275Ssam     segT segment;
2438173275Ssam{
2439173275Ssam  char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
2440173275Ssam  offsetT val;
2441173275Ssam  long insn;
2442173275Ssam
2443173275Ssam  val = *value;
2444173275Ssam
2445173275Ssam  assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
2446173275Ssam
2447173275Ssam  fixP->fx_addnumber = val;	/* Remember value for emit_reloc */
2448173275Ssam
2449173275Ssam#ifdef OBJ_ELF
2450173275Ssam  /* FIXME: SPARC ELF relocations don't use an addend in the data
2451173275Ssam     field itself.  This whole approach should be somehow combined
2452173275Ssam     with the calls to bfd_install_relocation.  Also, the value passed
2453173275Ssam     in by fixup_segment includes the value of a defined symbol.  We
2454173275Ssam     don't want to include the value of an externally visible symbol.  */
2455173275Ssam  if (fixP->fx_addsy != NULL)
2456170531Ssam    {
2457170531Ssam      if (fixP->fx_addsy->sy_used_in_reloc
2458170531Ssam	  && (S_IS_EXTERNAL (fixP->fx_addsy)
2459170531Ssam	      || S_IS_WEAK (fixP->fx_addsy)
2460170531Ssam	      || (sparc_pic_code && ! fixP->fx_pcrel)
2461170531Ssam	      || (S_GET_SEGMENT (fixP->fx_addsy) != segment
2462170531Ssam		  && ((bfd_get_section_flags (stdoutput,
2463170531Ssam					      S_GET_SEGMENT (fixP->fx_addsy))
2464170531Ssam		       & SEC_LINK_ONCE) != 0
2465170531Ssam		      || strncmp (segment_name (S_GET_SEGMENT (fixP->fx_addsy)),
2466170531Ssam				  ".gnu.linkonce",
2467170531Ssam				  sizeof ".gnu.linkonce" - 1) == 0)))
2468170531Ssam	  && S_GET_SEGMENT (fixP->fx_addsy) != absolute_section
2469170531Ssam	  && S_GET_SEGMENT (fixP->fx_addsy) != undefined_section
2470170531Ssam	  && ! bfd_is_com_section (S_GET_SEGMENT (fixP->fx_addsy)))
2471170531Ssam	fixP->fx_addnumber -= S_GET_VALUE (fixP->fx_addsy);
2472170531Ssam      return 1;
2473170531Ssam    }
2474170531Ssam#endif
2475170531Ssam
2476170531Ssam  /* This is a hack.  There should be a better way to
2477170531Ssam     handle this.  Probably in terms of howto fields, once
2478170531Ssam     we can look at these fixups in terms of howtos.  */
2479170531Ssam  if (fixP->fx_r_type == BFD_RELOC_32_PCREL_S2 && fixP->fx_addsy)
2480170531Ssam    val += fixP->fx_where + fixP->fx_frag->fr_address;
2481170531Ssam
2482170531Ssam#ifdef OBJ_AOUT
2483170531Ssam  /* FIXME: More ridiculous gas reloc hacking.  If we are going to
2484170531Ssam     generate a reloc, then we just want to let the reloc addend set
2485170531Ssam     the value.  We do not want to also stuff the addend into the
2486170531Ssam     object file.  Including the addend in the object file works when
2487170531Ssam     doing a static link, because the linker will ignore the object
2488170531Ssam     file contents.  However, the dynamic linker does not ignore the
2489170531Ssam     object file contents.  */
2490170531Ssam  if (fixP->fx_addsy != NULL
2491170531Ssam      && fixP->fx_r_type != BFD_RELOC_32_PCREL_S2)
2492170531Ssam    val = 0;
2493170531Ssam
2494170531Ssam  /* When generating PIC code, we do not want an addend for a reloc
2495170531Ssam     against a local symbol.  We adjust fx_addnumber to cancel out the
2496170531Ssam     value already included in val, and to also cancel out the
2497170531Ssam     adjustment which bfd_install_relocation will create.  */
2498170531Ssam  if (sparc_pic_code
2499170531Ssam      && fixP->fx_r_type != BFD_RELOC_32_PCREL_S2
2500170531Ssam      && fixP->fx_addsy != NULL
2501170531Ssam      && ! S_IS_COMMON (fixP->fx_addsy)
2502170531Ssam      && (fixP->fx_addsy->bsym->flags & BSF_SECTION_SYM) == 0)
2503170531Ssam    fixP->fx_addnumber -= 2 * S_GET_VALUE (fixP->fx_addsy);
2504170531Ssam#endif
2505170531Ssam
2506170531Ssam  /* If this is a data relocation, just output VAL.  */
2507170531Ssam
2508170531Ssam  if (fixP->fx_r_type == BFD_RELOC_16)
2509170531Ssam    {
2510170531Ssam      md_number_to_chars (buf, val, 2);
2511170531Ssam    }
2512170531Ssam  else if (fixP->fx_r_type == BFD_RELOC_32)
2513170531Ssam    {
2514170531Ssam      md_number_to_chars (buf, val, 4);
2515170531Ssam    }
2516170531Ssam  else if (fixP->fx_r_type == BFD_RELOC_64)
2517170531Ssam    {
2518170531Ssam      md_number_to_chars (buf, val, 8);
2519170531Ssam    }
2520170531Ssam  else
2521170531Ssam    {
2522170531Ssam      /* It's a relocation against an instruction.  */
2523170531Ssam
2524170531Ssam      if (INSN_BIG_ENDIAN)
2525170531Ssam	insn = bfd_getb32 ((unsigned char *) buf);
2526170531Ssam      else
2527170531Ssam	insn = bfd_getl32 ((unsigned char *) buf);
2528170531Ssam
2529170531Ssam      switch (fixP->fx_r_type)
2530170531Ssam	{
2531170531Ssam	case BFD_RELOC_32_PCREL_S2:
2532170531Ssam	  val = val >> 2;
2533170531Ssam	  /* FIXME: This increment-by-one deserves a comment of why it's
2534170531Ssam	     being done!  */
2535170531Ssam	  if (! sparc_pic_code
2536170531Ssam	      || fixP->fx_addsy == NULL
2537170531Ssam	      || (fixP->fx_addsy->bsym->flags & BSF_SECTION_SYM) != 0)
2538170531Ssam	    ++val;
2539170531Ssam	  insn |= val & 0x3fffffff;
2540170531Ssam	  break;
2541170531Ssam
2542170531Ssam	case BFD_RELOC_SPARC_11:
2543170531Ssam	  if (! in_signed_range (val, 0x7ff))
2544170531Ssam	    as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow");
2545170531Ssam	  insn |= val & 0x7ff;
2546170531Ssam	  break;
2547170531Ssam
2548170531Ssam	case BFD_RELOC_SPARC_10:
2549170531Ssam	  if (! in_signed_range (val, 0x3ff))
2550170531Ssam	    as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow");
2551170531Ssam	  insn |= val & 0x3ff;
2552170531Ssam	  break;
2553170531Ssam
2554170531Ssam	case BFD_RELOC_SPARC_7:
2555170531Ssam	  if (! in_bitfield_range (val, 0x7f))
2556170531Ssam	    as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow");
2557170531Ssam	  insn |= val & 0x7f;
2558170531Ssam	  break;
2559170531Ssam
2560170531Ssam	case BFD_RELOC_SPARC_6:
2561170531Ssam	  if (! in_bitfield_range (val, 0x3f))
2562170531Ssam	    as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow");
2563170531Ssam	  insn |= val & 0x3f;
2564170531Ssam	  break;
2565170531Ssam
2566170531Ssam	case BFD_RELOC_SPARC_5:
2567170531Ssam	  if (! in_bitfield_range (val, 0x1f))
2568170531Ssam	    as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow");
2569170531Ssam	  insn |= val & 0x1f;
2570170531Ssam	  break;
2571170531Ssam
2572170531Ssam	case BFD_RELOC_SPARC_WDISP16:
2573170531Ssam	  /* FIXME: simplify */
2574170531Ssam	  if (((val > 0) && (val & ~0x3fffc))
2575170531Ssam	      || ((val < 0) && (~(val - 1) & ~0x3fffc)))
2576170531Ssam	    as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow");
2577170531Ssam	  /* FIXME: The +1 deserves a comment.  */
2578170531Ssam	  val = (val >> 2) + 1;
2579170531Ssam	  insn |= ((val & 0xc000) << 6) | (val & 0x3fff);
2580170531Ssam	  break;
2581170531Ssam
2582170531Ssam	case BFD_RELOC_SPARC_WDISP19:
2583170531Ssam	  /* FIXME: simplify */
2584170531Ssam	  if (((val > 0) && (val & ~0x1ffffc))
2585170531Ssam	      || ((val < 0) && (~(val - 1) & ~0x1ffffc)))
2586170531Ssam	    as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow");
2587170531Ssam	  /* FIXME: The +1 deserves a comment.  */
2588170531Ssam	  val = (val >> 2) + 1;
2589170531Ssam	  insn |= val & 0x7ffff;
2590170531Ssam	  break;
2591170531Ssam
2592170531Ssam	case BFD_RELOC_SPARC_HH22:
2593170531Ssam	  val = BSR (val, 32);
2594170531Ssam	  /* intentional fallthrough */
2595170531Ssam
2596170531Ssam	case BFD_RELOC_SPARC_LM22:
2597170531Ssam	case BFD_RELOC_HI22:
2598170531Ssam	  if (!fixP->fx_addsy)
2599170531Ssam	    {
2600170531Ssam	      insn |= (val >> 10) & 0x3fffff;
2601170531Ssam	    }
2602170531Ssam	  else
2603170531Ssam	    {
2604170531Ssam	      /* FIXME: Need comment explaining why we do this.  */
2605170531Ssam	      insn &= ~0xffff;
2606170531Ssam	    }
2607170531Ssam	  break;
2608170531Ssam
2609170531Ssam	case BFD_RELOC_SPARC22:
2610170531Ssam	  if (val & ~0x003fffff)
2611170531Ssam	    as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow");
2612170531Ssam	  insn |= (val & 0x3fffff);
2613170531Ssam	  break;
2614170531Ssam
2615170531Ssam	case BFD_RELOC_SPARC_HM10:
2616170531Ssam	  val = BSR (val, 32);
2617170531Ssam	  /* intentional fallthrough */
2618170531Ssam
2619173275Ssam	case BFD_RELOC_LO10:
2620170531Ssam	  if (!fixP->fx_addsy)
2621170531Ssam	    {
2622173275Ssam	      insn |= val & 0x3ff;
2623170531Ssam	    }
2624170531Ssam	  else
2625173275Ssam	    {
2626170531Ssam	      /* FIXME: Need comment explaining why we do this.  */
2627170531Ssam	      insn &= ~0xff;
2628170531Ssam	    }
2629173275Ssam	  break;
2630170531Ssam
2631170531Ssam	case BFD_RELOC_SPARC13:
2632170531Ssam	  if (! in_signed_range (val, 0x1fff))
2633173275Ssam	    as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow");
2634170531Ssam	  insn |= val & 0x1fff;
2635170531Ssam	  break;
2636170531Ssam
2637170531Ssam	case BFD_RELOC_SPARC_WDISP22:
2638170531Ssam	  val = (val >> 2) + 1;
2639173275Ssam	  /* FALLTHROUGH */
2640170531Ssam	case BFD_RELOC_SPARC_BASE22:
2641170531Ssam	  insn |= val & 0x3fffff;
2642170531Ssam	  break;
2643173275Ssam
2644170531Ssam	case BFD_RELOC_SPARC_H44:
2645170531Ssam	  if (!fixP->fx_addsy)
2646170531Ssam	    {
2647173275Ssam	      bfd_vma tval = val;
2648170531Ssam	      tval >>= 22;
2649170531Ssam	      insn |= tval & 0x3fffff;
2650170531Ssam	    }
2651170531Ssam	  break;
2652170531Ssam
2653170531Ssam	case BFD_RELOC_SPARC_M44:
2654181454Ssam	  if (!fixP->fx_addsy)
2655181454Ssam	    insn |= (val >> 12) & 0x3ff;
2656181454Ssam	  break;
2657181454Ssam
2658181454Ssam	case BFD_RELOC_SPARC_L44:
2659181454Ssam	  if (!fixP->fx_addsy)
2660181454Ssam	    insn |= val & 0xfff;
2661181454Ssam	  break;
2662181454Ssam
2663181454Ssam	case BFD_RELOC_SPARC_HIX22:
2664181454Ssam	  if (!fixP->fx_addsy)
2665181454Ssam	    {
2666181454Ssam	      val ^= ~ (offsetT) 0;
2667181454Ssam	      insn |= (val >> 10) & 0x3fffff;
2668181454Ssam	    }
2669181454Ssam	  break;
2670181454Ssam
2671181454Ssam	case BFD_RELOC_SPARC_LOX10:
2672181454Ssam	  if (!fixP->fx_addsy)
2673181454Ssam	    insn |= 0x1c00 | (val & 0x3ff);
2674181454Ssam	  break;
2675181454Ssam
2676181454Ssam	case BFD_RELOC_NONE:
2677181454Ssam	default:
2678181454Ssam	  as_bad_where (fixP->fx_file, fixP->fx_line,
2679181454Ssam			"bad or unhandled relocation type: 0x%02x",
2680181454Ssam			fixP->fx_r_type);
2681181454Ssam	  break;
2682181454Ssam	}
2683181454Ssam
2684181454Ssam      if (INSN_BIG_ENDIAN)
2685181454Ssam	bfd_putb32 (insn, (unsigned char *) buf);
2686181454Ssam      else
2687181454Ssam	bfd_putl32 (insn, (unsigned char *) buf);
2688181454Ssam    }
2689181454Ssam
2690181454Ssam  /* Are we finished with this relocation now?  */
2691181454Ssam  if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
2692181454Ssam    fixP->fx_done = 1;
2693181454Ssam
2694181454Ssam  return 1;
2695181454Ssam}
2696181454Ssam
2697181454Ssam/* Translate internal representation of relocation info to BFD target
2698181454Ssam   format.  */
2699181454Ssamarelent *
2700181454Ssamtc_gen_reloc (section, fixp)
2701181454Ssam     asection *section;
2702181454Ssam     fixS *fixp;
2703181454Ssam{
2704181454Ssam  arelent *reloc;
2705181454Ssam  bfd_reloc_code_real_type code;
2706181454Ssam
2707181454Ssam  reloc = (arelent *) xmalloc (sizeof (arelent));
2708181454Ssam
2709181454Ssam  reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
2710181454Ssam  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
2711181454Ssam
2712181454Ssam  switch (fixp->fx_r_type)
2713181454Ssam    {
2714181454Ssam    case BFD_RELOC_16:
2715181454Ssam    case BFD_RELOC_32:
2716181454Ssam    case BFD_RELOC_HI22:
2717181454Ssam    case BFD_RELOC_LO10:
2718181454Ssam    case BFD_RELOC_32_PCREL_S2:
2719181454Ssam    case BFD_RELOC_SPARC13:
2720181454Ssam    case BFD_RELOC_SPARC_BASE13:
2721181454Ssam    case BFD_RELOC_SPARC_WDISP16:
2722181454Ssam    case BFD_RELOC_SPARC_WDISP19:
2723181454Ssam    case BFD_RELOC_SPARC_WDISP22:
2724181454Ssam    case BFD_RELOC_64:
2725181454Ssam    case BFD_RELOC_SPARC_5:
2726181454Ssam    case BFD_RELOC_SPARC_6:
2727186904Ssam    case BFD_RELOC_SPARC_7:
2728186904Ssam    case BFD_RELOC_SPARC_10:
2729186904Ssam    case BFD_RELOC_SPARC_11:
2730186904Ssam    case BFD_RELOC_SPARC_HH22:
2731186904Ssam    case BFD_RELOC_SPARC_HM10:
2732186904Ssam    case BFD_RELOC_SPARC_LM22:
2733186904Ssam    case BFD_RELOC_SPARC_PC_HH22:
2734186904Ssam    case BFD_RELOC_SPARC_PC_HM10:
2735186904Ssam    case BFD_RELOC_SPARC_PC_LM22:
2736186904Ssam    case BFD_RELOC_SPARC_H44:
2737186904Ssam    case BFD_RELOC_SPARC_M44:
2738186904Ssam    case BFD_RELOC_SPARC_L44:
2739186904Ssam    case BFD_RELOC_SPARC_HIX22:
2740186904Ssam    case BFD_RELOC_SPARC_LOX10:
2741186904Ssam      code = fixp->fx_r_type;
2742186904Ssam      break;
2743170531Ssam    default:
2744138593Ssam      abort ();
2745138593Ssam      return NULL;
2746138593Ssam    }
2747138593Ssam
2748138593Ssam#if defined (OBJ_ELF) || defined (OBJ_AOUT)
2749146873Sjhb  /* If we are generating PIC code, we need to generate a different
2750138593Ssam     set of relocs.  */
2751138593Ssam
2752138593Ssam#ifdef OBJ_ELF
2753138593Ssam#define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
2754138593Ssam#else
2755138593Ssam#define GOT_NAME "__GLOBAL_OFFSET_TABLE_"
2756138593Ssam#endif
2757138593Ssam
2758138593Ssam  if (sparc_pic_code)
2759138593Ssam    {
2760138593Ssam      switch (code)
2761138593Ssam	{
2762138593Ssam	case BFD_RELOC_32_PCREL_S2:
2763138593Ssam	  if (! S_IS_DEFINED (fixp->fx_addsy)
2764138593Ssam	      || S_IS_COMMON (fixp->fx_addsy)
2765138593Ssam	      || S_IS_EXTERNAL (fixp->fx_addsy)
2766138593Ssam	      || S_IS_WEAK (fixp->fx_addsy))
2767138593Ssam	    code = BFD_RELOC_SPARC_WPLT30;
2768138593Ssam	  break;
2769138593Ssam	case BFD_RELOC_HI22:
2770138593Ssam	  if (fixp->fx_addsy != NULL
2771138593Ssam	      && strcmp (S_GET_NAME (fixp->fx_addsy), GOT_NAME) == 0)
2772147489Savatar	    code = BFD_RELOC_SPARC_PC22;
2773138593Ssam	  else
2774138593Ssam	    code = BFD_RELOC_SPARC_GOT22;
2775147489Savatar	  break;
2776147489Savatar	case BFD_RELOC_LO10:
2777138593Ssam	  if (fixp->fx_addsy != NULL
2778138593Ssam	      && strcmp (S_GET_NAME (fixp->fx_addsy), GOT_NAME) == 0)
2779147489Savatar	    code = BFD_RELOC_SPARC_PC10;
2780147489Savatar	  else
2781138593Ssam	    code = BFD_RELOC_SPARC_GOT10;
2782138593Ssam	  break;
2783138593Ssam	case BFD_RELOC_SPARC13:
2784138593Ssam	  code = BFD_RELOC_SPARC_GOT13;
2785173275Ssam	  break;
2786173275Ssam	default:
2787173275Ssam	  break;
2788173275Ssam	}
2789173275Ssam    }
2790173275Ssam#endif /* defined (OBJ_ELF) || defined (OBJ_AOUT) */
2791173275Ssam
2792173275Ssam  reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
2793173275Ssam  if (reloc->howto == 0)
2794173275Ssam    {
2795173275Ssam      as_bad_where (fixp->fx_file, fixp->fx_line,
2796173275Ssam		    "internal error: can't export reloc type %d (`%s')",
2797173275Ssam		    fixp->fx_r_type, bfd_get_reloc_code_name (code));
2798173275Ssam      return 0;
2799173275Ssam    }
2800173275Ssam
2801173275Ssam  /* @@ Why fx_addnumber sometimes and fx_offset other times?  */
2802173275Ssam#ifdef OBJ_AOUT
2803173275Ssam
2804173275Ssam  if (reloc->howto->pc_relative == 0
2805173275Ssam      || code == BFD_RELOC_SPARC_PC10
2806173275Ssam      || code == BFD_RELOC_SPARC_PC22)
2807173275Ssam    reloc->addend = fixp->fx_addnumber;
2808173275Ssam  else
2809173275Ssam    reloc->addend = fixp->fx_offset - reloc->address;
2810173275Ssam
2811173275Ssam#else /* elf or coff */
2812173275Ssam
2813173275Ssam  if (reloc->howto->pc_relative == 0
2814173275Ssam      || code == BFD_RELOC_SPARC_PC10
2815173275Ssam      || code == BFD_RELOC_SPARC_PC22)
2816173275Ssam    reloc->addend = fixp->fx_addnumber;
2817173275Ssam  else if ((fixp->fx_addsy->bsym->flags & BSF_SECTION_SYM) != 0)
2818173275Ssam    reloc->addend = (section->vma
2819173275Ssam		     + fixp->fx_addnumber
2820173275Ssam		     + md_pcrel_from (fixp));
2821173275Ssam  else
2822173275Ssam    reloc->addend = fixp->fx_offset;
2823173275Ssam#endif
2824173275Ssam
2825173275Ssam  return reloc;
2826173275Ssam}
2827173275Ssam
2828173275Ssam/* We have no need to default values of symbols. */
2829173275Ssam
2830173275Ssam/* ARGSUSED */
2831148686SstefanfsymbolS *
2832138593Ssammd_undefined_symbol (name)
2833138593Ssam     char *name;
2834138593Ssam{
2835138593Ssam  return 0;
2836138593Ssam}				/* md_undefined_symbol() */
2837138593Ssam
2838138593Ssam/* Round up a section size to the appropriate boundary. */
2839178354SsamvalueT
2840138593Ssammd_section_align (segment, size)
2841138593Ssam     segT segment;
2842138593Ssam     valueT size;
2843138593Ssam{
2844138593Ssam#ifndef OBJ_ELF
2845178354Ssam  /* This is not right for ELF; a.out wants it, and COFF will force
2846173275Ssam     the alignment anyways.  */
2847138593Ssam  valueT align = ((valueT) 1
2848173275Ssam		  << (valueT) bfd_get_section_alignment (stdoutput, segment));
2849173275Ssam  valueT newsize;
2850138593Ssam  /* turn alignment value into a mask */
2851138593Ssam  align--;
2852178354Ssam  newsize = (size + align) & ~align;
2853173275Ssam  return newsize;
2854173275Ssam#else
2855173275Ssam  return size;
2856173275Ssam#endif
2857173275Ssam}
2858173275Ssam
2859178354Ssam/* Exactly what point is a PC-relative offset relative TO?
2860138593Ssam   On the sparc, they're relative to the address of the offset, plus
2861138593Ssam   its size.  This gets us to the following instruction.
2862138593Ssam   (??? Is this right?  FIXME-SOON) */
2863138593Ssamlong
2864138593Ssammd_pcrel_from (fixP)
2865181454Ssam     fixS *fixP;
2866186904Ssam{
2867186904Ssam  long ret;
2868186904Ssam
2869186904Ssam  ret = fixP->fx_where + fixP->fx_frag->fr_address;
2870186904Ssam  if (! sparc_pic_code
2871186904Ssam      || fixP->fx_addsy == NULL
2872181454Ssam      || (fixP->fx_addsy->bsym->flags & BSF_SECTION_SYM) != 0)
2873181454Ssam    ret += fixP->fx_size;
2874181454Ssam  return ret;
2875181454Ssam}
2876181454Ssam
2877173275Ssam/*
2878173275Ssam * sort of like s_lcomm
2879173275Ssam */
2880173275Ssam
2881173275Ssam#ifndef OBJ_ELF
2882173275Ssamstatic int max_alignment = 15;
2883173275Ssam#endif
2884173275Ssam
2885173275Ssamstatic void
2886173275Ssams_reserve (ignore)
2887173275Ssam     int ignore;
2888173275Ssam{
2889173275Ssam  char *name;
2890173275Ssam  char *p;
2891173275Ssam  char c;
2892173275Ssam  int align;
2893173275Ssam  int size;
2894173275Ssam  int temp;
2895173275Ssam  symbolS *symbolP;
2896173275Ssam
2897173275Ssam  name = input_line_pointer;
2898173275Ssam  c = get_symbol_end ();
2899173275Ssam  p = input_line_pointer;
2900173275Ssam  *p = c;
2901173275Ssam  SKIP_WHITESPACE ();
2902138593Ssam
2903138593Ssam  if (*input_line_pointer != ',')
2904138593Ssam    {
2905138593Ssam      as_bad ("Expected comma after name");
2906138593Ssam      ignore_rest_of_line ();
2907173275Ssam      return;
2908173275Ssam    }
2909173275Ssam
2910173275Ssam  ++input_line_pointer;
2911173275Ssam
2912173275Ssam  if ((size = get_absolute_expression ()) < 0)
2913173275Ssam    {
2914173275Ssam      as_bad ("BSS length (%d.) <0! Ignored.", size);
2915173275Ssam      ignore_rest_of_line ();
2916173275Ssam      return;
2917173275Ssam    }				/* bad length */
2918173275Ssam
2919173275Ssam  *p = 0;
2920173275Ssam  symbolP = symbol_find_or_make (name);
2921173275Ssam  *p = c;
2922173275Ssam
2923173275Ssam  if (strncmp (input_line_pointer, ",\"bss\"", 6) != 0
2924173275Ssam      && strncmp (input_line_pointer, ",\".bss\"", 7) != 0)
2925173275Ssam    {
2926173275Ssam      as_bad ("bad .reserve segment -- expected BSS segment");
2927173275Ssam      return;
2928173275Ssam    }
2929138593Ssam
2930138593Ssam  if (input_line_pointer[2] == '.')
2931170531Ssam    input_line_pointer += 7;
2932173275Ssam  else
2933173275Ssam    input_line_pointer += 6;
2934173275Ssam  SKIP_WHITESPACE ();
2935173275Ssam
2936139492Ssam  if (*input_line_pointer == ',')
2937170531Ssam    {
2938181454Ssam      ++input_line_pointer;
2939181454Ssam
2940186904Ssam      SKIP_WHITESPACE ();
2941186904Ssam      if (*input_line_pointer == '\n')
2942173275Ssam	{
2943138593Ssam	  as_bad ("Missing alignment");
2944138593Ssam	  return;
2945138593Ssam	}
2946170531Ssam
2947138593Ssam      align = get_absolute_expression ();
2948173275Ssam#ifndef OBJ_ELF
2949173275Ssam      if (align > max_alignment)
2950173275Ssam	{
2951173275Ssam	  align = max_alignment;
2952173275Ssam	  as_warn ("Alignment too large: %d. assumed.", align);
2953173275Ssam	}
2954173275Ssam#endif
2955138593Ssam      if (align < 0)
2956173275Ssam	{
2957173275Ssam	  align = 0;
2958138593Ssam	  as_warn ("Alignment negative. 0 assumed.");
2959138593Ssam	}
2960138593Ssam
2961138593Ssam      record_alignment (bss_section, align);
2962138593Ssam
2963138593Ssam      /* convert to a power of 2 alignment */
2964138593Ssam      for (temp = 0; (align & 1) == 0; align >>= 1, ++temp);;
2965138593Ssam
2966178354Ssam      if (align != 1)
2967178354Ssam	{
2968178354Ssam	  as_bad ("Alignment not a power of 2");
2969178354Ssam	  ignore_rest_of_line ();
2970178354Ssam	  return;
2971178354Ssam	}			/* not a power of two */
2972178354Ssam
2973178354Ssam      align = temp;
2974178354Ssam    }				/* if has optional alignment */
2975178354Ssam  else
2976178354Ssam    align = 0;
2977178354Ssam
2978138593Ssam  if (!S_IS_DEFINED (symbolP)
2979138593Ssam#ifdef OBJ_AOUT
2980138593Ssam      && S_GET_OTHER (symbolP) == 0
2981153892Srwatson      && S_GET_DESC (symbolP) == 0
2982173275Ssam#endif
2983154522Ssam      )
2984138593Ssam    {
2985173275Ssam      if (! need_pass_2)
2986138593Ssam	{
2987138593Ssam	  char *pfrag;
2988138593Ssam	  segT current_seg = now_seg;
2989138593Ssam	  subsegT current_subseg = now_subseg;
2990170531Ssam
2991170531Ssam	  subseg_set (bss_section, 1); /* switch to bss */
2992154522Ssam
2993170531Ssam	  if (align)
2994154522Ssam	    frag_align (align, 0, 0); /* do alignment */
2995138593Ssam
2996138593Ssam	  /* detach from old frag */
2997138593Ssam	  if (S_GET_SEGMENT(symbolP) == bss_section)
2998170531Ssam	    symbolP->sy_frag->fr_symbol = NULL;
2999138593Ssam
3000138593Ssam	  symbolP->sy_frag = frag_now;
3001138593Ssam	  pfrag = frag_var (rs_org, 1, 1, (relax_substateT)0, symbolP,
3002138593Ssam			    (offsetT) size, (char *)0);
3003138593Ssam	  *pfrag = 0;
3004170531Ssam
3005170531Ssam	  S_SET_SEGMENT (symbolP, bss_section);
3006138593Ssam
3007170531Ssam	  subseg_set (current_seg, current_subseg);
3008173275Ssam	}
3009170531Ssam    }
3010154522Ssam  else
3011155461Ssam    {
3012154522Ssam      as_warn("Ignoring attempt to re-define symbol %s",
3013138593Ssam	      S_GET_NAME (symbolP));
3014165570Ssam    }				/* if not redefining */
3015138593Ssam
3016170531Ssam  demand_empty_rest_of_line ();
3017138593Ssam}
3018138593Ssam
3019138593Ssamstatic void
3020170531Ssams_common (ignore)
3021138593Ssam     int ignore;
3022138593Ssam{
3023138593Ssam  char *name;
3024138593Ssam  char c;
3025138593Ssam  char *p;
3026138593Ssam  int temp, size;
3027138593Ssam  symbolS *symbolP;
3028138593Ssam
3029178354Ssam  name = input_line_pointer;
3030138593Ssam  c = get_symbol_end ();
3031138593Ssam  /* just after name is now '\0' */
3032138593Ssam  p = input_line_pointer;
3033138593Ssam  *p = c;
3034138593Ssam  SKIP_WHITESPACE ();
3035138593Ssam  if (*input_line_pointer != ',')
3036138593Ssam    {
3037138593Ssam      as_bad ("Expected comma after symbol-name");
3038138593Ssam      ignore_rest_of_line ();
3039138593Ssam      return;
3040138593Ssam    }
3041178354Ssam  input_line_pointer++;		/* skip ',' */
3042178354Ssam  if ((temp = get_absolute_expression ()) < 0)
3043178354Ssam    {
3044178354Ssam      as_bad (".COMMon length (%d.) <0! Ignored.", temp);
3045178354Ssam      ignore_rest_of_line ();
3046178354Ssam      return;
3047178354Ssam    }
3048178354Ssam  size = temp;
3049178354Ssam  *p = 0;
3050178354Ssam  symbolP = symbol_find_or_make (name);
3051138593Ssam  *p = c;
3052138593Ssam  if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
3053138593Ssam    {
3054138593Ssam      as_bad ("Ignoring attempt to re-define symbol");
3055138593Ssam      ignore_rest_of_line ();
3056138593Ssam      return;
3057138593Ssam    }
3058138593Ssam  if (S_GET_VALUE (symbolP) != 0)
3059138593Ssam    {
3060138593Ssam      if (S_GET_VALUE (symbolP) != (valueT) size)
3061138593Ssam	{
3062138593Ssam	  as_warn ("Length of .comm \"%s\" is already %ld. Not changed to %d.",
3063138593Ssam		   S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size);
3064138593Ssam	}
3065138593Ssam    }
3066138593Ssam  else
3067138593Ssam    {
3068138593Ssam#ifndef OBJ_ELF
3069138593Ssam      S_SET_VALUE (symbolP, (valueT) size);
3070138593Ssam      S_SET_EXTERNAL (symbolP);
3071138593Ssam#endif
3072138593Ssam    }
3073138593Ssam  know (symbolP->sy_frag == &zero_address_frag);
3074138593Ssam  if (*input_line_pointer != ',')
3075138593Ssam    {
3076138593Ssam      as_bad ("Expected comma after common length");
3077138593Ssam      ignore_rest_of_line ();
3078138593Ssam      return;
3079161147Ssam    }
3080161147Ssam  input_line_pointer++;
3081173275Ssam  SKIP_WHITESPACE ();
3082173275Ssam  if (*input_line_pointer != '"')
3083173275Ssam    {
3084173275Ssam      temp = get_absolute_expression ();
3085173275Ssam#ifndef OBJ_ELF
3086173275Ssam      if (temp > max_alignment)
3087173275Ssam	{
3088173275Ssam	  temp = max_alignment;
3089173275Ssam	  as_warn ("Common alignment too large: %d. assumed", temp);
3090173275Ssam	}
3091173275Ssam#endif
3092173275Ssam      if (temp < 0)
3093173275Ssam	{
3094173275Ssam	  temp = 0;
3095173275Ssam	  as_warn ("Common alignment negative; 0 assumed");
3096173275Ssam	}
3097173275Ssam#ifdef OBJ_ELF
3098173275Ssam      if (symbolP->local)
3099173275Ssam	{
3100173275Ssam	  segT old_sec;
3101173275Ssam	  int old_subsec;
3102173275Ssam	  char *p;
3103173275Ssam	  int align;
3104173275Ssam
3105173275Ssam	  old_sec = now_seg;
3106173275Ssam	  old_subsec = now_subseg;
3107173275Ssam	  align = temp;
3108173275Ssam	  record_alignment (bss_section, align);
3109173275Ssam	  subseg_set (bss_section, 0);
3110173275Ssam	  if (align)
3111173275Ssam	    frag_align (align, 0, 0);
3112173275Ssam	  if (S_GET_SEGMENT (symbolP) == bss_section)
3113173275Ssam	    symbolP->sy_frag->fr_symbol = 0;
3114173275Ssam	  symbolP->sy_frag = frag_now;
3115173275Ssam	  p = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
3116173275Ssam			(offsetT) size, (char *) 0);
3117138593Ssam	  *p = 0;
3118138593Ssam	  S_SET_SEGMENT (symbolP, bss_section);
3119138593Ssam	  S_CLEAR_EXTERNAL (symbolP);
3120161147Ssam	  subseg_set (old_sec, old_subsec);
3121161147Ssam	}
3122161147Ssam      else
3123161147Ssam#endif
3124161147Ssam	{
3125170531Ssam	allocate_common:
3126138593Ssam	  S_SET_VALUE (symbolP, (valueT) size);
3127138593Ssam#ifdef OBJ_ELF
3128161147Ssam	  S_SET_ALIGN (symbolP, temp);
3129161147Ssam#endif
3130161147Ssam	  S_SET_EXTERNAL (symbolP);
3131161147Ssam	  S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
3132161147Ssam	}
3133161147Ssam    }
3134173275Ssam  else
3135173275Ssam    {
3136161147Ssam      input_line_pointer++;
3137173275Ssam      /* @@ Some use the dot, some don't.  Can we get some consistency??  */
3138138593Ssam      if (*input_line_pointer == '.')
3139138593Ssam	input_line_pointer++;
3140138593Ssam      /* @@ Some say data, some say bss.  */
3141138593Ssam      if (strncmp (input_line_pointer, "bss\"", 4)
3142170531Ssam	  && strncmp (input_line_pointer, "data\"", 5))
3143170531Ssam	{
3144159885Ssam	  while (*--input_line_pointer != '"')
3145138593Ssam	    ;
3146138593Ssam	  input_line_pointer--;
3147138593Ssam	  goto bad_common_segment;
3148138593Ssam	}
3149138593Ssam      while (*input_line_pointer++ != '"')
3150138593Ssam	;
3151138593Ssam      goto allocate_common;
3152138593Ssam    }
3153138593Ssam
3154159885Ssam#ifdef BFD_ASSEMBLER
3155138593Ssam  symbolP->bsym->flags |= BSF_OBJECT;
3156170531Ssam#endif
3157138593Ssam
3158170531Ssam  demand_empty_rest_of_line ();
3159138593Ssam  return;
3160170531Ssam
3161161147Ssam  {
3162161147Ssam  bad_common_segment:
3163170531Ssam    p = input_line_pointer;
3164138593Ssam    while (*p && *p != '\n')
3165138593Ssam      p++;
3166166015Ssam    c = *p;
3167178354Ssam    *p = '\0';
3168170531Ssam    as_bad ("bad .common segment %s", input_line_pointer + 1);
3169138593Ssam    *p = c;
3170173275Ssam    input_line_pointer = p;
3171173275Ssam    ignore_rest_of_line ();
3172138593Ssam    return;
3173159885Ssam  }
3174138593Ssam}
3175170531Ssam
3176178354Ssam/* Handle the .empty pseudo-op.  This supresses the warnings about
3177138593Ssam   invalid delay slot usage.  */
3178138593Ssam
3179138593Ssamstatic void
3180138593Ssams_empty (ignore)
3181138593Ssam     int ignore;
3182170531Ssam{
3183170531Ssam  /* The easy way to implement is to just forget about the last
3184170531Ssam     instruction.  */
3185138593Ssam  last_insn = NULL;
3186138593Ssam}
3187138593Ssam
3188170531Ssamstatic void
3189187843Ssams_seg (ignore)
3190187843Ssam     int ignore;
3191187843Ssam{
3192187843Ssam
3193187843Ssam  if (strncmp (input_line_pointer, "\"text\"", 6) == 0)
3194170531Ssam    {
3195187843Ssam      input_line_pointer += 6;
3196187843Ssam      s_text (0);
3197187843Ssam      return;
3198187843Ssam    }
3199170531Ssam  if (strncmp (input_line_pointer, "\"data\"", 6) == 0)
3200170531Ssam    {
3201170531Ssam      input_line_pointer += 6;
3202170531Ssam      s_data (0);
3203170531Ssam      return;
3204170531Ssam    }
3205170531Ssam  if (strncmp (input_line_pointer, "\"data1\"", 7) == 0)
3206170531Ssam    {
3207170531Ssam      input_line_pointer += 7;
3208170531Ssam      s_data1 ();
3209170531Ssam      return;
3210170531Ssam    }
3211170531Ssam  if (strncmp (input_line_pointer, "\"bss\"", 5) == 0)
3212170531Ssam    {
3213170531Ssam      input_line_pointer += 5;
3214170531Ssam      /* We only support 2 segments -- text and data -- for now, so
3215170531Ssam	 things in the "bss segment" will have to go into data for now.
3216173275Ssam	 You can still allocate SEG_BSS stuff with .lcomm or .reserve. */
3217170531Ssam      subseg_set (data_section, 255);	/* FIXME-SOMEDAY */
3218170531Ssam      return;
3219170531Ssam    }
3220138593Ssam  as_bad ("Unknown segment type");
3221165570Ssam  demand_empty_rest_of_line ();
3222170531Ssam}
3223173275Ssam
3224138593Ssamstatic void
3225138593Ssams_data1 ()
3226187844Ssam{
3227187844Ssam  subseg_set (data_section, 1);
3228187844Ssam  demand_empty_rest_of_line ();
3229187844Ssam}
3230187844Ssam
3231187844Ssamstatic void
3232187844Ssams_proc (ignore)
3233187844Ssam     int ignore;
3234187844Ssam{
3235187844Ssam  while (!is_end_of_line[(unsigned char) *input_line_pointer])
3236187844Ssam    {
3237187844Ssam      ++input_line_pointer;
3238187844Ssam    }
3239187844Ssam  ++input_line_pointer;
3240187844Ssam}
3241187844Ssam
3242187844Ssam/* This static variable is set by s_uacons to tell sparc_cons_align
3243187844Ssam   that the expession does not need to be aligned.  */
3244187844Ssam
3245187844Ssamstatic int sparc_no_align_cons = 0;
3246187844Ssam
3247187844Ssam/* This handles the unaligned space allocation pseudo-ops, such as
3248187844Ssam   .uaword.  .uaword is just like .word, but the value does not need
3249187844Ssam   to be aligned.  */
3250138593Ssam
3251173275Ssamstatic void
3252173275Ssams_uacons (bytes)
3253138593Ssam     int bytes;
3254187801Ssam{
3255170531Ssam  /* Tell sparc_cons_align not to align this value.  */
3256138593Ssam  sparc_no_align_cons = 1;
3257170531Ssam  cons (bytes);
3258138593Ssam}
3259187801Ssam
3260187801Ssam/* If the --enforce-aligned-data option is used, we require .word,
3261187801Ssam   et. al., to be aligned correctly.  We do it by setting up an
3262187801Ssam   rs_align_code frag, and checking in HANDLE_ALIGN to make sure that
3263170531Ssam   no unexpected alignment was introduced.
3264138593Ssam
3265138593Ssam   The SunOS and Solaris native assemblers enforce aligned data by
3266138593Ssam   default.  We don't want to do that, because gcc can deliberately
3267173275Ssam   generate misaligned data if the packed attribute is used.  Instead,
3268138593Ssam   we permit misaligned data by default, and permit the user to set an
3269173275Ssam   option to check for it.  */
3270173275Ssam
3271170531Ssamvoid
3272170531Ssamsparc_cons_align (nbytes)
3273170531Ssam     int nbytes;
3274170531Ssam{
3275170531Ssam  int nalign;
3276170531Ssam  char *p;
3277170531Ssam
3278170531Ssam  /* Only do this if we are enforcing aligned data.  */
3279173275Ssam  if (! enforce_aligned_data)
3280170531Ssam    return;
3281187801Ssam
3282170531Ssam  if (sparc_no_align_cons)
3283187801Ssam    {
3284170531Ssam      /* This is an unaligned pseudo-op.  */
3285170531Ssam      sparc_no_align_cons = 0;
3286138593Ssam      return;
3287170531Ssam    }
3288173275Ssam
3289173275Ssam  nalign = 0;
3290170531Ssam  while ((nbytes & 1) == 0)
3291173275Ssam    {
3292170531Ssam      ++nalign;
3293187844Ssam      nbytes >>= 1;
3294187844Ssam    }
3295187844Ssam
3296187844Ssam  if (nalign == 0)
3297170531Ssam    return;
3298187801Ssam
3299170531Ssam  if (now_seg == absolute_section)
3300170531Ssam    {
3301170531Ssam      if ((abs_section_offset & ((1 << nalign) - 1)) != 0)
3302170531Ssam	as_bad ("misaligned data");
3303187801Ssam      return;
3304187801Ssam    }
3305138593Ssam
3306170531Ssam  p = frag_var (rs_align_code, 1, 1, (relax_substateT) 0,
3307187801Ssam		(symbolS *) NULL, (offsetT) nalign, (char *) NULL);
3308187801Ssam
3309187801Ssam  record_alignment (now_seg, nalign);
3310138593Ssam}
3311138593Ssam
3312187801Ssam/* This is where we do the unexpected alignment check.
3313187801Ssam   This is called from HANDLE_ALIGN in tc-sparc.h.  */
3314138593Ssam
3315138593Ssamvoid
3316187801Ssamsparc_handle_align (fragp)
3317138593Ssam     fragS *fragp;
3318138593Ssam{
3319138593Ssam  if (fragp->fr_type == rs_align_code && !fragp->fr_subtype
3320173275Ssam      && fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix != 0)
3321173275Ssam    as_bad_where (fragp->fr_file, fragp->fr_line, "misaligned data");
3322173275Ssam  if (fragp->fr_type == rs_align_code && fragp->fr_subtype == 1024)
3323187801Ssam    {
3324173275Ssam      int count = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
3325173275Ssam
3326173275Ssam      if (count >= 4 && !(count & 3) && count <= 1024 && !((long)(fragp->fr_literal + fragp->fr_fix) & 3))
3327170531Ssam        {
3328170531Ssam          unsigned *p = (unsigned *)(fragp->fr_literal + fragp->fr_fix);
3329170531Ssam          int i;
3330170531Ssam
3331170531Ssam          for (i = 0; i < count; i += 4)
3332170531Ssam            *p++ = 0x01000000; /* nop */
3333170531Ssam          if (SPARC_OPCODE_ARCH_V9_P (max_architecture) && count > 8)
3334170531Ssam            *(unsigned *)(fragp->fr_literal + fragp->fr_fix) =
3335170531Ssam              0x30680000 | (count >> 2); /* ba,a,pt %xcc, 1f */
3336170531Ssam          fragp->fr_var = count;
3337173275Ssam        }
3338170531Ssam    }
3339170531Ssam}
3340170531Ssam
3341170531Ssam#ifdef OBJ_ELF
3342170531Ssam/* Some special processing for a Sparc ELF file.  */
3343170531Ssam
3344170531Ssamvoid
3345170531Ssamsparc_elf_final_processing ()
3346170531Ssam{
3347170531Ssam  /* Set the Sparc ELF flag bits.  FIXME: There should probably be some
3348187801Ssam     sort of BFD interface for this.  */
3349170531Ssam  if (sparc_arch_size == 64)
3350170531Ssam    switch (sparc_memory_model)
3351170531Ssam      {
3352170531Ssam      case MM_RMO:
3353170531Ssam        elf_elfheader (stdoutput)->e_flags |= EF_SPARCV9_RMO;
3354187801Ssam        break;
3355187801Ssam      case MM_PSO:
3356187801Ssam        elf_elfheader (stdoutput)->e_flags |= EF_SPARCV9_PSO;
3357187801Ssam        break;
3358170531Ssam      }
3359187801Ssam  else if (current_architecture >= SPARC_OPCODE_ARCH_V9)
3360187801Ssam    elf_elfheader (stdoutput)->e_flags |= EF_SPARC_32PLUS;
3361170531Ssam  if (current_architecture == SPARC_OPCODE_ARCH_V9A)
3362170531Ssam    elf_elfheader (stdoutput)->e_flags |= EF_SPARC_SUN_US1;
3363170531Ssam}
3364187801Ssam#endif
3365170531Ssam