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