X-Git-Url: http://drtracing.org/?a=blobdiff_plain;ds=sidebyside;f=gas%2Fconfig%2Ftc-sparc.c;h=1114afa139d1091ab1924a60250d54184391e03f;hb=add39d2344036db9334bdeb1ec20a90beaa3ca49;hp=d35b1882043725f0c614b9fe1f16937a36e8b247;hpb=668b27eacf911204998fe203a610d4d101f45d06;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-sparc.c b/gas/config/tc-sparc.c index d35b188204..1114afa139 100644 --- a/gas/config/tc-sparc.c +++ b/gas/config/tc-sparc.c @@ -1,8 +1,5 @@ /* tc-sparc.c -- Assemble for the SPARC - Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, - 2011 - Free Software Foundation, Inc. + Copyright (C) 1989-2016 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify @@ -50,7 +47,7 @@ static int get_expression (char *); #ifndef DEFAULT_ARCH #define DEFAULT_ARCH "sparclite" #endif -static char *default_arch = DEFAULT_ARCH; +static const char *default_arch = DEFAULT_ARCH; /* Non-zero if the initial values of `max_architecture' and `sparc_arch_size' have been set. */ @@ -80,11 +77,11 @@ static enum { MM_TSO, MM_PSO, MM_RMO } sparc_memory_model = MM_RMO; #ifndef TE_SOLARIS /* Bitmask of instruction types seen so far, used to populate the GNU attributes section with hwcap information. */ -static int hwcap_seen; +static bfd_uint64_t hwcap_seen; #endif #endif -static int hwcap_allowed; +static bfd_uint64_t hwcap_allowed; static int architecture_requested; static int warn_on_bump; @@ -203,7 +200,7 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP"; struct sparc_it { - char *error; + const char *error; unsigned long opcode; struct nlist *nlistp; expressionS exp; @@ -221,12 +218,31 @@ static void output_insn (const struct sparc_opcode *, struct sparc_it *); for this use. That table is for opcodes only. This table is for opcodes and file formats. */ -enum sparc_arch_types {v6, v7, v8, sparclet, sparclite, sparc86x, v8plus, +enum sparc_arch_types {v6, v7, v8, leon, sparclet, sparclite, sparc86x, v8plus, v8plusa, v9, v9a, v9b, v9_64}; +/* Hardware capability sets, used to keep sparc_arch_table easy to + read. */ +#define HWS_V8 HWCAP_MUL32 | HWCAP_DIV32 | HWCAP_FSMULD +#define HWS_V9 HWS_V8 | HWCAP_POPC +#define HWS_VA HWS_V9 | HWCAP_VIS +#define HWS_VB HWS_VA | HWCAP_VIS2 +#define HWS_VC HWS_VB | HWCAP_ASI_BLK_INIT +#define HWS_VD HWS_VC | HWCAP_FMAF | HWCAP_VIS3 | HWCAP_HPC +#define HWS_VE HWS_VD \ + | HWCAP_AES | HWCAP_DES | HWCAP_KASUMI | HWCAP_CAMELLIA \ + | HWCAP_MD5 | HWCAP_SHA1 | HWCAP_SHA256 |HWCAP_SHA512 | HWCAP_MPMUL \ + | HWCAP_MONT | HWCAP_CRC32C | HWCAP_CBCOND | HWCAP_PAUSE +#define HWS_VV HWS_VE | HWCAP_FJFMAU | HWCAP_IMA +#define HWS_VM HWS_VV + +#define HWS2_VM \ + HWCAP2_VIS3B | HWCAP2_ADP | HWCAP2_SPARC5 | HWCAP2_MWAIT \ + | HWCAP2_XMPMUL | HWCAP2_XMONT + static struct sparc_arch { - char *name; - char *opcode_arch; + const char *name; + const char *opcode_arch; enum sparc_arch_types arch_type; /* Default word size, as specified during configuration. A value of zero means can't be used to specify default architecture. */ @@ -234,47 +250,57 @@ static struct sparc_arch { /* Allowable arg to -A? */ int user_option_p; int hwcap_allowed; + int hwcap2_allowed; } sparc_arch_table[] = { - { "v6", "v6", v6, 0, 1, 0 }, - { "v7", "v7", v7, 0, 1, 0 }, - { "v8", "v8", v8, 32, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD }, - { "v8a", "v8", v8, 32, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD }, - { "sparc", "v9", v9, 0, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD|HWCAP_POPC|HWCAP_V8PLUS }, - { "sparcvis", "v9a", v9, 0, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD|HWCAP_POPC|HWCAP_VIS }, - { "sparcvis2", "v9b", v9, 0, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD|HWCAP_POPC|HWCAP_VIS|HWCAP_VIS2 }, - { "sparcfmaf", "v9b", v9, 0, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD|HWCAP_POPC|HWCAP_VIS|HWCAP_VIS2|HWCAP_FMAF }, - { "sparcima", "v9b", v9, 0, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD|HWCAP_POPC|HWCAP_VIS|HWCAP_VIS2|HWCAP_FMAF|HWCAP_IMA }, - { "sparcvis3", "v9b", v9, 0, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD|HWCAP_POPC|HWCAP_VIS|HWCAP_VIS2|HWCAP_FMAF|HWCAP_VIS3|HWCAP_HPC }, - { "sparc4", "v9b", v9, 0, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD|HWCAP_POPC|HWCAP_VIS|HWCAP_VIS2|HWCAP_FMAF|HWCAP_VIS3|HWCAP_HPC|HWCAP_RANDOM|HWCAP_TRANS|HWCAP_FJFMAU|HWCAP_AES|HWCAP_DES|HWCAP_KASUMI|HWCAP_CAMELLIA|HWCAP_MD5|HWCAP_SHA1|HWCAP_SHA256|HWCAP_SHA512|HWCAP_MPMUL|HWCAP_MONT|HWCAP_CRC32C|HWCAP_CBCOND|HWCAP_PAUSE }, - { "sparcvis3r", "v9b", v9, 0, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD|HWCAP_POPC|HWCAP_VIS|HWCAP_VIS2|HWCAP_FMAF|HWCAP_VIS3|HWCAP_HPC|HWCAP_RANDOM|HWCAP_TRANS|HWCAP_FJFMAU }, - { "sparclet", "sparclet", sparclet, 32, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD }, - { "sparclite", "sparclite", sparclite, 32, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD }, - { "sparc86x", "sparclite", sparc86x, 32, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD }, - { "v8plus", "v9", v9, 0, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD|HWCAP_POPC|HWCAP_V8PLUS }, - { "v8plusa", "v9a", v9, 0, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD|HWCAP_POPC|HWCAP_V8PLUS|HWCAP_VIS }, - { "v8plusb", "v9b", v9, 0, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD|HWCAP_POPC|HWCAP_V8PLUS|HWCAP_VIS|HWCAP_VIS2 }, - { "v8plusc", "v9b", v9, 0, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD|HWCAP_POPC|HWCAP_V8PLUS|HWCAP_VIS|HWCAP_VIS2|HWCAP_ASI_BLK_INIT }, - { "v8plusd", "v9b", v9, 0, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD|HWCAP_POPC|HWCAP_V8PLUS|HWCAP_VIS|HWCAP_VIS2|HWCAP_ASI_BLK_INIT|HWCAP_FMAF|HWCAP_VIS3|HWCAP_HPC }, - { "v8pluse", "v9b", v9, 0, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD|HWCAP_POPC|HWCAP_V8PLUS|HWCAP_VIS|HWCAP_VIS2|HWCAP_ASI_BLK_INIT|HWCAP_FMAF|HWCAP_VIS3|HWCAP_HPC|HWCAP_AES|HWCAP_DES|HWCAP_KASUMI|HWCAP_CAMELLIA|HWCAP_MD5|HWCAP_SHA1|HWCAP_SHA256|HWCAP_SHA512|HWCAP_MPMUL|HWCAP_MONT|HWCAP_CRC32C|HWCAP_CBCOND|HWCAP_PAUSE }, - { "v8plusv", "v9b", v9, 0, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD|HWCAP_POPC|HWCAP_V8PLUS|HWCAP_VIS|HWCAP_VIS2|HWCAP_ASI_BLK_INIT|HWCAP_FMAF|HWCAP_VIS3|HWCAP_HPC|HWCAP_RANDOM|HWCAP_TRANS|HWCAP_FJFMAU|HWCAP_IMA|HWCAP_ASI_CACHE_SPARING|HWCAP_AES|HWCAP_DES|HWCAP_KASUMI|HWCAP_CAMELLIA|HWCAP_MD5|HWCAP_SHA1|HWCAP_SHA256|HWCAP_SHA512|HWCAP_MPMUL|HWCAP_MONT|HWCAP_CRC32C|HWCAP_CBCOND|HWCAP_PAUSE }, - { "v9", "v9", v9, 0, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD|HWCAP_POPC }, - { "v9a", "v9a", v9, 0, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD|HWCAP_POPC|HWCAP_VIS }, - { "v9b", "v9b", v9, 0, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD|HWCAP_POPC|HWCAP_VIS|HWCAP_VIS2 }, - { "v9c", "v9b", v9, 0, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD|HWCAP_POPC|HWCAP_VIS|HWCAP_VIS2|HWCAP_ASI_BLK_INIT }, - { "v9d", "v9b", v9, 0, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD|HWCAP_POPC|HWCAP_VIS|HWCAP_VIS2|HWCAP_ASI_BLK_INIT|HWCAP_FMAF|HWCAP_VIS3|HWCAP_HPC }, - { "v9e", "v9b", v9, 0, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD|HWCAP_POPC|HWCAP_VIS|HWCAP_VIS2|HWCAP_ASI_BLK_INIT|HWCAP_FMAF|HWCAP_VIS3|HWCAP_HPC|HWCAP_AES|HWCAP_DES|HWCAP_KASUMI|HWCAP_CAMELLIA|HWCAP_MD5|HWCAP_SHA1|HWCAP_SHA256|HWCAP_SHA512|HWCAP_MPMUL|HWCAP_MONT|HWCAP_CRC32C|HWCAP_CBCOND|HWCAP_PAUSE }, - { "v9v", "v9b", v9, 0, 1, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD|HWCAP_POPC|HWCAP_VIS|HWCAP_VIS2|HWCAP_ASI_BLK_INIT|HWCAP_FMAF|HWCAP_VIS3|HWCAP_HPC|HWCAP_RANDOM|HWCAP_TRANS|HWCAP_FJFMAU|HWCAP_IMA|HWCAP_ASI_CACHE_SPARING|HWCAP_AES|HWCAP_DES|HWCAP_KASUMI|HWCAP_CAMELLIA|HWCAP_MD5|HWCAP_SHA1|HWCAP_SHA256|HWCAP_SHA512|HWCAP_MPMUL|HWCAP_MONT|HWCAP_CRC32C|HWCAP_CBCOND|HWCAP_PAUSE }, - /* This exists to allow configure.in/Makefile.in to pass one + { "v6", "v6", v6, 0, 1, 0, 0 }, + { "v7", "v7", v7, 0, 1, 0, 0 }, + { "v8", "v8", v8, 32, 1, HWS_V8, 0 }, + { "v8a", "v8", v8, 32, 1, HWS_V8, 0 }, + { "sparc", "v9", v9, 0, 1, HWCAP_V8PLUS|HWS_V9, 0 }, + { "sparcvis", "v9a", v9, 0, 1, HWS_VA, 0 }, + { "sparcvis2", "v9b", v9, 0, 1, HWS_VB, 0 }, + { "sparcfmaf", "v9b", v9, 0, 1, HWS_VB|HWCAP_FMAF, 0 }, + { "sparcima", "v9b", v9, 0, 1, HWS_VB|HWCAP_FMAF|HWCAP_IMA, 0 }, + { "sparcvis3", "v9b", v9, 0, 1, HWS_VB|HWCAP_FMAF|HWCAP_VIS3|HWCAP_HPC, 0 }, + { "sparcvis3r", "v9b", v9, 0, 1, HWS_VB|HWCAP_FMAF|HWCAP_VIS3|HWCAP_HPC|HWCAP_FJFMAU, 0 }, + + { "sparc4", "v9b", v9, 0, 1, HWS_VV, 0 }, + { "sparc5", "v9b", v9, 0, 1, HWS_VM, HWS2_VM }, + + { "leon", "leon", leon, 32, 1, HWS_V8, 0 }, + { "sparclet", "sparclet", sparclet, 32, 1, HWS_V8, 0 }, + { "sparclite", "sparclite", sparclite, 32, 1, HWS_V8, 0 }, + { "sparc86x", "sparclite", sparc86x, 32, 1, HWS_V8, 0 }, + + { "v8plus", "v9", v9, 0, 1, HWCAP_V8PLUS|HWS_V9, 0 }, + { "v8plusa", "v9a", v9, 0, 1, HWCAP_V8PLUS|HWS_VA, 0 }, + { "v8plusb", "v9b", v9, 0, 1, HWCAP_V8PLUS|HWS_VB, 0 }, + { "v8plusc", "v9b", v9, 0, 1, HWCAP_V8PLUS|HWS_VC, 0 }, + { "v8plusd", "v9b", v9, 0, 1, HWCAP_V8PLUS|HWS_VD, 0 }, + { "v8pluse", "v9b", v9, 0, 1, HWCAP_V8PLUS|HWS_VE, 0 }, + { "v8plusv", "v9b", v9, 0, 1, HWCAP_V8PLUS|HWS_VV, 0 }, + { "v8plusm", "v9b", v9, 0, 1, HWCAP_V8PLUS|HWS_VM, 0 }, + + { "v9", "v9", v9, 0, 1, HWS_V9, 0 }, + { "v9a", "v9a", v9, 0, 1, HWS_VA, 0 }, + { "v9b", "v9b", v9, 0, 1, HWS_VB, 0 }, + { "v9c", "v9b", v9, 0, 1, HWS_VC, 0 }, + { "v9d", "v9b", v9, 0, 1, HWS_VD, 0 }, + { "v9e", "v9b", v9, 0, 1, HWS_VE, 0 }, + { "v9v", "v9b", v9, 0, 1, HWS_VV, 0 }, + { "v9m", "v9b", v9, 0, 1, HWS_VM, HWS2_VM }, + + /* This exists to allow configure.tgt to pass one value to specify both the default machine and default word size. */ - { "v9-64", "v9", v9, 64, 0, HWCAP_MUL32|HWCAP_DIV32|HWCAP_FSMULD|HWCAP_POPC }, - { NULL, NULL, v8, 0, 0, 0 } + { "v9-64", "v9", v9, 64, 0, HWS_V9, 0 }, + { NULL, NULL, v8, 0, 0, 0, 0 } }; /* Variant of default_arch */ static enum sparc_arch_types default_arch_type; static struct sparc_arch * -lookup_arch (char *name) +lookup_arch (const char *name) { struct sparc_arch *sa; @@ -363,7 +389,7 @@ sparc_target_format (void) * -bump * Warn on architecture bumps. See also -A. * - * -Av6, -Av7, -Av8, -Asparclite, -Asparclet + * -Av6, -Av7, -Av8, -Aleon, -Asparclite, -Asparclet * Standard 32 bit architectures. * -Av9, -Av9a, -Av9b * Sparc64 in either a 32 or 64 bit world (-32/-64 says which). @@ -464,7 +490,7 @@ struct option md_longopts[] = { size_t md_longopts_size = sizeof (md_longopts); int -md_parse_option (int c, char *arg) +md_parse_option (int c, const char *arg) { /* We don't get a chance to initialize anything before we're called, so handle that now. */ @@ -518,7 +544,8 @@ md_parse_option (int c, char *arg) if (!architecture_requested || opcode_arch > max_architecture) max_architecture = opcode_arch; - hwcap_allowed |= sa->hwcap_allowed; + hwcap_allowed + |= (((bfd_uint64_t) sa->hwcap2_allowed) << 32) | sa->hwcap_allowed; architecture_requested = 1; } break; @@ -731,11 +758,11 @@ md_show_usage (FILE *stream) } /* Native operand size opcode translation. */ -struct +static struct { - char *name; - char *name32; - char *name64; + const char *name; + const char *name32; + const char *name64; } native_op_table[] = { {"ldn", "ld", "ldx"}, @@ -755,7 +782,7 @@ struct struct priv_reg_entry { - char *name; + const char *name; int regnum; }; @@ -778,6 +805,7 @@ struct priv_reg_entry priv_reg_table[] = {"wstate", 14}, {"fq", 15}, {"gl", 16}, + {"pmcdper", 23}, {"ver", 31}, {"", -1}, /* End marker. */ }; @@ -789,6 +817,8 @@ struct priv_reg_entry hpriv_reg_table[] = {"hintp", 3}, {"htba", 5}, {"hver", 6}, + {"hstick_offset", 28}, + {"hstick_enable", 29}, {"hstick_cmpr", 31}, {"", -1}, /* End marker. */ }; @@ -810,9 +840,9 @@ struct priv_reg_entry v9a_asr_table[] = {"pause", 27}, {"pic", 17}, {"pcr", 16}, + {"mwait", 28}, {"gsr", 19}, {"dcr", 18}, - {"cps", 28}, {"cfr", 26}, {"clear_softint", 21}, {"", -1}, /* End marker. */ @@ -834,9 +864,9 @@ cmp_reg_entry (const void *parg, const void *qarg) void md_begin (void) { - register const char *retval = NULL; + const char *retval = NULL; int lose = 0; - register unsigned int i = 0; + unsigned int i = 0; /* We don't get a chance to initialize anything before md_parse_option is called, and it may not be called, so handle default initialization @@ -874,7 +904,7 @@ md_begin (void) for (i = 0; native_op_table[i].name; i++) { const struct sparc_opcode *insn; - char *name = ((sparc_arch_size == 32) + const char *name = ((sparc_arch_size == 32) ? native_op_table[i].name32 : native_op_table[i].name64); insn = (struct sparc_opcode *) hash_find (op_hash, name); @@ -916,16 +946,24 @@ md_begin (void) /* `max_architecture' records the requested architecture. Issue warnings if we go above it. */ warn_after_architecture = max_architecture; - - /* Find the highest architecture level that doesn't conflict with - the requested one. */ - for (max_architecture = SPARC_OPCODE_ARCH_MAX; - max_architecture > warn_after_architecture; - --max_architecture) - if (! SPARC_OPCODE_CONFLICT_P (max_architecture, - warn_after_architecture)) - break; } + + /* Find the highest architecture level that doesn't conflict with + the requested one. */ + + if (warn_on_bump + || !architecture_requested) + { + enum sparc_opcode_arch_val current_max_architecture + = max_architecture; + + for (max_architecture = SPARC_OPCODE_ARCH_MAX; + max_architecture > warn_after_architecture; + --max_architecture) + if (! SPARC_OPCODE_CONFLICT_P (max_architecture, + current_max_architecture)) + break; + } } /* Called after all assembly has been done. */ @@ -934,6 +972,9 @@ void sparc_md_end (void) { unsigned long mach = bfd_mach_sparc; +#if defined(OBJ_ELF) && !defined(TE_SOLARIS) + int hwcaps, hwcaps2; +#endif if (sparc_arch_size == 64) switch (current_architecture) @@ -957,8 +998,13 @@ sparc_md_end (void) bfd_set_arch_mach (stdoutput, bfd_arch_sparc, mach); #if defined(OBJ_ELF) && !defined(TE_SOLARIS) - if (hwcap_seen) - bfd_elf_add_obj_attr_int (stdoutput, OBJ_ATTR_GNU, Tag_GNU_Sparc_HWCAPS, hwcap_seen); + hwcaps = hwcap_seen & U0xffffffff; + hwcaps2 = hwcap_seen >> 32; + + if (hwcaps) + bfd_elf_add_obj_attr_int (stdoutput, OBJ_ATTR_GNU, Tag_GNU_Sparc_HWCAPS, hwcaps); + if (hwcaps2) + bfd_elf_add_obj_attr_int (stdoutput, OBJ_ATTR_GNU, Tag_GNU_Sparc_HWCAPS2, hwcaps2); #endif } @@ -1166,7 +1212,7 @@ synthetize_setsw (const struct sparc_opcode *insn) output_insn (insn, &the_insn); } -/* Handle the setsw synthetic instruction. */ +/* Handle the setx synthetic instruction. */ static void synthetize_setx (const struct sparc_opcode *insn) @@ -1414,7 +1460,7 @@ md_assemble (char *str) } static const char * -get_hwcap_name (int mask) +get_hwcap_name (bfd_uint64_t mask) { if (mask & HWCAP_MUL32) return "mul32"; @@ -1474,6 +1520,25 @@ get_hwcap_name (int mask) return "cbcond"; if (mask & HWCAP_CRC32C) return "crc32c"; + + mask = mask >> 32; + if (mask & HWCAP2_FJATHPLUS) + return "fjathplus"; + if (mask & HWCAP2_VIS3B) + return "vis3b"; + if (mask & HWCAP2_ADP) + return "adp"; + if (mask & HWCAP2_SPARC5) + return "sparc5"; + if (mask & HWCAP2_MWAIT) + return "mwait"; + if (mask & HWCAP2_XMPMUL) + return "xmpmul"; + if (mask & HWCAP2_XMONT) + return "xmont"; + if (mask & HWCAP2_NSEC) + return "nsec"; + return "UNKNOWN"; } @@ -1482,7 +1547,7 @@ get_hwcap_name (int mask) static int sparc_ip (char *str, const struct sparc_opcode **pinsn) { - char *error_message = ""; + const char *error_message = ""; char *s; const char *args; char c; @@ -1776,22 +1841,22 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn) ++s; } - if (current_architecture >= SPARC_OPCODE_ARCH_V9) - { - if (num < 16 || 31 < num) - { - error_message = _(": asr number must be between 16 and 31"); - goto error; - } - } - else - { - if (num < 0 || 31 < num) - { - error_message = _(": asr number must be between 0 and 31"); - goto error; - } - } + /* We used to check here for the asr number to + be between 16 and 31 in V9 and later, as + mandated by the section C.1.1 "Register + Names" in the SPARC spec. However, we + decided to remove this restriction as a) it + introduces problems when new V9 asr registers + are introduced, b) the Solaris assembler + doesn't implement this restriction and c) the + restriction will go away in future revisions + of the Oracle SPARC Architecture. */ + + if (num < 0 || 31 < num) + { + error_message = _(": asr number must be between 0 and 31"); + goto error; + } opcode |= (*args == 'M' ? RS1 (num) : RD (num)); continue; @@ -1909,7 +1974,8 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn) { ++s; } - if (strncmp (s, "%icc", 4) == 0) + if ((strncmp (s, "%icc", 4) == 0) + || (sparc_arch_size == 32 && strncmp (s, "%ncc", 4) == 0)) { s += 4; continue; @@ -1921,7 +1987,8 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn) { ++s; } - if (strncmp (s, "%xcc", 4) == 0) + if ((strncmp (s, "%xcc", 4) == 0) + || (sparc_arch_size == 64 && strncmp (s, "%ncc", 4) == 0)) { s += 4; continue; @@ -1998,7 +2065,7 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn) static const struct ops { /* The name as it appears in assembler. */ - char *name; + const char *name; /* strlen (name), precomputed for speed */ int len; /* The reloc this pseudo-op translates to. */ @@ -2298,11 +2365,14 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn) case 'g': case 'H': case 'J': + case '}': { char format; if (*s++ == '%' - && ((format = *s) == 'f') + && ((format = *s) == 'f' + || format == 'd' + || format == 'q') && ISDIGIT (*++s)) { for (mask = 0; ISDIGIT (*s); ++s) @@ -2313,19 +2383,23 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn) if ((*args == 'v' || *args == 'B' || *args == '5' - || *args == 'H') + || *args == 'H' + || format == 'd') && (mask & 1)) { + /* register must be even numbered */ break; - } /* register must be even numbered */ + } if ((*args == 'V' || *args == 'R' - || *args == 'J') + || *args == 'J' + || format == 'q') && (mask & 3)) { + /* register must be multiple of 4 */ break; - } /* register must be multiple of 4 */ + } if (mask >= 64) { @@ -2360,6 +2434,13 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn) break; } /* if not an 'f' register. */ + if (*args == '}' && mask != RS2 (opcode)) + { + error_message + = _(": Instruction requires frs2 and frsd must be the same register"); + goto error; + } + switch (*args) { case 'v': @@ -2382,6 +2463,7 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn) case 'g': case 'H': case 'J': + case '}': opcode |= RD (mask); continue; } /* Pack it in. */ @@ -2436,7 +2518,7 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn) { char *s1; - char *op_arg = NULL; + const char *op_arg = NULL; static expressionS op_exp; bfd_reloc_code_real_type old_reloc = the_insn.reloc; @@ -2445,7 +2527,7 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn) { static const struct ops { /* The name as it appears in assembler. */ - char *name; + const char *name; /* strlen (name), precomputed for speed */ int len; /* The reloc this pseudo-op translates to. */ @@ -2544,6 +2626,11 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn) *s1 = '\0'; (void) get_expression (s); *s1 = ')'; + if (expr_end != s1) + { + as_bad (_("Expression inside %%%s could not be parsed"), op_arg); + return special_case; + } s = s1 + 1; if (*s == ',' || *s == ']' || !*s) continue; @@ -2835,6 +2922,12 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn) s += 5; continue; + case '{': + if (strncmp (s, "%mcdper",7) != 0) + break; + s += 7; + continue; + case 'E': if (strncmp (s, "%ccr", 4) != 0) break; @@ -2925,7 +3018,8 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn) { /* We have a match. Now see if the architecture is OK. */ int needed_arch_mask = insn->architecture; - int hwcaps = insn->hwcaps; + bfd_uint64_t hwcaps + = (((bfd_uint64_t) insn->hwcaps2) << 32) | insn->hwcaps; #if defined(OBJ_ELF) && !defined(TE_SOLARIS) if (hwcaps) @@ -2963,6 +3057,7 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn) warn_after_architecture = needed_architecture; } current_architecture = needed_architecture; + hwcap_allowed |= hwcaps; } /* Conflict. */ /* ??? This seems to be a bit fragile. What if the next entry in @@ -2999,7 +3094,7 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn) return special_case; } - /* Make sure the the hwcaps used by the instruction are + /* Make sure the hwcaps used by the instruction are currently enabled. */ if (hwcaps & ~hwcap_allowed) { @@ -3144,7 +3239,7 @@ output_insn (const struct sparc_opcode *insn, struct sparc_it *theinsn) #endif } -char * +const char * md_atof (int type, char *litP, int *sizeP) { return ieee_md_atof (type, litP, sizeP, target_big_endian); @@ -3590,10 +3685,10 @@ tc_gen_reloc (asection *section, fixS *fixp) arelent *reloc; bfd_reloc_code_real_type code; - relocs[0] = reloc = (arelent *) xmalloc (sizeof (arelent)); + relocs[0] = reloc = XNEW (arelent); relocs[1] = NULL; - reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + reloc->sym_ptr_ptr = XNEW (asymbol *); *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; @@ -3798,10 +3893,10 @@ tc_gen_reloc (asection *section, fixS *fixp) on the same location. */ if (code == BFD_RELOC_SPARC_OLO10) { - relocs[1] = reloc = (arelent *) xmalloc (sizeof (arelent)); + relocs[1] = reloc = XNEW (arelent); relocs[2] = NULL; - reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + reloc->sym_ptr_ptr = XNEW (asymbol *); *reloc->sym_ptr_ptr = symbol_get_bfdsym (section_symbol (absolute_section)); reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; @@ -3892,11 +3987,10 @@ s_reserve (int ignore ATTRIBUTE_UNUSED) int temp; symbolS *symbolP; - name = input_line_pointer; - c = get_symbol_end (); + c = get_symbol_name (&name); p = input_line_pointer; *p = c; - SKIP_WHITESPACE (); + SKIP_WHITESPACE_AFTER_NAME (); if (*input_line_pointer != ',') { @@ -4034,12 +4128,11 @@ s_common (int ignore ATTRIBUTE_UNUSED) offsetT temp, size; symbolS *symbolP; - name = input_line_pointer; - c = get_symbol_end (); + c = get_symbol_name (&name); /* Just after name is now '\0'. */ p = input_line_pointer; *p = c; - SKIP_WHITESPACE (); + SKIP_WHITESPACE_AFTER_NAME (); if (*input_line_pointer != ',') { as_bad (_("Expected comma after symbol-name")); @@ -4268,11 +4361,6 @@ s_proc (int ignore ATTRIBUTE_UNUSED) static int sparc_no_align_cons = 0; -/* This static variable is set by sparc_cons to emit requested types - of relocations in cons_fix_new_sparc. */ - -static const char *sparc_cons_special_reloc; - /* This handles the unaligned space allocation pseudo-ops, such as .uaword. .uaword is just like .word, but the value does not need to be aligned. */ @@ -4310,7 +4398,7 @@ s_register (int ignore ATTRIBUTE_UNUSED) char c; int reg; int flags; - const char *regname; + char *regname; if (input_line_pointer[0] != '%' || input_line_pointer[1] != 'g' @@ -4324,20 +4412,19 @@ s_register (int ignore ATTRIBUTE_UNUSED) if (*input_line_pointer == '#') { ++input_line_pointer; - regname = input_line_pointer; - c = get_symbol_end (); + c = get_symbol_name (®name); if (strcmp (regname, "scratch") && strcmp (regname, "ignore")) as_bad (_("register syntax is .register %%g[2367],{#scratch|symbolname|#ignore}")); if (regname[0] == 'i') regname = NULL; else - regname = ""; + regname = (char *) ""; } else { - regname = input_line_pointer; - c = get_symbol_end (); + c = get_symbol_name (®name); } + if (sparc_arch_size == 64) { if (globals[reg]) @@ -4384,7 +4471,7 @@ s_register (int ignore ATTRIBUTE_UNUSED) } } - *input_line_pointer = c; + (void) restore_line_pointer (c); demand_empty_rest_of_line (); } @@ -4540,13 +4627,13 @@ sparc_elf_final_processing (void) elf_elfheader (stdoutput)->e_flags |= EF_SPARC_SUN_US1|EF_SPARC_SUN_US3; } -void +const char * sparc_cons (expressionS *exp, int size) { char *save; + const char *sparc_cons_special_reloc = NULL; SKIP_WHITESPACE (); - sparc_cons_special_reloc = NULL; save = input_line_pointer; if (input_line_pointer[0] == '%' && input_line_pointer[1] == 'r' @@ -4673,6 +4760,7 @@ sparc_cons (expressionS *exp, int size) } if (sparc_cons_special_reloc == NULL) expression (exp); + return sparc_cons_special_reloc; } #endif @@ -4685,7 +4773,8 @@ void cons_fix_new_sparc (fragS *frag, int where, unsigned int nbytes, - expressionS *exp) + expressionS *exp, + const char *sparc_cons_special_reloc) { bfd_reloc_code_real_type r; @@ -4734,7 +4823,6 @@ cons_fix_new_sparc (fragS *frag, } fix_new_exp (frag, where, (int) nbytes, exp, 0, r); - sparc_cons_special_reloc = NULL; } void @@ -4746,18 +4834,25 @@ sparc_cfi_frame_initial_instructions (void) int sparc_regname_to_dw2regnum (char *regname) { - char *p, *q; + char *q; + int i; if (!regname[0]) return -1; - q = "goli"; - p = strchr (q, regname[0]); - if (p) + switch (regname[0]) + { + case 'g': i = 0; break; + case 'o': i = 1; break; + case 'l': i = 2; break; + case 'i': i = 3; break; + default: i = -1; break; + } + if (i != -1) { if (regname[1] < '0' || regname[1] > '8' || regname[2]) return -1; - return (p - q) * 8 + regname[1] - '0'; + return i * 8 + regname[1] - '0'; } if (regname[0] == 's' && regname[1] == 'p' && !regname[2]) return 14; @@ -4768,7 +4863,7 @@ sparc_regname_to_dw2regnum (char *regname) unsigned int regnum; regnum = strtoul (regname + 1, &q, 10); - if (p == q || *q) + if (q == NULL || *q) return -1; if (regnum >= ((regname[0] == 'f' && SPARC_OPCODE_ARCH_V9_P (max_architecture)) @@ -4788,9 +4883,7 @@ sparc_regname_to_dw2regnum (char *regname) void sparc_cfi_emit_pcrel_expr (expressionS *exp, unsigned int nbytes) { - sparc_cons_special_reloc = "disp"; sparc_no_align_cons = 1; - emit_expr (exp, nbytes); + emit_expr_with_reloc (exp, nbytes, "disp"); sparc_no_align_cons = 0; - sparc_cons_special_reloc = NULL; }