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