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