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