X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-ppc.c;h=4248be79a37302992bfc6a41823d58befedef19f;hb=eb1e0e807ac769f624181bc44acdcd79d866949d;hp=a0f18d586db08e4c29c4f11499571f69c39cdbb0;hpb=0baf16f23c580c5b0ee2c93289a0fc27fe6c240f;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index a0f18d586d..4248be79a3 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -1,5 +1,5 @@ /* tc-ppc.c -- Assemble for the PowerPC or POWER (RS/6000) - Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 + Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. Written by Ian Lance Taylor, Cygnus Support. @@ -21,8 +21,8 @@ 02111-1307, USA. */ #include -#include #include "as.h" +#include "safe-ctype.h" #include "subsegs.h" #include "opcode/ppc.h" @@ -65,26 +65,21 @@ static int set_target_endian = 0; /* #ha(value) denotes the high adjusted value: bits 16 through 31 of the indicated value, compensating for #lo() being treated as a signed number. */ -#define PPC_HA(v) ((((v) >> 16) + (((v) >> 15) & 1)) & 0xffff) +#define PPC_HA(v) PPC_HI ((v) + 0x8000) /* #higher(value) denotes bits 32 through 47 of the indicated value. */ #define PPC_HIGHER(v) (((v) >> 32) & 0xffff) /* #highera(value) denotes bits 32 through 47 of the indicated value, compensating for #lo() being treated as a signed number. */ -#define PPC_HIGHERA(v) \ - ((((v) >> 32) + (((v) & 0xffff8000) == 0xffff8000)) & 0xffff) +#define PPC_HIGHERA(v) PPC_HIGHER ((v) + 0x8000) /* #highest(value) denotes bits 48 through 63 of the indicated value. */ #define PPC_HIGHEST(v) (((v) >> 48) & 0xffff) /* #highesta(value) denotes bits 48 through 63 of the indicated value, - compensating for #lo being treated as a signed number. - Generate 0xffffffff8000 with arithmetic here, for portability. */ -#define PPC_HIGHESTA(v) \ - ((((v) >> 48) \ - + (((v) & (((valueT) 1 << 48) - 0x8000)) == ((valueT) 1 << 48) - 0x8000)) \ - & 0xffff) + compensating for #lo being treated as a signed number. */ +#define PPC_HIGHESTA(v) PPC_HIGHEST ((v) + 0x8000) #define SEX16(val) ((((val) & 0xffff) ^ 0x8000) - 0x8000) @@ -618,10 +613,10 @@ register_name (expressionP) /* Find the spelling of the operand. */ start = name = input_line_pointer; - if (name[0] == '%' && isalpha (name[1])) + if (name[0] == '%' && ISALPHA (name[1])) name = ++input_line_pointer; - else if (!reg_names_p || !isalpha (name[0])) + else if (!reg_names_p || !ISALPHA (name[0])) return false; c = get_symbol_end (); @@ -704,7 +699,9 @@ static int ppc_cpu = 0; /* The size of the processor we are assembling for. This is either PPC_OPCODE_32 or PPC_OPCODE_64. */ -static unsigned long ppc_size = PPC_OPCODE_32; +static unsigned long ppc_size = (BFD_DEFAULT_TARGET_SIZE == 64 + ? PPC_OPCODE_64 + : PPC_OPCODE_32); /* Whether to target xcoff64. */ static int ppc_xcoff64 = 0; @@ -799,14 +796,14 @@ symbolS *GOT_symbol; /* Pre-defined "_GLOBAL_OFFSET_TABLE" */ #endif /* OBJ_ELF */ #ifdef OBJ_ELF -CONST char *md_shortopts = "b:l:usm:K:VQ:"; +const char *const md_shortopts = "b:l:usm:K:VQ:"; #else -CONST char *md_shortopts = "um:"; +const char *const md_shortopts = "um:"; #endif -struct option md_longopts[] = { +const struct option md_longopts[] = { {NULL, no_argument, NULL, 0} }; -size_t md_longopts_size = sizeof (md_longopts); +const size_t md_longopts_size = sizeof (md_longopts); int md_parse_option (c, arg) @@ -879,31 +876,58 @@ md_parse_option (c, arg) /* -mpwr means to assemble for the IBM POWER (RIOS1). */ else if (strcmp (arg, "pwr") == 0) ppc_cpu = PPC_OPCODE_POWER; - /* -m601 means to assemble for the Motorola PowerPC 601, which includes + /* -m601 means to assemble for the PowerPC 601, which includes instructions that are holdovers from the Power. */ else if (strcmp (arg, "601") == 0) ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_601; /* -mppc, -mppc32, -m603, and -m604 mean to assemble for the - Motorola PowerPC 603/604. */ + PowerPC 603/604. */ else if (strcmp (arg, "ppc") == 0 || strcmp (arg, "ppc32") == 0 - || strcmp (arg, "403") == 0 - || strcmp (arg, "405") == 0 || strcmp (arg, "603") == 0 || strcmp (arg, "604") == 0) ppc_cpu = PPC_OPCODE_PPC; - else if (strcmp (arg, "7400") == 0) + /* -m403 and -m405 mean to assemble for the PowerPC 403/405. */ + else if (strcmp (arg, "403") == 0 + || strcmp (arg, "405") == 0) + ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_403; + else if (strcmp (arg, "7400") == 0 + || strcmp (arg, "7410") == 0 + || strcmp (arg, "7450") == 0 + || strcmp (arg, "7455") == 0) ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC; + else if (strcmp (arg, "altivec") == 0) + { + if (ppc_cpu == 0) + ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC; + else + ppc_cpu |= PPC_OPCODE_ALTIVEC; + } /* -mppc64 and -m620 mean to assemble for the 64-bit PowerPC 620. */ else if (strcmp (arg, "ppc64") == 0 || strcmp (arg, "620") == 0) { - ppc_cpu = PPC_OPCODE_PPC; + ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_64; ppc_size = PPC_OPCODE_64; } else if (strcmp (arg, "ppc64bridge") == 0) { - ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_64_BRIDGE; + ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_64_BRIDGE | PPC_OPCODE_64; + ppc_size = PPC_OPCODE_64; + } + /* -mbooke/-mbooke32 mean enable 32-bit BookE support. */ + else if (strcmp (arg, "booke") == 0 || strcmp (arg, "booke32") == 0) + ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_BOOKE; + /* -mbooke64 means enable 64-bit BookE support. */ + else if (strcmp (arg, "booke64") == 0) + { + ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | + PPC_OPCODE_BOOKE64 | PPC_OPCODE_64; + ppc_size = PPC_OPCODE_64; + } + else if (strcmp (arg, "power4") == 0) + { + ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4; ppc_size = PPC_OPCODE_64; } /* -mcom means assemble for the common intersection between Power @@ -1008,13 +1032,20 @@ md_show_usage (stream) fprintf (stream, _("\ PowerPC options:\n\ -u ignored\n\ --mpwrx, -mpwr2 generate code for IBM POWER/2 (RIOS2)\n\ --mpwr generate code for IBM POWER (RIOS1)\n\ --m601 generate code for Motorola PowerPC 601\n\ --mppc, -mppc32, -m403, -m405, -m603, -m604\n\ - generate code for Motorola PowerPC 603/604\n\ --mppc64, -m620 generate code for Motorola PowerPC 620\n\ +-mpwrx, -mpwr2 generate code for POWER/2 (RIOS2)\n\ +-mpwr generate code for POWER (RIOS1)\n\ +-m601 generate code for PowerPC 601\n\ +-mppc, -mppc32, -m603, -m604\n\ + generate code for PowerPC 603/604\n\ +-m403, -m405 generate code for PowerPC 403/405\n\ +-m7400, -m7410, -m7450, -m7455\n\ + generate code For PowerPC 7400/7410/7450/7455\n\ +-mppc64, -m620 generate code for PowerPC 620/625/630\n\ -mppc64bridge generate code for PowerPC 64, including bridge insns\n\ +-mbooke64 generate code for 64-bit PowerPC BookE\n\ +-mbooke, mbooke32 generate code for 32-bit PowerPC BookE\n\ +-mpower4 generate code for Power4 architecture\n\ +-maltivec generate code for AltiVec\n\ -mcom generate code Power/PowerPC common instructions\n\ -many generate code for any architecture (PWR/PWRX/PPC)\n\ -mregnames Allow symbolic names for registers\n\ @@ -1106,13 +1137,19 @@ ppc_target_format () #elif TE_POWERMAC return "xcoff-powermac"; #else - return ppc_xcoff64 ? "aixcoff64-rs6000" : "aixcoff-rs6000"; +# ifdef TE_AIX5 + return (ppc_xcoff64 ? "aix5coff64-rs6000" : "aixcoff-rs6000"); +# else + return (ppc_xcoff64 ? "aixcoff64-rs6000" : "aixcoff-rs6000"); +# endif #endif #endif #ifdef OBJ_ELF + boolean is64 = BFD_DEFAULT_TARGET_SIZE == 64 && ppc_size == PPC_OPCODE_64; + return (target_big_endian - ? (BFD_DEFAULT_TARGET_SIZE == 64 ? "elf64-powerpc" : "elf32-powerpc") - : (BFD_DEFAULT_TARGET_SIZE == 64 ? "elf64-powerpcle" : "elf32-powerpcle")); + ? (is64 ? "elf64-powerpc" : "elf32-powerpc") + : (is64 ? "elf64-powerpcle" : "elf32-powerpcle")); #endif } @@ -1132,11 +1169,6 @@ md_begin () ppc_set_cpu (); #ifdef OBJ_ELF - /* If we're going to generate a 64-bit ABI file, then we need - the 64-bit capable instructions. */ - if (BFD_DEFAULT_TARGET_SIZE == 64) - ppc_size = PPC_OPCODE_64; - /* Set the ELF flags if desired. */ if (ppc_flags && !msolaris) bfd_set_private_flags (stdoutput, ppc_flags); @@ -1153,7 +1185,10 @@ md_begin () if ((op->flags & ppc_cpu) != 0 && ((op->flags & (PPC_OPCODE_32 | PPC_OPCODE_64)) == 0 || (op->flags & (PPC_OPCODE_32 | PPC_OPCODE_64)) == ppc_size - || (ppc_cpu & PPC_OPCODE_64_BRIDGE) != 0)) + || (ppc_cpu & PPC_OPCODE_64_BRIDGE) != 0) + && ((op->flags & (PPC_OPCODE_POWER4 | PPC_OPCODE_NOPOWER4)) == 0 + || ((op->flags & PPC_OPCODE_POWER4) + == (ppc_cpu & PPC_OPCODE_POWER4)))) { const char *retval; @@ -1287,7 +1322,7 @@ ppc_insert_operand (insn, operand, val, file, line) const char *errmsg; errmsg = NULL; - insn = (*operand->insert) (insn, (long) val, &errmsg); + insn = (*operand->insert) (insn, (long) val, ppc_cpu | ppc_size, &errmsg); if (errmsg != (const char *) NULL) as_bad_where (file, line, errmsg); } @@ -1309,7 +1344,7 @@ ppc_elf_suffix (str_p, exp_p) struct map_bfd { char *string; int length; - bfd_reloc_code_real_type reloc; + int reloc; }; char ident[20]; @@ -1317,65 +1352,65 @@ ppc_elf_suffix (str_p, exp_p) char *str2; int ch; int len; - struct map_bfd *ptr; + const struct map_bfd *ptr; #define MAP(str,reloc) { str, sizeof (str)-1, reloc } - static struct map_bfd mapping[] = { - MAP ("l", BFD_RELOC_LO16), - MAP ("h", BFD_RELOC_HI16), - MAP ("ha", BFD_RELOC_HI16_S), - MAP ("brtaken", BFD_RELOC_PPC_B16_BRTAKEN), - MAP ("brntaken", BFD_RELOC_PPC_B16_BRNTAKEN), - MAP ("got", BFD_RELOC_16_GOTOFF), - MAP ("got@l", BFD_RELOC_LO16_GOTOFF), - MAP ("got@h", BFD_RELOC_HI16_GOTOFF), - MAP ("got@ha", BFD_RELOC_HI16_S_GOTOFF), - MAP ("fixup", BFD_RELOC_CTOR), /* warnings with -mrelocatable */ - MAP ("plt", BFD_RELOC_24_PLT_PCREL), - MAP ("pltrel24", BFD_RELOC_24_PLT_PCREL), - MAP ("copy", BFD_RELOC_PPC_COPY), - MAP ("globdat", BFD_RELOC_PPC_GLOB_DAT), - MAP ("local24pc", BFD_RELOC_PPC_LOCAL24PC), - MAP ("local", BFD_RELOC_PPC_LOCAL24PC), - MAP ("pltrel", BFD_RELOC_32_PLT_PCREL), - MAP ("plt@l", BFD_RELOC_LO16_PLTOFF), - MAP ("plt@h", BFD_RELOC_HI16_PLTOFF), - MAP ("plt@ha", BFD_RELOC_HI16_S_PLTOFF), - MAP ("sdarel", BFD_RELOC_GPREL16), - MAP ("sectoff", BFD_RELOC_32_BASEREL), - MAP ("sectoff@l", BFD_RELOC_LO16_BASEREL), - MAP ("sectoff@h", BFD_RELOC_HI16_BASEREL), - MAP ("sectoff@ha", BFD_RELOC_HI16_S_BASEREL), - MAP ("naddr", BFD_RELOC_PPC_EMB_NADDR32), - MAP ("naddr16", BFD_RELOC_PPC_EMB_NADDR16), - MAP ("naddr@l", BFD_RELOC_PPC_EMB_NADDR16_LO), - MAP ("naddr@h", BFD_RELOC_PPC_EMB_NADDR16_HI), - MAP ("naddr@ha", BFD_RELOC_PPC_EMB_NADDR16_HA), - MAP ("sdai16", BFD_RELOC_PPC_EMB_SDAI16), - MAP ("sda2rel", BFD_RELOC_PPC_EMB_SDA2REL), - MAP ("sda2i16", BFD_RELOC_PPC_EMB_SDA2I16), - MAP ("sda21", BFD_RELOC_PPC_EMB_SDA21), - MAP ("mrkref", BFD_RELOC_PPC_EMB_MRKREF), - MAP ("relsect", BFD_RELOC_PPC_EMB_RELSEC16), - MAP ("relsect@l", BFD_RELOC_PPC_EMB_RELST_LO), - MAP ("relsect@h", BFD_RELOC_PPC_EMB_RELST_HI), - MAP ("relsect@ha", BFD_RELOC_PPC_EMB_RELST_HA), - MAP ("bitfld", BFD_RELOC_PPC_EMB_BIT_FLD), - MAP ("relsda", BFD_RELOC_PPC_EMB_RELSDA), - MAP ("xgot", BFD_RELOC_PPC_TOC16), + static const struct map_bfd mapping[] = { + MAP ("l", (int) BFD_RELOC_LO16), + MAP ("h", (int) BFD_RELOC_HI16), + MAP ("ha", (int) BFD_RELOC_HI16_S), + MAP ("brtaken", (int) BFD_RELOC_PPC_B16_BRTAKEN), + MAP ("brntaken", (int) BFD_RELOC_PPC_B16_BRNTAKEN), + MAP ("got", (int) BFD_RELOC_16_GOTOFF), + MAP ("got@l", (int) BFD_RELOC_LO16_GOTOFF), + MAP ("got@h", (int) BFD_RELOC_HI16_GOTOFF), + MAP ("got@ha", (int) BFD_RELOC_HI16_S_GOTOFF), + MAP ("fixup", (int) BFD_RELOC_CTOR), /* warning with -mrelocatable */ + MAP ("plt", (int) BFD_RELOC_24_PLT_PCREL), + MAP ("pltrel24", (int) BFD_RELOC_24_PLT_PCREL), + MAP ("copy", (int) BFD_RELOC_PPC_COPY), + MAP ("globdat", (int) BFD_RELOC_PPC_GLOB_DAT), + MAP ("local24pc", (int) BFD_RELOC_PPC_LOCAL24PC), + MAP ("local", (int) BFD_RELOC_PPC_LOCAL24PC), + MAP ("pltrel", (int) BFD_RELOC_32_PLT_PCREL), + MAP ("plt@l", (int) BFD_RELOC_LO16_PLTOFF), + MAP ("plt@h", (int) BFD_RELOC_HI16_PLTOFF), + MAP ("plt@ha", (int) BFD_RELOC_HI16_S_PLTOFF), + MAP ("sdarel", (int) BFD_RELOC_GPREL16), + MAP ("sectoff", (int) BFD_RELOC_32_BASEREL), + MAP ("sectoff@l", (int) BFD_RELOC_LO16_BASEREL), + MAP ("sectoff@h", (int) BFD_RELOC_HI16_BASEREL), + MAP ("sectoff@ha", (int) BFD_RELOC_HI16_S_BASEREL), + MAP ("naddr", (int) BFD_RELOC_PPC_EMB_NADDR32), + MAP ("naddr16", (int) BFD_RELOC_PPC_EMB_NADDR16), + MAP ("naddr@l", (int) BFD_RELOC_PPC_EMB_NADDR16_LO), + MAP ("naddr@h", (int) BFD_RELOC_PPC_EMB_NADDR16_HI), + MAP ("naddr@ha", (int) BFD_RELOC_PPC_EMB_NADDR16_HA), + MAP ("sdai16", (int) BFD_RELOC_PPC_EMB_SDAI16), + MAP ("sda2rel", (int) BFD_RELOC_PPC_EMB_SDA2REL), + MAP ("sda2i16", (int) BFD_RELOC_PPC_EMB_SDA2I16), + MAP ("sda21", (int) BFD_RELOC_PPC_EMB_SDA21), + MAP ("mrkref", (int) BFD_RELOC_PPC_EMB_MRKREF), + MAP ("relsect", (int) BFD_RELOC_PPC_EMB_RELSEC16), + MAP ("relsect@l", (int) BFD_RELOC_PPC_EMB_RELST_LO), + MAP ("relsect@h", (int) BFD_RELOC_PPC_EMB_RELST_HI), + MAP ("relsect@ha", (int) BFD_RELOC_PPC_EMB_RELST_HA), + MAP ("bitfld", (int) BFD_RELOC_PPC_EMB_BIT_FLD), + MAP ("relsda", (int) BFD_RELOC_PPC_EMB_RELSDA), + MAP ("xgot", (int) BFD_RELOC_PPC_TOC16), #if BFD_DEFAULT_TARGET_SIZE == 64 - MAP ("higher", BFD_RELOC_PPC64_HIGHER), - MAP ("highera", BFD_RELOC_PPC64_HIGHER_S), - MAP ("highest", BFD_RELOC_PPC64_HIGHEST), - MAP ("highesta", BFD_RELOC_PPC64_HIGHEST_S), - MAP ("tocbase", BFD_RELOC_PPC64_TOC), - MAP ("toc", BFD_RELOC_PPC_TOC16), - MAP ("toc@l", BFD_RELOC_PPC64_TOC16_LO), - MAP ("toc@h", BFD_RELOC_PPC64_TOC16_HI), - MAP ("toc@ha", BFD_RELOC_PPC64_TOC16_HA), + MAP ("higher", - (int) BFD_RELOC_PPC64_HIGHER), + MAP ("highera", - (int) BFD_RELOC_PPC64_HIGHER_S), + MAP ("highest", - (int) BFD_RELOC_PPC64_HIGHEST), + MAP ("highesta", - (int) BFD_RELOC_PPC64_HIGHEST_S), + MAP ("tocbase", - (int) BFD_RELOC_PPC64_TOC), + MAP ("toc", - (int) BFD_RELOC_PPC_TOC16), + MAP ("toc@l", - (int) BFD_RELOC_PPC64_TOC16_LO), + MAP ("toc@h", - (int) BFD_RELOC_PPC64_TOC16_HI), + MAP ("toc@ha", - (int) BFD_RELOC_PPC64_TOC16_HA), #endif - { (char *) 0, 0, BFD_RELOC_UNUSED } + { (char *) 0, 0, (int) BFD_RELOC_UNUSED } }; if (*str++ != '@') @@ -1383,10 +1418,10 @@ ppc_elf_suffix (str_p, exp_p) for (ch = *str, str2 = ident; (str2 < ident + sizeof (ident) - 1 - && (isalnum (ch) || ch == '@')); + && (ISALNUM (ch) || ch == '@')); ch = *++str) { - *str2++ = (islower (ch)) ? ch : tolower (ch); + *str2++ = TOLOWER (ch); } *str2 = '\0'; @@ -1398,11 +1433,20 @@ ppc_elf_suffix (str_p, exp_p) && len == ptr->length && memcmp (ident, ptr->string, ptr->length) == 0) { + int reloc = ptr->reloc; + + if (BFD_DEFAULT_TARGET_SIZE == 64 && reloc < 0) + { + if (ppc_size != PPC_OPCODE_64) + return BFD_RELOC_UNUSED; + reloc = -reloc; + } + if (exp_p->X_add_number != 0 - && (ptr->reloc == BFD_RELOC_16_GOTOFF - || ptr->reloc == BFD_RELOC_LO16_GOTOFF - || ptr->reloc == BFD_RELOC_HI16_GOTOFF - || ptr->reloc == BFD_RELOC_HI16_S_GOTOFF)) + && (reloc == (int) BFD_RELOC_16_GOTOFF + || reloc == (int) BFD_RELOC_LO16_GOTOFF + || reloc == (int) BFD_RELOC_HI16_GOTOFF + || reloc == (int) BFD_RELOC_HI16_S_GOTOFF)) as_warn (_("identifier+constant@got means identifier@got+constant")); /* Now check for identifier@suffix+constant. */ @@ -1425,7 +1469,7 @@ ppc_elf_suffix (str_p, exp_p) *str_p = str; if (BFD_DEFAULT_TARGET_SIZE == 64 - && ptr->reloc == BFD_RELOC_PPC64_TOC + && reloc == (int) BFD_RELOC_PPC64_TOC && exp_p->X_op == O_symbol) { /* This reloc type ignores the symbol. Change the symbol @@ -1434,7 +1478,7 @@ ppc_elf_suffix (str_p, exp_p) exp_p->X_add_symbol = &abs_symbol; } - return ptr->reloc; + return (bfd_reloc_code_real_type) reloc; } return BFD_RELOC_UNUSED; @@ -1820,7 +1864,7 @@ md_assemble (str) #endif /* Get the opcode. */ - for (s = str; *s != '\0' && ! isspace (*s); s++) + for (s = str; *s != '\0' && ! ISSPACE (*s); s++) ; if (*s != '\0') *s++ = '\0'; @@ -1843,7 +1887,7 @@ md_assemble (str) insn = opcode->opcode; str = s; - while (isspace (*str)) + while (ISSPACE (*str)) ++str; /* PowerPC operands are just expressions. The only real issue is @@ -1916,7 +1960,7 @@ md_assemble (str) from the input. */ if ((operand->flags & PPC_OPERAND_FAKE) != 0) { - insn = (*operand->insert) (insn, 0L, &errmsg); + insn = (*operand->insert) (insn, 0L, ppc_cpu | ppc_size, &errmsg); if (errmsg != (const char *) NULL) as_bad (errmsg); continue; @@ -1929,7 +1973,7 @@ md_assemble (str) { if (operand->insert) { - insn = (*operand->insert) (insn, 0L, &errmsg); + insn = (*operand->insert) (insn, 0L, ppc_cpu | ppc_size, &errmsg); if (errmsg != (const char *) NULL) as_bad (errmsg); } @@ -2176,6 +2220,7 @@ md_assemble (str) } if (BFD_DEFAULT_TARGET_SIZE == 64 + && ppc_size == PPC_OPCODE_64 && (operand->flags & PPC_OPERAND_DS) != 0) { switch (reloc) @@ -2266,7 +2311,7 @@ md_assemble (str) ++str; } - while (isspace (*str)) + while (ISSPACE (*str)) ++str; if (*str != '\0') @@ -2285,7 +2330,7 @@ md_assemble (str) BFD_RELOC_UNUSED plus the operand index. This lets us easily handle fixups for any operand type, although that is admittedly not a very exciting feature. We pick a BFD reloc type in - md_apply_fix. */ + md_apply_fix3. */ for (i = 0; i < fc; i++) { const struct powerpc_operand *operand; @@ -2440,7 +2485,7 @@ ppc_section_letter (letter, ptr_msg) if (letter == 'e') return SHF_EXCLUDE; - *ptr_msg = _("Bad .section directive: want a,w,x,e in string"); + *ptr_msg = _("Bad .section directive: want a,e,w,x,M,S in string"); return 0; } @@ -3167,7 +3212,10 @@ ppc_function (ignore) } /* The .bf pseudo-op. This is just like a COFF C_FCN symbol named - ".bf". */ + ".bf". If the pseudo op .bi was seen before .bf, patch the .bi sym + with the correct line number */ + +static symbolS *saved_bi_sym = 0; static void ppc_bf (ignore) @@ -3186,6 +3234,14 @@ ppc_bf (ignore) S_SET_NUMBER_AUXILIARY (sym, 1); SA_SET_SYM_LNNO (sym, coff_line_base); + /* Line number for bi. */ + if (saved_bi_sym) + { + S_SET_VALUE (saved_bi_sym, coff_n_line_nos); + saved_bi_sym = 0; + } + + symbol_get_tc (sym)->output = 1; ppc_frob_label (sym); @@ -3219,7 +3275,8 @@ ppc_ef (ignore) /* The .bi and .ei pseudo-ops. These take a string argument and generates a C_BINCL or C_EINCL symbol, which goes at the start of - the symbol list. */ + the symbol list. The value of .bi will be know when the next .bf + is encountered. */ static void ppc_biei (ei) @@ -3249,6 +3306,12 @@ ppc_biei (ei) S_SET_STORAGE_CLASS (sym, ei ? C_EINCL : C_BINCL); symbol_get_tc (sym)->output = 1; + /* Save bi. */ + if (ei) + saved_bi_sym = 0; + else + saved_bi_sym = sym; + for (look = last_biei ? last_biei : symbol_rootP; (look != (symbolS *) NULL && (S_GET_STORAGE_CLASS (look) == C_FILE @@ -3586,6 +3649,7 @@ ppc_tc (ignore) #endif /* OBJ_XCOFF */ #ifdef OBJ_ELF + int align; /* Skip the TOC symbol name. */ while (is_part_of_name (*input_line_pointer) @@ -3596,8 +3660,9 @@ ppc_tc (ignore) ++input_line_pointer; /* Align to a four/eight byte boundary. */ - frag_align (BFD_DEFAULT_TARGET_SIZE == 64 ? 3 : 2, 0, 0); - record_alignment (now_seg, BFD_DEFAULT_TARGET_SIZE == 64 ? 3 : 2); + align = BFD_DEFAULT_TARGET_SIZE == 64 && ppc_size == PPC_OPCODE_64 ? 3 : 2; + frag_align (align, 0, 0); + record_alignment (now_seg, align); #endif /* OBJ_ELF */ if (*input_line_pointer != ',') @@ -3610,7 +3675,12 @@ ppc_tc (ignore) } /* Pseudo-op .machine. */ -/* FIXME: `.machine' is a nop for the moment. */ +/* FIXME: `.machine' is a nop for the moment. It would be nice to + accept this directive on the first line of input and set ppc_size + and the target format accordingly. Unfortunately, the target + format is selected in output-file.c:output_file_create before we + even get to md_begin, so it's not possible without changing + as.c:main. */ static void ppc_machine (ignore) @@ -3630,7 +3700,7 @@ ppc_is_toc_sym (sym) #endif #ifdef OBJ_ELF const char *sname = segment_name (S_GET_SEGMENT (sym)); - if (BFD_DEFAULT_TARGET_SIZE == 64) + if (BFD_DEFAULT_TARGET_SIZE == 64 && ppc_size == PPC_OPCODE_64) return strcmp (sname, ".toc") == 0; else return strcmp (sname, ".got") == 0; @@ -4267,8 +4337,7 @@ ppc_canonicalize_symbol_name (name) } for (s++; *s != '\0' && *s != brac; s++) - if (islower (*s)) - *s = toupper (*s); + *s = TOUPPER (*s); if (*s == '\0' || s[1] != '\0') as_bad (_("bad symbol suffix")); @@ -5029,36 +5098,33 @@ ppc_fix_adjustable (fix) that, we determine the correct reloc code and put it back in the fixup. */ -int -md_apply_fix3 (fixp, valuep, seg) - fixS *fixp; - valueT *valuep; +void +md_apply_fix3 (fixP, valP, seg) + fixS *fixP; + valueT * valP; segT seg ATTRIBUTE_UNUSED; { - valueT value; + valueT value = * valP; #ifdef OBJ_ELF - value = *valuep; - if (fixp->fx_addsy != NULL) + if (fixP->fx_addsy != NULL) { /* `*valuep' may contain the value of the symbol on which the reloc will be based; we have to remove it. */ - if (symbol_used_in_reloc_p (fixp->fx_addsy) - && S_GET_SEGMENT (fixp->fx_addsy) != absolute_section - && S_GET_SEGMENT (fixp->fx_addsy) != undefined_section - && ! bfd_is_com_section (S_GET_SEGMENT (fixp->fx_addsy))) - value -= S_GET_VALUE (fixp->fx_addsy); + if (symbol_used_in_reloc_p (fixP->fx_addsy) + && S_GET_SEGMENT (fixP->fx_addsy) != absolute_section + && S_GET_SEGMENT (fixP->fx_addsy) != undefined_section + && ! bfd_is_com_section (S_GET_SEGMENT (fixP->fx_addsy))) + value -= S_GET_VALUE (fixP->fx_addsy); /* FIXME: Why '+'? Better yet, what exactly is '*valuep' supposed to be? I think this is related to various similar FIXMEs in tc-i386.c and tc-sparc.c. */ - if (fixp->fx_pcrel) - value += fixp->fx_frag->fr_address + fixp->fx_where; + if (fixP->fx_pcrel) + value += fixP->fx_frag->fr_address + fixP->fx_where; } else - { - fixp->fx_done = 1; - } + fixP->fx_done = 1; #else /* FIXME FIXME FIXME: The value we are passed in *valuep includes the symbol values. Since we are using BFD_ASSEMBLER, if we are @@ -5070,38 +5136,37 @@ md_apply_fix3 (fixp, valuep, seg) *valuep, and must use fx_offset instead. However, if the reloc is PC relative, we do want to use *valuep since it includes the result of md_pcrel_from. This is confusing. */ - if (fixp->fx_addsy == (symbolS *) NULL) - { - value = *valuep; - fixp->fx_done = 1; - } - else if (fixp->fx_pcrel) - value = *valuep; + if (fixP->fx_addsy == (symbolS *) NULL) + fixP->fx_done = 1; + + else if (fixP->fx_pcrel) + ; + else { - value = fixp->fx_offset; - if (fixp->fx_subsy != (symbolS *) NULL) + value = fixP->fx_offset; + if (fixP->fx_subsy != (symbolS *) NULL) { - if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section) - value -= S_GET_VALUE (fixp->fx_subsy); + if (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section) + value -= S_GET_VALUE (fixP->fx_subsy); else { /* We can't actually support subtracting a symbol. */ - as_bad_where (fixp->fx_file, fixp->fx_line, + as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex")); } } } #endif - if ((int) fixp->fx_r_type >= (int) BFD_RELOC_UNUSED) + if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED) { int opindex; const struct powerpc_operand *operand; char *where; unsigned long insn; - opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED; + opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED; operand = &powerpc_operands[opindex]; @@ -5113,39 +5178,37 @@ md_apply_fix3 (fixp, valuep, seg) if ((operand->flags & PPC_OPERAND_PARENS) != 0 && operand->bits == 16 && operand->shift == 0 - && operand->insert == NULL - && fixp->fx_addsy != NULL - && symbol_get_tc (fixp->fx_addsy)->subseg != 0 - && symbol_get_tc (fixp->fx_addsy)->class != XMC_TC - && symbol_get_tc (fixp->fx_addsy)->class != XMC_TC0 - && S_GET_SEGMENT (fixp->fx_addsy) != bss_section) + && (operand->insert == NULL || ppc_xcoff64) + && fixP->fx_addsy != NULL + && symbol_get_tc (fixP->fx_addsy)->subseg != 0 + && symbol_get_tc (fixP->fx_addsy)->class != XMC_TC + && symbol_get_tc (fixP->fx_addsy)->class != XMC_TC0 + && S_GET_SEGMENT (fixP->fx_addsy) != bss_section) { - value = fixp->fx_offset; - fixp->fx_done = 1; + value = fixP->fx_offset; + fixP->fx_done = 1; } #endif /* Fetch the instruction, insert the fully resolved operand value, and stuff the instruction back again. */ - where = fixp->fx_frag->fr_literal + fixp->fx_where; + where = fixP->fx_frag->fr_literal + fixP->fx_where; if (target_big_endian) insn = bfd_getb32 ((unsigned char *) where); else insn = bfd_getl32 ((unsigned char *) where); insn = ppc_insert_operand (insn, operand, (offsetT) value, - fixp->fx_file, fixp->fx_line); + fixP->fx_file, fixP->fx_line); if (target_big_endian) bfd_putb32 ((bfd_vma) insn, (unsigned char *) where); else bfd_putl32 ((bfd_vma) insn, (unsigned char *) where); - if (fixp->fx_done) - { - /* Nothing else to do here. */ - return 1; - } + if (fixP->fx_done) + /* Nothing else to do here. */ + return; - assert (fixp->fx_addsy != NULL); + assert (fixP->fx_addsy != NULL); /* Determine a BFD reloc value based on the operand information. We are only prepared to turn a few of the operands into @@ -5153,34 +5216,35 @@ md_apply_fix3 (fixp, valuep, seg) if ((operand->flags & PPC_OPERAND_RELATIVE) != 0 && operand->bits == 26 && operand->shift == 0) - fixp->fx_r_type = BFD_RELOC_PPC_B26; + fixP->fx_r_type = BFD_RELOC_PPC_B26; else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0 && operand->bits == 16 && operand->shift == 0) - fixp->fx_r_type = BFD_RELOC_PPC_B16; + fixP->fx_r_type = BFD_RELOC_PPC_B16; else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0 && operand->bits == 26 && operand->shift == 0) - fixp->fx_r_type = BFD_RELOC_PPC_BA26; + fixP->fx_r_type = BFD_RELOC_PPC_BA26; else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0 && operand->bits == 16 && operand->shift == 0) - fixp->fx_r_type = BFD_RELOC_PPC_BA16; + fixP->fx_r_type = BFD_RELOC_PPC_BA16; #if defined (OBJ_XCOFF) || defined (OBJ_ELF) else if ((operand->flags & PPC_OPERAND_PARENS) != 0 && operand->bits == 16 && operand->shift == 0 - && ppc_is_toc_sym (fixp->fx_addsy)) + && ppc_is_toc_sym (fixP->fx_addsy)) { - fixp->fx_r_type = BFD_RELOC_PPC_TOC16; + fixP->fx_r_type = BFD_RELOC_PPC_TOC16; #ifdef OBJ_ELF if (BFD_DEFAULT_TARGET_SIZE == 64 + && ppc_size == PPC_OPCODE_64 && (operand->flags & PPC_OPERAND_DS) != 0) - fixp->fx_r_type = BFD_RELOC_PPC64_TOC16_DS; + fixP->fx_r_type = BFD_RELOC_PPC64_TOC16_DS; #endif - fixp->fx_size = 2; + fixP->fx_size = 2; if (target_big_endian) - fixp->fx_where += 2; + fixP->fx_where += 2; } #endif /* defined (OBJ_XCOFF) || defined (OBJ_ELF) */ else @@ -5190,46 +5254,50 @@ md_apply_fix3 (fixp, valuep, seg) /* Use expr_symbol_where to see if this is an expression symbol. */ - if (expr_symbol_where (fixp->fx_addsy, &sfile, &sline)) - as_bad_where (fixp->fx_file, fixp->fx_line, + if (expr_symbol_where (fixP->fx_addsy, &sfile, &sline)) + as_bad_where (fixP->fx_file, fixP->fx_line, _("unresolved expression that must be resolved")); else - as_bad_where (fixp->fx_file, fixp->fx_line, + as_bad_where (fixP->fx_file, fixP->fx_line, _("unsupported relocation against %s"), - S_GET_NAME (fixp->fx_addsy)); - fixp->fx_done = 1; - return 1; + S_GET_NAME (fixP->fx_addsy)); + fixP->fx_done = 1; + return; } } else { #ifdef OBJ_ELF - ppc_elf_validate_fix (fixp, seg); + ppc_elf_validate_fix (fixP, seg); #endif - switch (fixp->fx_r_type) + switch (fixP->fx_r_type) { case BFD_RELOC_CTOR: - /* FIXME: 32 bits even for 64-bit targets? */ + if (BFD_DEFAULT_TARGET_SIZE == 64 && ppc_size == PPC_OPCODE_64) + goto ctor64; + /* fall through */ + case BFD_RELOC_32: - if (fixp->fx_pcrel) - fixp->fx_r_type = BFD_RELOC_32_PCREL; + if (fixP->fx_pcrel) + fixP->fx_r_type = BFD_RELOC_32_PCREL; /* fall through */ case BFD_RELOC_RVA: case BFD_RELOC_32_PCREL: case BFD_RELOC_32_BASEREL: case BFD_RELOC_PPC_EMB_NADDR32: - md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where, + md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where, value, 4); break; case BFD_RELOC_64: - if (fixp->fx_pcrel) - fixp->fx_r_type = BFD_RELOC_64_PCREL; + ctor64: + if (fixP->fx_pcrel) + fixP->fx_r_type = BFD_RELOC_64_PCREL; /* fall through */ case BFD_RELOC_64_PCREL: - md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where, + md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where, value, 8); break; @@ -5264,20 +5332,20 @@ md_apply_fix3 (fixp, valuep, seg) case BFD_RELOC_PPC64_TOC16_HA: #endif #endif - if (fixp->fx_pcrel) + if (fixP->fx_pcrel) { - if (fixp->fx_addsy != NULL) - as_bad_where (fixp->fx_file, fixp->fx_line, + if (fixP->fx_addsy != NULL) + as_bad_where (fixP->fx_file, fixP->fx_line, _("cannot emit PC relative %s relocation against %s"), - bfd_get_reloc_code_name (fixp->fx_r_type), - S_GET_NAME (fixp->fx_addsy)); + bfd_get_reloc_code_name (fixP->fx_r_type), + S_GET_NAME (fixP->fx_addsy)); else - as_bad_where (fixp->fx_file, fixp->fx_line, + as_bad_where (fixP->fx_file, fixP->fx_line, _("cannot emit PC relative %s relocation"), - bfd_get_reloc_code_name (fixp->fx_r_type)); + bfd_get_reloc_code_name (fixP->fx_r_type)); } - md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where, + md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where, value, 2); break; @@ -5285,46 +5353,46 @@ md_apply_fix3 (fixp, valuep, seg) lis %r3,(L1-L2)@ha where L1 and L2 are defined later. */ case BFD_RELOC_HI16: - if (fixp->fx_pcrel) + if (fixP->fx_pcrel) abort (); - md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where, + md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where, PPC_HI (value), 2); break; case BFD_RELOC_HI16_S: - if (fixp->fx_pcrel) + if (fixP->fx_pcrel) abort (); - md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where, + md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where, PPC_HA (value), 2); break; #ifdef OBJ_ELF #if BFD_DEFAULT_TARGET_SIZE == 64 case BFD_RELOC_PPC64_HIGHER: - if (fixp->fx_pcrel) + if (fixP->fx_pcrel) abort (); - md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where, + md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where, PPC_HIGHER (value), 2); break; case BFD_RELOC_PPC64_HIGHER_S: - if (fixp->fx_pcrel) + if (fixP->fx_pcrel) abort (); - md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where, + md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where, PPC_HIGHERA (value), 2); break; case BFD_RELOC_PPC64_HIGHEST: - if (fixp->fx_pcrel) + if (fixP->fx_pcrel) abort (); - md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where, + md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where, PPC_HIGHEST (value), 2); break; case BFD_RELOC_PPC64_HIGHEST_S: - if (fixp->fx_pcrel) + if (fixP->fx_pcrel) abort (); - md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where, + md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where, PPC_HIGHESTA (value), 2); break; @@ -5339,10 +5407,10 @@ md_apply_fix3 (fixp, valuep, seg) case BFD_RELOC_PPC64_TOC16_LO_DS: case BFD_RELOC_PPC64_PLTGOT16_DS: case BFD_RELOC_PPC64_PLTGOT16_LO_DS: - if (fixp->fx_pcrel) + if (fixP->fx_pcrel) abort (); { - unsigned char *where = fixp->fx_frag->fr_literal + fixp->fx_where; + unsigned char *where = fixP->fx_frag->fr_literal + fixP->fx_where; unsigned long val; if (target_big_endian) @@ -5361,45 +5429,45 @@ md_apply_fix3 (fixp, valuep, seg) /* Because SDA21 modifies the register field, the size is set to 4 bytes, rather than 2, so offset it here appropriately. */ case BFD_RELOC_PPC_EMB_SDA21: - if (fixp->fx_pcrel) + if (fixP->fx_pcrel) abort (); - md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where + md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where + ((target_big_endian) ? 2 : 0), value, 2); break; case BFD_RELOC_8: - if (fixp->fx_pcrel) + if (fixP->fx_pcrel) abort (); - md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where, + md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where, value, 1); break; case BFD_RELOC_24_PLT_PCREL: case BFD_RELOC_PPC_LOCAL24PC: - if (!fixp->fx_pcrel && !fixp->fx_done) + if (!fixP->fx_pcrel && !fixP->fx_done) abort (); - if (fixp->fx_done) + if (fixP->fx_done) { char *where; unsigned long insn; /* Fetch the instruction, insert the fully resolved operand value, and stuff the instruction back again. */ - where = fixp->fx_frag->fr_literal + fixp->fx_where; + where = fixP->fx_frag->fr_literal + fixP->fx_where; if (target_big_endian) insn = bfd_getb32 ((unsigned char *) where); else insn = bfd_getl32 ((unsigned char *) where); if ((value & 3) != 0) - as_bad_where (fixp->fx_file, fixp->fx_line, + as_bad_where (fixP->fx_file, fixP->fx_line, _("must branch to an address a multiple of 4")); if ((offsetT) value < -0x40000000 || (offsetT) value >= 0x40000000) - as_bad_where (fixp->fx_file, fixp->fx_line, + as_bad_where (fixP->fx_file, fixP->fx_line, _("@local or @plt branch destination is too far away, %ld bytes"), (long) value); insn = insn | (value & 0x03fffffc); @@ -5411,15 +5479,15 @@ md_apply_fix3 (fixp, valuep, seg) break; case BFD_RELOC_VTABLE_INHERIT: - fixp->fx_done = 0; - if (fixp->fx_addsy - && !S_IS_DEFINED (fixp->fx_addsy) - && !S_IS_WEAK (fixp->fx_addsy)) - S_SET_WEAK (fixp->fx_addsy); + fixP->fx_done = 0; + if (fixP->fx_addsy + && !S_IS_DEFINED (fixP->fx_addsy) + && !S_IS_WEAK (fixP->fx_addsy)) + S_SET_WEAK (fixP->fx_addsy); break; case BFD_RELOC_VTABLE_ENTRY: - fixp->fx_done = 0; + fixP->fx_done = 0; break; #ifdef OBJ_ELF @@ -5427,37 +5495,35 @@ md_apply_fix3 (fixp, valuep, seg) /* Generated by reference to `sym@tocbase'. The sym is ignored by the linker. */ case BFD_RELOC_PPC64_TOC: - fixp->fx_done = 0; + fixP->fx_done = 0; break; #endif #endif default: fprintf (stderr, - _("Gas failure, reloc value %d\n"), fixp->fx_r_type); + _("Gas failure, reloc value %d\n"), fixP->fx_r_type); fflush (stderr); abort (); } } #ifdef OBJ_ELF - fixp->fx_addnumber = value; + fixP->fx_addnumber = value; #else - if (fixp->fx_r_type != BFD_RELOC_PPC_TOC16) - fixp->fx_addnumber = 0; + if (fixP->fx_r_type != BFD_RELOC_PPC_TOC16) + fixP->fx_addnumber = 0; else { #ifdef TE_PE - fixp->fx_addnumber = 0; + fixP->fx_addnumber = 0; #else /* We want to use the offset within the data segment of the symbol, not the actual VMA of the symbol. */ - fixp->fx_addnumber = - - bfd_get_section_vma (stdoutput, S_GET_SEGMENT (fixp->fx_addsy)); + fixP->fx_addnumber = + - bfd_get_section_vma (stdoutput, S_GET_SEGMENT (fixP->fx_addsy)); #endif } #endif - - return 1; } /* Generate a reloc for a fixup. */