Update year range in copyright notice of binutils files
[deliverable/binutils-gdb.git] / gas / config / tc-ppc.c
index 1d2c57f0293b1debaca194a7cfbe7ec5a6a9c933..35da05c510e5f664368b2f22fa2a0616f86b425c 100644 (file)
@@ -1,5 +1,5 @@
 /* tc-ppc.c -- Assemble for the PowerPC or POWER (RS/6000)
-   Copyright (C) 1994-2016 Free Software Foundation, Inc.
+   Copyright (C) 1994-2018 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Cygnus Support.
 
    This file is part of GAS, the GNU Assembler.
@@ -133,6 +133,7 @@ static void ppc_elf_rdata (int);
 static void ppc_elf_lcomm (int);
 static void ppc_elf_localentry (int);
 static void ppc_elf_abiversion (int);
+static void ppc_elf_gnu_attribute (int);
 #endif
 
 #ifdef TE_PE
@@ -206,15 +207,17 @@ ppc_cpu_t sticky = 0;
 /* Value for ELF e_flags EF_PPC64_ABI.  */
 unsigned int ppc_abiversion = 0;
 
+#ifdef OBJ_ELF
 /* Flags set on encountering toc relocs.  */
-enum {
+static enum {
   has_large_toc_reloc = 1,
   has_small_toc_reloc = 2
 } toc_reloc_types;
+#endif
 
 /* Warn on emitting data to code sections.  */
 int warn_476;
-unsigned long last_insn;
+uint64_t last_insn;
 segT last_seg;
 subsegT last_subseg;
 \f
@@ -268,6 +271,7 @@ const pseudo_typeS md_pseudo_table[] =
   { "lcomm",   ppc_elf_lcomm,  0 },
   { "localentry", ppc_elf_localentry,  0 },
   { "abiversion", ppc_elf_abiversion,  0 },
+  { "gnu_attribute", ppc_elf_gnu_attribute, 0},
 #endif
 
 #ifdef TE_PE
@@ -303,7 +307,8 @@ const pseudo_typeS md_pseudo_table[] =
 struct pd_reg
   {
     const char *name;
-    int value;
+    unsigned short value;
+    unsigned short flags;
   };
 
 /* List of registers that are pre-defined:
@@ -327,11 +332,9 @@ struct pd_reg
    There are individual registers as well:
    sp or r.sp     has the value 1
    rtoc or r.toc  has the value 2
-   fpscr          has the value 0
    xer            has the value 1
    lr             has the value 8
    ctr            has the value 9
-   pmr            has the value 0
    dar            has the value 19
    dsisr          has the value 18
    dec            has the value 22
@@ -343,463 +346,460 @@ struct pd_reg
 
 static const struct pd_reg pre_defined_registers[] =
 {
-  { "cr.0", 0 },    /* Condition Registers */
-  { "cr.1", 1 },
-  { "cr.2", 2 },
-  { "cr.3", 3 },
-  { "cr.4", 4 },
-  { "cr.5", 5 },
-  { "cr.6", 6 },
-  { "cr.7", 7 },
-
-  { "cr0", 0 },
-  { "cr1", 1 },
-  { "cr2", 2 },
-  { "cr3", 3 },
-  { "cr4", 4 },
-  { "cr5", 5 },
-  { "cr6", 6 },
-  { "cr7", 7 },
-
-  { "ctr", 9 },
-
-  { "dar", 19 },    /* Data Access Register */
-  { "dec", 22 },    /* Decrementer */
-  { "dsisr", 18 },  /* Data Storage Interrupt Status Register */
-
-  { "f.0", 0 },     /* Floating point registers */
-  { "f.1", 1 },
-  { "f.10", 10 },
-  { "f.11", 11 },
-  { "f.12", 12 },
-  { "f.13", 13 },
-  { "f.14", 14 },
-  { "f.15", 15 },
-  { "f.16", 16 },
-  { "f.17", 17 },
-  { "f.18", 18 },
-  { "f.19", 19 },
-  { "f.2", 2 },
-  { "f.20", 20 },
-  { "f.21", 21 },
-  { "f.22", 22 },
-  { "f.23", 23 },
-  { "f.24", 24 },
-  { "f.25", 25 },
-  { "f.26", 26 },
-  { "f.27", 27 },
-  { "f.28", 28 },
-  { "f.29", 29 },
-  { "f.3", 3 },
-  { "f.30", 30 },
-  { "f.31", 31 },
-
-  { "f.32", 32 },    /* Extended floating point scalar registers (ISA 2.06).  */
-  { "f.33", 33 },
-  { "f.34", 34 },
-  { "f.35", 35 },
-  { "f.36", 36 },
-  { "f.37", 37 },
-  { "f.38", 38 },
-  { "f.39", 39 },
-  { "f.4", 4 },
-  { "f.40", 40 },
-  { "f.41", 41 },
-  { "f.42", 42 },
-  { "f.43", 43 },
-  { "f.44", 44 },
-  { "f.45", 45 },
-  { "f.46", 46 },
-  { "f.47", 47 },
-  { "f.48", 48 },
-  { "f.49", 49 },
-  { "f.5", 5 },
-  { "f.50", 50 },
-  { "f.51", 51 },
-  { "f.52", 52 },
-  { "f.53", 53 },
-  { "f.54", 54 },
-  { "f.55", 55 },
-  { "f.56", 56 },
-  { "f.57", 57 },
-  { "f.58", 58 },
-  { "f.59", 59 },
-  { "f.6", 6 },
-  { "f.60", 60 },
-  { "f.61", 61 },
-  { "f.62", 62 },
-  { "f.63", 63 },
-  { "f.7", 7 },
-  { "f.8", 8 },
-  { "f.9", 9 },
-
-  { "f0", 0 },
-  { "f1", 1 },
-  { "f10", 10 },
-  { "f11", 11 },
-  { "f12", 12 },
-  { "f13", 13 },
-  { "f14", 14 },
-  { "f15", 15 },
-  { "f16", 16 },
-  { "f17", 17 },
-  { "f18", 18 },
-  { "f19", 19 },
-  { "f2", 2 },
-  { "f20", 20 },
-  { "f21", 21 },
-  { "f22", 22 },
-  { "f23", 23 },
-  { "f24", 24 },
-  { "f25", 25 },
-  { "f26", 26 },
-  { "f27", 27 },
-  { "f28", 28 },
-  { "f29", 29 },
-  { "f3", 3 },
-  { "f30", 30 },
-  { "f31", 31 },
-
-  { "f32", 32 },    /* Extended floating point scalar registers (ISA 2.06).  */
-  { "f33", 33 },
-  { "f34", 34 },
-  { "f35", 35 },
-  { "f36", 36 },
-  { "f37", 37 },
-  { "f38", 38 },
-  { "f39", 39 },
-  { "f4", 4 },
-  { "f40", 40 },
-  { "f41", 41 },
-  { "f42", 42 },
-  { "f43", 43 },
-  { "f44", 44 },
-  { "f45", 45 },
-  { "f46", 46 },
-  { "f47", 47 },
-  { "f48", 48 },
-  { "f49", 49 },
-  { "f5", 5 },
-  { "f50", 50 },
-  { "f51", 51 },
-  { "f52", 52 },
-  { "f53", 53 },
-  { "f54", 54 },
-  { "f55", 55 },
-  { "f56", 56 },
-  { "f57", 57 },
-  { "f58", 58 },
-  { "f59", 59 },
-  { "f6", 6 },
-  { "f60", 60 },
-  { "f61", 61 },
-  { "f62", 62 },
-  { "f63", 63 },
-  { "f7", 7 },
-  { "f8", 8 },
-  { "f9", 9 },
-
-  { "fpscr", 0 },
+  /* Condition Registers */
+  { "cr.0", 0, PPC_OPERAND_CR_REG },
+  { "cr.1", 1, PPC_OPERAND_CR_REG },
+  { "cr.2", 2, PPC_OPERAND_CR_REG },
+  { "cr.3", 3, PPC_OPERAND_CR_REG },
+  { "cr.4", 4, PPC_OPERAND_CR_REG },
+  { "cr.5", 5, PPC_OPERAND_CR_REG },
+  { "cr.6", 6, PPC_OPERAND_CR_REG },
+  { "cr.7", 7, PPC_OPERAND_CR_REG },
+
+  { "cr0", 0, PPC_OPERAND_CR_REG },
+  { "cr1", 1, PPC_OPERAND_CR_REG },
+  { "cr2", 2, PPC_OPERAND_CR_REG },
+  { "cr3", 3, PPC_OPERAND_CR_REG },
+  { "cr4", 4, PPC_OPERAND_CR_REG },
+  { "cr5", 5, PPC_OPERAND_CR_REG },
+  { "cr6", 6, PPC_OPERAND_CR_REG },
+  { "cr7", 7, PPC_OPERAND_CR_REG },
+
+  { "ctr", 9, PPC_OPERAND_SPR },
+  { "dar", 19, PPC_OPERAND_SPR },
+  { "dec", 22, PPC_OPERAND_SPR },
+  { "dsisr", 18, PPC_OPERAND_SPR },
+
+  /* Floating point registers */
+  { "f.0", 0, PPC_OPERAND_FPR },
+  { "f.1", 1, PPC_OPERAND_FPR },
+  { "f.10", 10, PPC_OPERAND_FPR },
+  { "f.11", 11, PPC_OPERAND_FPR },
+  { "f.12", 12, PPC_OPERAND_FPR },
+  { "f.13", 13, PPC_OPERAND_FPR },
+  { "f.14", 14, PPC_OPERAND_FPR },
+  { "f.15", 15, PPC_OPERAND_FPR },
+  { "f.16", 16, PPC_OPERAND_FPR },
+  { "f.17", 17, PPC_OPERAND_FPR },
+  { "f.18", 18, PPC_OPERAND_FPR },
+  { "f.19", 19, PPC_OPERAND_FPR },
+  { "f.2", 2, PPC_OPERAND_FPR },
+  { "f.20", 20, PPC_OPERAND_FPR },
+  { "f.21", 21, PPC_OPERAND_FPR },
+  { "f.22", 22, PPC_OPERAND_FPR },
+  { "f.23", 23, PPC_OPERAND_FPR },
+  { "f.24", 24, PPC_OPERAND_FPR },
+  { "f.25", 25, PPC_OPERAND_FPR },
+  { "f.26", 26, PPC_OPERAND_FPR },
+  { "f.27", 27, PPC_OPERAND_FPR },
+  { "f.28", 28, PPC_OPERAND_FPR },
+  { "f.29", 29, PPC_OPERAND_FPR },
+  { "f.3", 3, PPC_OPERAND_FPR },
+  { "f.30", 30, PPC_OPERAND_FPR },
+  { "f.31", 31, PPC_OPERAND_FPR },
+  { "f.32", 32, PPC_OPERAND_VSR },
+  { "f.33", 33, PPC_OPERAND_VSR },
+  { "f.34", 34, PPC_OPERAND_VSR },
+  { "f.35", 35, PPC_OPERAND_VSR },
+  { "f.36", 36, PPC_OPERAND_VSR },
+  { "f.37", 37, PPC_OPERAND_VSR },
+  { "f.38", 38, PPC_OPERAND_VSR },
+  { "f.39", 39, PPC_OPERAND_VSR },
+  { "f.4", 4, PPC_OPERAND_FPR },
+  { "f.40", 40, PPC_OPERAND_VSR },
+  { "f.41", 41, PPC_OPERAND_VSR },
+  { "f.42", 42, PPC_OPERAND_VSR },
+  { "f.43", 43, PPC_OPERAND_VSR },
+  { "f.44", 44, PPC_OPERAND_VSR },
+  { "f.45", 45, PPC_OPERAND_VSR },
+  { "f.46", 46, PPC_OPERAND_VSR },
+  { "f.47", 47, PPC_OPERAND_VSR },
+  { "f.48", 48, PPC_OPERAND_VSR },
+  { "f.49", 49, PPC_OPERAND_VSR },
+  { "f.5", 5, PPC_OPERAND_FPR },
+  { "f.50", 50, PPC_OPERAND_VSR },
+  { "f.51", 51, PPC_OPERAND_VSR },
+  { "f.52", 52, PPC_OPERAND_VSR },
+  { "f.53", 53, PPC_OPERAND_VSR },
+  { "f.54", 54, PPC_OPERAND_VSR },
+  { "f.55", 55, PPC_OPERAND_VSR },
+  { "f.56", 56, PPC_OPERAND_VSR },
+  { "f.57", 57, PPC_OPERAND_VSR },
+  { "f.58", 58, PPC_OPERAND_VSR },
+  { "f.59", 59, PPC_OPERAND_VSR },
+  { "f.6", 6, PPC_OPERAND_FPR },
+  { "f.60", 60, PPC_OPERAND_VSR },
+  { "f.61", 61, PPC_OPERAND_VSR },
+  { "f.62", 62, PPC_OPERAND_VSR },
+  { "f.63", 63, PPC_OPERAND_VSR },
+  { "f.7", 7, PPC_OPERAND_FPR },
+  { "f.8", 8, PPC_OPERAND_FPR },
+  { "f.9", 9, PPC_OPERAND_FPR },
+
+  { "f0", 0, PPC_OPERAND_FPR },
+  { "f1", 1, PPC_OPERAND_FPR },
+  { "f10", 10, PPC_OPERAND_FPR },
+  { "f11", 11, PPC_OPERAND_FPR },
+  { "f12", 12, PPC_OPERAND_FPR },
+  { "f13", 13, PPC_OPERAND_FPR },
+  { "f14", 14, PPC_OPERAND_FPR },
+  { "f15", 15, PPC_OPERAND_FPR },
+  { "f16", 16, PPC_OPERAND_FPR },
+  { "f17", 17, PPC_OPERAND_FPR },
+  { "f18", 18, PPC_OPERAND_FPR },
+  { "f19", 19, PPC_OPERAND_FPR },
+  { "f2", 2, PPC_OPERAND_FPR },
+  { "f20", 20, PPC_OPERAND_FPR },
+  { "f21", 21, PPC_OPERAND_FPR },
+  { "f22", 22, PPC_OPERAND_FPR },
+  { "f23", 23, PPC_OPERAND_FPR },
+  { "f24", 24, PPC_OPERAND_FPR },
+  { "f25", 25, PPC_OPERAND_FPR },
+  { "f26", 26, PPC_OPERAND_FPR },
+  { "f27", 27, PPC_OPERAND_FPR },
+  { "f28", 28, PPC_OPERAND_FPR },
+  { "f29", 29, PPC_OPERAND_FPR },
+  { "f3", 3, PPC_OPERAND_FPR },
+  { "f30", 30, PPC_OPERAND_FPR },
+  { "f31", 31, PPC_OPERAND_FPR },
+  { "f32", 32, PPC_OPERAND_VSR },
+  { "f33", 33, PPC_OPERAND_VSR },
+  { "f34", 34, PPC_OPERAND_VSR },
+  { "f35", 35, PPC_OPERAND_VSR },
+  { "f36", 36, PPC_OPERAND_VSR },
+  { "f37", 37, PPC_OPERAND_VSR },
+  { "f38", 38, PPC_OPERAND_VSR },
+  { "f39", 39, PPC_OPERAND_VSR },
+  { "f4", 4, PPC_OPERAND_FPR },
+  { "f40", 40, PPC_OPERAND_VSR },
+  { "f41", 41, PPC_OPERAND_VSR },
+  { "f42", 42, PPC_OPERAND_VSR },
+  { "f43", 43, PPC_OPERAND_VSR },
+  { "f44", 44, PPC_OPERAND_VSR },
+  { "f45", 45, PPC_OPERAND_VSR },
+  { "f46", 46, PPC_OPERAND_VSR },
+  { "f47", 47, PPC_OPERAND_VSR },
+  { "f48", 48, PPC_OPERAND_VSR },
+  { "f49", 49, PPC_OPERAND_VSR },
+  { "f5", 5, PPC_OPERAND_FPR },
+  { "f50", 50, PPC_OPERAND_VSR },
+  { "f51", 51, PPC_OPERAND_VSR },
+  { "f52", 52, PPC_OPERAND_VSR },
+  { "f53", 53, PPC_OPERAND_VSR },
+  { "f54", 54, PPC_OPERAND_VSR },
+  { "f55", 55, PPC_OPERAND_VSR },
+  { "f56", 56, PPC_OPERAND_VSR },
+  { "f57", 57, PPC_OPERAND_VSR },
+  { "f58", 58, PPC_OPERAND_VSR },
+  { "f59", 59, PPC_OPERAND_VSR },
+  { "f6", 6, PPC_OPERAND_FPR },
+  { "f60", 60, PPC_OPERAND_VSR },
+  { "f61", 61, PPC_OPERAND_VSR },
+  { "f62", 62, PPC_OPERAND_VSR },
+  { "f63", 63, PPC_OPERAND_VSR },
+  { "f7", 7, PPC_OPERAND_FPR },
+  { "f8", 8, PPC_OPERAND_FPR },
+  { "f9", 9, PPC_OPERAND_FPR },
 
   /* Quantization registers used with pair single instructions.  */
-  { "gqr.0", 0 },
-  { "gqr.1", 1 },
-  { "gqr.2", 2 },
-  { "gqr.3", 3 },
-  { "gqr.4", 4 },
-  { "gqr.5", 5 },
-  { "gqr.6", 6 },
-  { "gqr.7", 7 },
-  { "gqr0", 0 },
-  { "gqr1", 1 },
-  { "gqr2", 2 },
-  { "gqr3", 3 },
-  { "gqr4", 4 },
-  { "gqr5", 5 },
-  { "gqr6", 6 },
-  { "gqr7", 7 },
-
-  { "lr", 8 },     /* Link Register */
-
-  { "pmr", 0 },
-
-  { "r.0", 0 },    /* General Purpose Registers */
-  { "r.1", 1 },
-  { "r.10", 10 },
-  { "r.11", 11 },
-  { "r.12", 12 },
-  { "r.13", 13 },
-  { "r.14", 14 },
-  { "r.15", 15 },
-  { "r.16", 16 },
-  { "r.17", 17 },
-  { "r.18", 18 },
-  { "r.19", 19 },
-  { "r.2", 2 },
-  { "r.20", 20 },
-  { "r.21", 21 },
-  { "r.22", 22 },
-  { "r.23", 23 },
-  { "r.24", 24 },
-  { "r.25", 25 },
-  { "r.26", 26 },
-  { "r.27", 27 },
-  { "r.28", 28 },
-  { "r.29", 29 },
-  { "r.3", 3 },
-  { "r.30", 30 },
-  { "r.31", 31 },
-  { "r.4", 4 },
-  { "r.5", 5 },
-  { "r.6", 6 },
-  { "r.7", 7 },
-  { "r.8", 8 },
-  { "r.9", 9 },
-
-  { "r.sp", 1 },   /* Stack Pointer */
-
-  { "r.toc", 2 },  /* Pointer to the table of contents */
-
-  { "r0", 0 },     /* More general purpose registers */
-  { "r1", 1 },
-  { "r10", 10 },
-  { "r11", 11 },
-  { "r12", 12 },
-  { "r13", 13 },
-  { "r14", 14 },
-  { "r15", 15 },
-  { "r16", 16 },
-  { "r17", 17 },
-  { "r18", 18 },
-  { "r19", 19 },
-  { "r2", 2 },
-  { "r20", 20 },
-  { "r21", 21 },
-  { "r22", 22 },
-  { "r23", 23 },
-  { "r24", 24 },
-  { "r25", 25 },
-  { "r26", 26 },
-  { "r27", 27 },
-  { "r28", 28 },
-  { "r29", 29 },
-  { "r3", 3 },
-  { "r30", 30 },
-  { "r31", 31 },
-  { "r4", 4 },
-  { "r5", 5 },
-  { "r6", 6 },
-  { "r7", 7 },
-  { "r8", 8 },
-  { "r9", 9 },
-
-  { "rtoc", 2 },  /* Table of contents */
-
-  { "sdr1", 25 }, /* Storage Description Register 1 */
-
-  { "sp", 1 },
-
-  { "srr0", 26 }, /* Machine Status Save/Restore Register 0 */
-  { "srr1", 27 }, /* Machine Status Save/Restore Register 1 */
-
-  { "v.0", 0 },     /* Vector (Altivec/VMX) registers */
-  { "v.1", 1 },
-  { "v.10", 10 },
-  { "v.11", 11 },
-  { "v.12", 12 },
-  { "v.13", 13 },
-  { "v.14", 14 },
-  { "v.15", 15 },
-  { "v.16", 16 },
-  { "v.17", 17 },
-  { "v.18", 18 },
-  { "v.19", 19 },
-  { "v.2", 2 },
-  { "v.20", 20 },
-  { "v.21", 21 },
-  { "v.22", 22 },
-  { "v.23", 23 },
-  { "v.24", 24 },
-  { "v.25", 25 },
-  { "v.26", 26 },
-  { "v.27", 27 },
-  { "v.28", 28 },
-  { "v.29", 29 },
-  { "v.3", 3 },
-  { "v.30", 30 },
-  { "v.31", 31 },
-  { "v.4", 4 },
-  { "v.5", 5 },
-  { "v.6", 6 },
-  { "v.7", 7 },
-  { "v.8", 8 },
-  { "v.9", 9 },
-
-  { "v0", 0 },
-  { "v1", 1 },
-  { "v10", 10 },
-  { "v11", 11 },
-  { "v12", 12 },
-  { "v13", 13 },
-  { "v14", 14 },
-  { "v15", 15 },
-  { "v16", 16 },
-  { "v17", 17 },
-  { "v18", 18 },
-  { "v19", 19 },
-  { "v2", 2 },
-  { "v20", 20 },
-  { "v21", 21 },
-  { "v22", 22 },
-  { "v23", 23 },
-  { "v24", 24 },
-  { "v25", 25 },
-  { "v26", 26 },
-  { "v27", 27 },
-  { "v28", 28 },
-  { "v29", 29 },
-  { "v3", 3 },
-  { "v30", 30 },
-  { "v31", 31 },
-  { "v4", 4 },
-  { "v5", 5 },
-  { "v6", 6 },
-  { "v7", 7 },
-  { "v8", 8 },
-  { "v9", 9 },
-
-  { "vs.0", 0 },     /* Vector Scalar (VSX) registers (ISA 2.06).  */
-  { "vs.1", 1 },
-  { "vs.10", 10 },
-  { "vs.11", 11 },
-  { "vs.12", 12 },
-  { "vs.13", 13 },
-  { "vs.14", 14 },
-  { "vs.15", 15 },
-  { "vs.16", 16 },
-  { "vs.17", 17 },
-  { "vs.18", 18 },
-  { "vs.19", 19 },
-  { "vs.2", 2 },
-  { "vs.20", 20 },
-  { "vs.21", 21 },
-  { "vs.22", 22 },
-  { "vs.23", 23 },
-  { "vs.24", 24 },
-  { "vs.25", 25 },
-  { "vs.26", 26 },
-  { "vs.27", 27 },
-  { "vs.28", 28 },
-  { "vs.29", 29 },
-  { "vs.3", 3 },
-  { "vs.30", 30 },
-  { "vs.31", 31 },
-  { "vs.32", 32 },
-  { "vs.33", 33 },
-  { "vs.34", 34 },
-  { "vs.35", 35 },
-  { "vs.36", 36 },
-  { "vs.37", 37 },
-  { "vs.38", 38 },
-  { "vs.39", 39 },
-  { "vs.4", 4 },
-  { "vs.40", 40 },
-  { "vs.41", 41 },
-  { "vs.42", 42 },
-  { "vs.43", 43 },
-  { "vs.44", 44 },
-  { "vs.45", 45 },
-  { "vs.46", 46 },
-  { "vs.47", 47 },
-  { "vs.48", 48 },
-  { "vs.49", 49 },
-  { "vs.5", 5 },
-  { "vs.50", 50 },
-  { "vs.51", 51 },
-  { "vs.52", 52 },
-  { "vs.53", 53 },
-  { "vs.54", 54 },
-  { "vs.55", 55 },
-  { "vs.56", 56 },
-  { "vs.57", 57 },
-  { "vs.58", 58 },
-  { "vs.59", 59 },
-  { "vs.6", 6 },
-  { "vs.60", 60 },
-  { "vs.61", 61 },
-  { "vs.62", 62 },
-  { "vs.63", 63 },
-  { "vs.7", 7 },
-  { "vs.8", 8 },
-  { "vs.9", 9 },
-
-  { "vs0", 0 },
-  { "vs1", 1 },
-  { "vs10", 10 },
-  { "vs11", 11 },
-  { "vs12", 12 },
-  { "vs13", 13 },
-  { "vs14", 14 },
-  { "vs15", 15 },
-  { "vs16", 16 },
-  { "vs17", 17 },
-  { "vs18", 18 },
-  { "vs19", 19 },
-  { "vs2", 2 },
-  { "vs20", 20 },
-  { "vs21", 21 },
-  { "vs22", 22 },
-  { "vs23", 23 },
-  { "vs24", 24 },
-  { "vs25", 25 },
-  { "vs26", 26 },
-  { "vs27", 27 },
-  { "vs28", 28 },
-  { "vs29", 29 },
-  { "vs3", 3 },
-  { "vs30", 30 },
-  { "vs31", 31 },
-  { "vs32", 32 },
-  { "vs33", 33 },
-  { "vs34", 34 },
-  { "vs35", 35 },
-  { "vs36", 36 },
-  { "vs37", 37 },
-  { "vs38", 38 },
-  { "vs39", 39 },
-  { "vs4", 4 },
-  { "vs40", 40 },
-  { "vs41", 41 },
-  { "vs42", 42 },
-  { "vs43", 43 },
-  { "vs44", 44 },
-  { "vs45", 45 },
-  { "vs46", 46 },
-  { "vs47", 47 },
-  { "vs48", 48 },
-  { "vs49", 49 },
-  { "vs5", 5 },
-  { "vs50", 50 },
-  { "vs51", 51 },
-  { "vs52", 52 },
-  { "vs53", 53 },
-  { "vs54", 54 },
-  { "vs55", 55 },
-  { "vs56", 56 },
-  { "vs57", 57 },
-  { "vs58", 58 },
-  { "vs59", 59 },
-  { "vs6", 6 },
-  { "vs60", 60 },
-  { "vs61", 61 },
-  { "vs62", 62 },
-  { "vs63", 63 },
-  { "vs7", 7 },
-  { "vs8", 8 },
-  { "vs9", 9 },
-
-  { "xer", 1 },
-
+  { "gqr.0", 0, PPC_OPERAND_GQR },
+  { "gqr.1", 1, PPC_OPERAND_GQR },
+  { "gqr.2", 2, PPC_OPERAND_GQR },
+  { "gqr.3", 3, PPC_OPERAND_GQR },
+  { "gqr.4", 4, PPC_OPERAND_GQR },
+  { "gqr.5", 5, PPC_OPERAND_GQR },
+  { "gqr.6", 6, PPC_OPERAND_GQR },
+  { "gqr.7", 7, PPC_OPERAND_GQR },
+  { "gqr0", 0, PPC_OPERAND_GQR },
+  { "gqr1", 1, PPC_OPERAND_GQR },
+  { "gqr2", 2, PPC_OPERAND_GQR },
+  { "gqr3", 3, PPC_OPERAND_GQR },
+  { "gqr4", 4, PPC_OPERAND_GQR },
+  { "gqr5", 5, PPC_OPERAND_GQR },
+  { "gqr6", 6, PPC_OPERAND_GQR },
+  { "gqr7", 7, PPC_OPERAND_GQR },
+
+  { "lr", 8, PPC_OPERAND_SPR },
+
+  /* General Purpose Registers */
+  { "r.0", 0, PPC_OPERAND_GPR },
+  { "r.1", 1, PPC_OPERAND_GPR },
+  { "r.10", 10, PPC_OPERAND_GPR },
+  { "r.11", 11, PPC_OPERAND_GPR },
+  { "r.12", 12, PPC_OPERAND_GPR },
+  { "r.13", 13, PPC_OPERAND_GPR },
+  { "r.14", 14, PPC_OPERAND_GPR },
+  { "r.15", 15, PPC_OPERAND_GPR },
+  { "r.16", 16, PPC_OPERAND_GPR },
+  { "r.17", 17, PPC_OPERAND_GPR },
+  { "r.18", 18, PPC_OPERAND_GPR },
+  { "r.19", 19, PPC_OPERAND_GPR },
+  { "r.2", 2, PPC_OPERAND_GPR },
+  { "r.20", 20, PPC_OPERAND_GPR },
+  { "r.21", 21, PPC_OPERAND_GPR },
+  { "r.22", 22, PPC_OPERAND_GPR },
+  { "r.23", 23, PPC_OPERAND_GPR },
+  { "r.24", 24, PPC_OPERAND_GPR },
+  { "r.25", 25, PPC_OPERAND_GPR },
+  { "r.26", 26, PPC_OPERAND_GPR },
+  { "r.27", 27, PPC_OPERAND_GPR },
+  { "r.28", 28, PPC_OPERAND_GPR },
+  { "r.29", 29, PPC_OPERAND_GPR },
+  { "r.3", 3, PPC_OPERAND_GPR },
+  { "r.30", 30, PPC_OPERAND_GPR },
+  { "r.31", 31, PPC_OPERAND_GPR },
+  { "r.4", 4, PPC_OPERAND_GPR },
+  { "r.5", 5, PPC_OPERAND_GPR },
+  { "r.6", 6, PPC_OPERAND_GPR },
+  { "r.7", 7, PPC_OPERAND_GPR },
+  { "r.8", 8, PPC_OPERAND_GPR },
+  { "r.9", 9, PPC_OPERAND_GPR },
+
+  { "r.sp", 1, PPC_OPERAND_GPR },
+
+  { "r.toc", 2, PPC_OPERAND_GPR },
+
+  { "r0", 0, PPC_OPERAND_GPR },
+  { "r1", 1, PPC_OPERAND_GPR },
+  { "r10", 10, PPC_OPERAND_GPR },
+  { "r11", 11, PPC_OPERAND_GPR },
+  { "r12", 12, PPC_OPERAND_GPR },
+  { "r13", 13, PPC_OPERAND_GPR },
+  { "r14", 14, PPC_OPERAND_GPR },
+  { "r15", 15, PPC_OPERAND_GPR },
+  { "r16", 16, PPC_OPERAND_GPR },
+  { "r17", 17, PPC_OPERAND_GPR },
+  { "r18", 18, PPC_OPERAND_GPR },
+  { "r19", 19, PPC_OPERAND_GPR },
+  { "r2", 2, PPC_OPERAND_GPR },
+  { "r20", 20, PPC_OPERAND_GPR },
+  { "r21", 21, PPC_OPERAND_GPR },
+  { "r22", 22, PPC_OPERAND_GPR },
+  { "r23", 23, PPC_OPERAND_GPR },
+  { "r24", 24, PPC_OPERAND_GPR },
+  { "r25", 25, PPC_OPERAND_GPR },
+  { "r26", 26, PPC_OPERAND_GPR },
+  { "r27", 27, PPC_OPERAND_GPR },
+  { "r28", 28, PPC_OPERAND_GPR },
+  { "r29", 29, PPC_OPERAND_GPR },
+  { "r3", 3, PPC_OPERAND_GPR },
+  { "r30", 30, PPC_OPERAND_GPR },
+  { "r31", 31, PPC_OPERAND_GPR },
+  { "r4", 4, PPC_OPERAND_GPR },
+  { "r5", 5, PPC_OPERAND_GPR },
+  { "r6", 6, PPC_OPERAND_GPR },
+  { "r7", 7, PPC_OPERAND_GPR },
+  { "r8", 8, PPC_OPERAND_GPR },
+  { "r9", 9, PPC_OPERAND_GPR },
+
+  { "rtoc", 2, PPC_OPERAND_GPR },
+
+  { "sdr1", 25, PPC_OPERAND_SPR },
+
+  { "sp", 1, PPC_OPERAND_GPR },
+
+  { "srr0", 26, PPC_OPERAND_SPR },
+  { "srr1", 27, PPC_OPERAND_SPR },
+
+  /* Vector (Altivec/VMX) registers */
+  { "v.0", 0, PPC_OPERAND_VR },
+  { "v.1", 1, PPC_OPERAND_VR },
+  { "v.10", 10, PPC_OPERAND_VR },
+  { "v.11", 11, PPC_OPERAND_VR },
+  { "v.12", 12, PPC_OPERAND_VR },
+  { "v.13", 13, PPC_OPERAND_VR },
+  { "v.14", 14, PPC_OPERAND_VR },
+  { "v.15", 15, PPC_OPERAND_VR },
+  { "v.16", 16, PPC_OPERAND_VR },
+  { "v.17", 17, PPC_OPERAND_VR },
+  { "v.18", 18, PPC_OPERAND_VR },
+  { "v.19", 19, PPC_OPERAND_VR },
+  { "v.2", 2, PPC_OPERAND_VR },
+  { "v.20", 20, PPC_OPERAND_VR },
+  { "v.21", 21, PPC_OPERAND_VR },
+  { "v.22", 22, PPC_OPERAND_VR },
+  { "v.23", 23, PPC_OPERAND_VR },
+  { "v.24", 24, PPC_OPERAND_VR },
+  { "v.25", 25, PPC_OPERAND_VR },
+  { "v.26", 26, PPC_OPERAND_VR },
+  { "v.27", 27, PPC_OPERAND_VR },
+  { "v.28", 28, PPC_OPERAND_VR },
+  { "v.29", 29, PPC_OPERAND_VR },
+  { "v.3", 3, PPC_OPERAND_VR },
+  { "v.30", 30, PPC_OPERAND_VR },
+  { "v.31", 31, PPC_OPERAND_VR },
+  { "v.4", 4, PPC_OPERAND_VR },
+  { "v.5", 5, PPC_OPERAND_VR },
+  { "v.6", 6, PPC_OPERAND_VR },
+  { "v.7", 7, PPC_OPERAND_VR },
+  { "v.8", 8, PPC_OPERAND_VR },
+  { "v.9", 9, PPC_OPERAND_VR },
+
+  { "v0", 0, PPC_OPERAND_VR },
+  { "v1", 1, PPC_OPERAND_VR },
+  { "v10", 10, PPC_OPERAND_VR },
+  { "v11", 11, PPC_OPERAND_VR },
+  { "v12", 12, PPC_OPERAND_VR },
+  { "v13", 13, PPC_OPERAND_VR },
+  { "v14", 14, PPC_OPERAND_VR },
+  { "v15", 15, PPC_OPERAND_VR },
+  { "v16", 16, PPC_OPERAND_VR },
+  { "v17", 17, PPC_OPERAND_VR },
+  { "v18", 18, PPC_OPERAND_VR },
+  { "v19", 19, PPC_OPERAND_VR },
+  { "v2", 2, PPC_OPERAND_VR },
+  { "v20", 20, PPC_OPERAND_VR },
+  { "v21", 21, PPC_OPERAND_VR },
+  { "v22", 22, PPC_OPERAND_VR },
+  { "v23", 23, PPC_OPERAND_VR },
+  { "v24", 24, PPC_OPERAND_VR },
+  { "v25", 25, PPC_OPERAND_VR },
+  { "v26", 26, PPC_OPERAND_VR },
+  { "v27", 27, PPC_OPERAND_VR },
+  { "v28", 28, PPC_OPERAND_VR },
+  { "v29", 29, PPC_OPERAND_VR },
+  { "v3", 3, PPC_OPERAND_VR },
+  { "v30", 30, PPC_OPERAND_VR },
+  { "v31", 31, PPC_OPERAND_VR },
+  { "v4", 4, PPC_OPERAND_VR },
+  { "v5", 5, PPC_OPERAND_VR },
+  { "v6", 6, PPC_OPERAND_VR },
+  { "v7", 7, PPC_OPERAND_VR },
+  { "v8", 8, PPC_OPERAND_VR },
+  { "v9", 9, PPC_OPERAND_VR },
+
+  /* Vector Scalar (VSX) registers (ISA 2.06).  */
+  { "vs.0", 0, PPC_OPERAND_VSR },
+  { "vs.1", 1, PPC_OPERAND_VSR },
+  { "vs.10", 10, PPC_OPERAND_VSR },
+  { "vs.11", 11, PPC_OPERAND_VSR },
+  { "vs.12", 12, PPC_OPERAND_VSR },
+  { "vs.13", 13, PPC_OPERAND_VSR },
+  { "vs.14", 14, PPC_OPERAND_VSR },
+  { "vs.15", 15, PPC_OPERAND_VSR },
+  { "vs.16", 16, PPC_OPERAND_VSR },
+  { "vs.17", 17, PPC_OPERAND_VSR },
+  { "vs.18", 18, PPC_OPERAND_VSR },
+  { "vs.19", 19, PPC_OPERAND_VSR },
+  { "vs.2", 2, PPC_OPERAND_VSR },
+  { "vs.20", 20, PPC_OPERAND_VSR },
+  { "vs.21", 21, PPC_OPERAND_VSR },
+  { "vs.22", 22, PPC_OPERAND_VSR },
+  { "vs.23", 23, PPC_OPERAND_VSR },
+  { "vs.24", 24, PPC_OPERAND_VSR },
+  { "vs.25", 25, PPC_OPERAND_VSR },
+  { "vs.26", 26, PPC_OPERAND_VSR },
+  { "vs.27", 27, PPC_OPERAND_VSR },
+  { "vs.28", 28, PPC_OPERAND_VSR },
+  { "vs.29", 29, PPC_OPERAND_VSR },
+  { "vs.3", 3, PPC_OPERAND_VSR },
+  { "vs.30", 30, PPC_OPERAND_VSR },
+  { "vs.31", 31, PPC_OPERAND_VSR },
+  { "vs.32", 32, PPC_OPERAND_VSR },
+  { "vs.33", 33, PPC_OPERAND_VSR },
+  { "vs.34", 34, PPC_OPERAND_VSR },
+  { "vs.35", 35, PPC_OPERAND_VSR },
+  { "vs.36", 36, PPC_OPERAND_VSR },
+  { "vs.37", 37, PPC_OPERAND_VSR },
+  { "vs.38", 38, PPC_OPERAND_VSR },
+  { "vs.39", 39, PPC_OPERAND_VSR },
+  { "vs.4", 4, PPC_OPERAND_VSR },
+  { "vs.40", 40, PPC_OPERAND_VSR },
+  { "vs.41", 41, PPC_OPERAND_VSR },
+  { "vs.42", 42, PPC_OPERAND_VSR },
+  { "vs.43", 43, PPC_OPERAND_VSR },
+  { "vs.44", 44, PPC_OPERAND_VSR },
+  { "vs.45", 45, PPC_OPERAND_VSR },
+  { "vs.46", 46, PPC_OPERAND_VSR },
+  { "vs.47", 47, PPC_OPERAND_VSR },
+  { "vs.48", 48, PPC_OPERAND_VSR },
+  { "vs.49", 49, PPC_OPERAND_VSR },
+  { "vs.5", 5, PPC_OPERAND_VSR },
+  { "vs.50", 50, PPC_OPERAND_VSR },
+  { "vs.51", 51, PPC_OPERAND_VSR },
+  { "vs.52", 52, PPC_OPERAND_VSR },
+  { "vs.53", 53, PPC_OPERAND_VSR },
+  { "vs.54", 54, PPC_OPERAND_VSR },
+  { "vs.55", 55, PPC_OPERAND_VSR },
+  { "vs.56", 56, PPC_OPERAND_VSR },
+  { "vs.57", 57, PPC_OPERAND_VSR },
+  { "vs.58", 58, PPC_OPERAND_VSR },
+  { "vs.59", 59, PPC_OPERAND_VSR },
+  { "vs.6", 6, PPC_OPERAND_VSR },
+  { "vs.60", 60, PPC_OPERAND_VSR },
+  { "vs.61", 61, PPC_OPERAND_VSR },
+  { "vs.62", 62, PPC_OPERAND_VSR },
+  { "vs.63", 63, PPC_OPERAND_VSR },
+  { "vs.7", 7, PPC_OPERAND_VSR },
+  { "vs.8", 8, PPC_OPERAND_VSR },
+  { "vs.9", 9, PPC_OPERAND_VSR },
+
+  { "vs0", 0, PPC_OPERAND_VSR },
+  { "vs1", 1, PPC_OPERAND_VSR },
+  { "vs10", 10, PPC_OPERAND_VSR },
+  { "vs11", 11, PPC_OPERAND_VSR },
+  { "vs12", 12, PPC_OPERAND_VSR },
+  { "vs13", 13, PPC_OPERAND_VSR },
+  { "vs14", 14, PPC_OPERAND_VSR },
+  { "vs15", 15, PPC_OPERAND_VSR },
+  { "vs16", 16, PPC_OPERAND_VSR },
+  { "vs17", 17, PPC_OPERAND_VSR },
+  { "vs18", 18, PPC_OPERAND_VSR },
+  { "vs19", 19, PPC_OPERAND_VSR },
+  { "vs2", 2, PPC_OPERAND_VSR },
+  { "vs20", 20, PPC_OPERAND_VSR },
+  { "vs21", 21, PPC_OPERAND_VSR },
+  { "vs22", 22, PPC_OPERAND_VSR },
+  { "vs23", 23, PPC_OPERAND_VSR },
+  { "vs24", 24, PPC_OPERAND_VSR },
+  { "vs25", 25, PPC_OPERAND_VSR },
+  { "vs26", 26, PPC_OPERAND_VSR },
+  { "vs27", 27, PPC_OPERAND_VSR },
+  { "vs28", 28, PPC_OPERAND_VSR },
+  { "vs29", 29, PPC_OPERAND_VSR },
+  { "vs3", 3, PPC_OPERAND_VSR },
+  { "vs30", 30, PPC_OPERAND_VSR },
+  { "vs31", 31, PPC_OPERAND_VSR },
+  { "vs32", 32, PPC_OPERAND_VSR },
+  { "vs33", 33, PPC_OPERAND_VSR },
+  { "vs34", 34, PPC_OPERAND_VSR },
+  { "vs35", 35, PPC_OPERAND_VSR },
+  { "vs36", 36, PPC_OPERAND_VSR },
+  { "vs37", 37, PPC_OPERAND_VSR },
+  { "vs38", 38, PPC_OPERAND_VSR },
+  { "vs39", 39, PPC_OPERAND_VSR },
+  { "vs4", 4, PPC_OPERAND_VSR },
+  { "vs40", 40, PPC_OPERAND_VSR },
+  { "vs41", 41, PPC_OPERAND_VSR },
+  { "vs42", 42, PPC_OPERAND_VSR },
+  { "vs43", 43, PPC_OPERAND_VSR },
+  { "vs44", 44, PPC_OPERAND_VSR },
+  { "vs45", 45, PPC_OPERAND_VSR },
+  { "vs46", 46, PPC_OPERAND_VSR },
+  { "vs47", 47, PPC_OPERAND_VSR },
+  { "vs48", 48, PPC_OPERAND_VSR },
+  { "vs49", 49, PPC_OPERAND_VSR },
+  { "vs5", 5, PPC_OPERAND_VSR },
+  { "vs50", 50, PPC_OPERAND_VSR },
+  { "vs51", 51, PPC_OPERAND_VSR },
+  { "vs52", 52, PPC_OPERAND_VSR },
+  { "vs53", 53, PPC_OPERAND_VSR },
+  { "vs54", 54, PPC_OPERAND_VSR },
+  { "vs55", 55, PPC_OPERAND_VSR },
+  { "vs56", 56, PPC_OPERAND_VSR },
+  { "vs57", 57, PPC_OPERAND_VSR },
+  { "vs58", 58, PPC_OPERAND_VSR },
+  { "vs59", 59, PPC_OPERAND_VSR },
+  { "vs6", 6, PPC_OPERAND_VSR },
+  { "vs60", 60, PPC_OPERAND_VSR },
+  { "vs61", 61, PPC_OPERAND_VSR },
+  { "vs62", 62, PPC_OPERAND_VSR },
+  { "vs63", 63, PPC_OPERAND_VSR },
+  { "vs7", 7, PPC_OPERAND_VSR },
+  { "vs8", 8, PPC_OPERAND_VSR },
+  { "vs9", 9, PPC_OPERAND_VSR },
+
+  { "xer", 1, PPC_OPERAND_SPR }
 };
 
 #define REG_NAME_CNT   (sizeof (pre_defined_registers) / sizeof (struct pd_reg))
@@ -807,7 +807,7 @@ static const struct pd_reg pre_defined_registers[] =
 /* Given NAME, find the register number associated with that name, return
    the integer value associated with the given name or -1 on failure.  */
 
-static int
+static const struct pd_reg *
 reg_name_search (const struct pd_reg *regs, int regcount, const char *name)
 {
   int middle, low, high;
@@ -825,11 +825,11 @@ reg_name_search (const struct pd_reg *regs, int regcount, const char *name)
       else if (cmp > 0)
        low = middle + 1;
       else
-       return regs[middle].value;
+       return &regs[middle];
     }
   while (low <= high);
 
-  return -1;
+  return NULL;
 }
 
 /*
@@ -847,7 +847,7 @@ reg_name_search (const struct pd_reg *regs, int regcount, const char *name)
 static bfd_boolean
 register_name (expressionS *expressionP)
 {
-  int reg_number;
+  const struct pd_reg *reg;
   char *name;
   char *start;
   char c;
@@ -861,16 +861,17 @@ register_name (expressionS *expressionP)
     return FALSE;
 
   c = get_symbol_name (&name);
-  reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT, name);
+  reg = reg_name_search (pre_defined_registers, REG_NAME_CNT, name);
 
   /* Put back the delimiting char.  */
   *input_line_pointer = c;
 
   /* Look to see if it's in the register table.  */
-  if (reg_number >= 0)
+  if (reg != NULL)
     {
       expressionP->X_op = O_register;
-      expressionP->X_add_number = reg_number;
+      expressionP->X_add_number = reg->value;
+      expressionP->X_md = reg->flags;
 
       /* Make the rest nice.  */
       expressionP->X_add_symbol = NULL;
@@ -893,19 +894,19 @@ static bfd_boolean cr_operand;
 /* Names to recognize in a condition code.  This table is sorted.  */
 static const struct pd_reg cr_names[] =
 {
-  { "cr0", 0 },
-  { "cr1", 1 },
-  { "cr2", 2 },
-  { "cr3", 3 },
-  { "cr4", 4 },
-  { "cr5", 5 },
-  { "cr6", 6 },
-  { "cr7", 7 },
-  { "eq", 2 },
-  { "gt", 1 },
-  { "lt", 0 },
-  { "so", 3 },
-  { "un", 3 }
+  { "cr0", 0, PPC_OPERAND_CR_REG },
+  { "cr1", 1, PPC_OPERAND_CR_REG },
+  { "cr2", 2, PPC_OPERAND_CR_REG },
+  { "cr3", 3, PPC_OPERAND_CR_REG },
+  { "cr4", 4, PPC_OPERAND_CR_REG },
+  { "cr5", 5, PPC_OPERAND_CR_REG },
+  { "cr6", 6, PPC_OPERAND_CR_REG },
+  { "cr7", 7, PPC_OPERAND_CR_REG },
+  { "eq", 2, PPC_OPERAND_CR_BIT },
+  { "gt", 1, PPC_OPERAND_CR_BIT },
+  { "lt", 0, PPC_OPERAND_CR_BIT },
+  { "so", 3, PPC_OPERAND_CR_BIT },
+  { "un", 3, PPC_OPERAND_CR_BIT }
 };
 
 /* Parsing function.  This returns non-zero if it recognized an
@@ -914,23 +915,78 @@ static const struct pd_reg cr_names[] =
 int
 ppc_parse_name (const char *name, expressionS *exp)
 {
-  int val;
+  const struct pd_reg *reg;
 
   if (! cr_operand)
     return 0;
 
   if (*name == '%')
     ++name;
-  val = reg_name_search (cr_names, sizeof cr_names / sizeof cr_names[0],
+  reg = reg_name_search (cr_names, sizeof cr_names / sizeof cr_names[0],
                         name);
-  if (val < 0)
+  if (reg == NULL)
     return 0;
 
-  exp->X_op = O_constant;
-  exp->X_add_number = val;
+  exp->X_op = O_register;
+  exp->X_add_number = reg->value;
+  exp->X_md = reg->flags;
 
   return 1;
 }
+
+/* Propagate X_md and check register expressions.  This is to support
+   condition codes like 4*cr5+eq.  */
+
+int
+ppc_optimize_expr (expressionS *left, operatorT op, expressionS *right)
+{
+  /* Accept 4*cr<n> and cr<n>*4.  */
+  if (op == O_multiply
+      && ((right->X_op == O_register
+          && right->X_md == PPC_OPERAND_CR_REG
+          && left->X_op == O_constant
+          && left->X_add_number == 4)
+         || (left->X_op == O_register
+             && left->X_md == PPC_OPERAND_CR_REG
+             && right->X_op == O_constant
+             && right->X_add_number == 4)))
+    {
+      left->X_op = O_register;
+      left->X_md = PPC_OPERAND_CR_REG | PPC_OPERAND_CR_BIT;
+      left->X_add_number *= right->X_add_number;
+      return 1;
+    }
+
+  /* Accept the above plus <cr bit>, and <cr bit> plus the above.  */
+  if (right->X_op == O_register
+      && left->X_op == O_register
+      && op == O_add
+      && ((right->X_md == PPC_OPERAND_CR_BIT
+          && left->X_md == (PPC_OPERAND_CR_REG | PPC_OPERAND_CR_BIT))
+         || (right->X_md == (PPC_OPERAND_CR_REG | PPC_OPERAND_CR_BIT)
+             && left->X_md == PPC_OPERAND_CR_BIT)))
+    {
+      left->X_md = PPC_OPERAND_CR_BIT;
+      right->X_op = O_constant;
+      return 0;
+    }
+
+  /* Accept reg +/- constant.  */
+  if (left->X_op == O_register
+      && !((op == O_add || op == O_subtract) && right->X_op == O_constant))
+    as_warn (_("invalid register expression"));
+
+  /* Accept constant + reg.  */
+  if (right->X_op == O_register)
+    {
+      if (op == O_add && left->X_op == O_constant)
+       left->X_md = right->X_md;
+      else
+       as_warn (_("invalid register expression"));
+    }
+
+  return 0;
+}
 \f
 /* Local variables.  */
 
@@ -1046,18 +1102,6 @@ static segT ppc_current_section;
 
 #ifdef OBJ_ELF
 symbolS *GOT_symbol;           /* Pre-defined "_GLOBAL_OFFSET_TABLE" */
-#define PPC_APUINFO_ISEL       0x40
-#define PPC_APUINFO_PMR                0x41
-#define PPC_APUINFO_RFMCI      0x42
-#define PPC_APUINFO_CACHELCK   0x43
-#define PPC_APUINFO_SPE                0x100
-#define PPC_APUINFO_EFS                0x101
-#define PPC_APUINFO_BRLOCK     0x102
-#define PPC_APUINFO_VLE                0x104
-
-/*
- * We keep a list of APUinfo
- */
 unsigned long *ppc_apuinfo_list;
 unsigned int ppc_apuinfo_num;
 unsigned int ppc_apuinfo_num_alloc;
@@ -1149,7 +1193,8 @@ md_parse_option (int c, const char *arg)
 
     case 'm':
       new_cpu = ppc_parse_cpu (ppc_cpu, &sticky, arg);
-      if (new_cpu != 0)
+      /* "raw" is only valid for the disassembler.  */
+      if (new_cpu != 0 && (new_cpu & PPC_OPCODE_RAW) == 0)
        {
          ppc_cpu = new_cpu;
          if (strcmp (arg, "vle") == 0)
@@ -1161,6 +1206,16 @@ md_parse_option (int c, const char *arg)
            }
        }
 
+      else if (strcmp (arg, "no-vle") == 0)
+       {
+         sticky &= ~PPC_OPCODE_VLE;
+
+         new_cpu = ppc_parse_cpu (ppc_cpu, &sticky, "booke");
+         new_cpu &= ~PPC_OPCODE_VLE;
+
+         ppc_cpu = new_cpu;
+       }
+
       else if (strcmp (arg, "regnames") == 0)
        reg_names_p = TRUE;
 
@@ -1213,6 +1268,10 @@ md_parse_option (int c, const char *arg)
          msolaris = FALSE;
          ppc_comment_chars = ppc_eabi_comment_chars;
        }
+      else if (strcmp (arg, "spe2") == 0)
+       {
+         ppc_cpu |= PPC_OPCODE_SPE2;
+       }
 #endif
       else
        {
@@ -1296,12 +1355,11 @@ PowerPC options:\n\
 -mpower8, -mpwr8        generate code for Power8 architecture\n\
 -mpower9, -mpwr9        generate code for Power9 architecture\n\
 -mcell                  generate code for Cell Broadband Engine architecture\n\
--mcom                   generate code Power/PowerPC common instructions\n\
+-mcom                   generate code for Power/PowerPC common instructions\n\
 -many                   generate code for any architecture (PWR/PWRX/PPC)\n"));
   fprintf (stream, _("\
 -maltivec               generate code for AltiVec\n\
 -mvsx                   generate code for Vector-Scalar (VSX) instructions\n\
--mhtm                   generate code for Hardware Transactional Memory\n\
 -me300                  generate code for PowerPC e300 family\n\
 -me500, -me500x2        generate code for Motorola e500 core complex\n\
 -me500mc,               generate code for Freescale e500mc core complex\n\
@@ -1309,6 +1367,7 @@ PowerPC options:\n\
 -me5500,                generate code for Freescale e5500 core complex\n\
 -me6500,                generate code for Freescale e6500 core complex\n\
 -mspe                   generate code for Motorola SPE instructions\n\
+-mspe2                  generate code for Freescale SPE2 instructions\n\
 -mvle                   generate code for Freescale VLE instructions\n\
 -mtitan                 generate code for AppliedMicro Titan core complex\n\
 -mregnames              Allow symbolic names for registers\n\
@@ -1438,7 +1497,7 @@ static bfd_boolean
 insn_validate (const struct powerpc_opcode *op)
 {
   const unsigned char *o;
-  unsigned long omask = op->mask;
+  uint64_t omask = op->mask;
 
   /* The mask had better not trim off opcode bits.  */
   if ((op->opcode & omask) != op->opcode)
@@ -1460,7 +1519,7 @@ insn_validate (const struct powerpc_opcode *op)
          const struct powerpc_operand *operand = &powerpc_operands[*o];
          if (operand->shift != (int) PPC_OPSHIFT_INV)
            {
-             unsigned long mask;
+             uint64_t mask;
 
              if (operand->shift >= 0)
                mask = operand->bitm << operand->shift;
@@ -1511,8 +1570,8 @@ ppc_setup_opcodes (void)
         all the 1's in the mask are contiguous.  */
       for (i = 0; i < num_powerpc_operands; ++i)
        {
-         unsigned long mask = powerpc_operands[i].bitm;
-         unsigned long right_bit;
+         uint64_t mask = powerpc_operands[i].bitm;
+         uint64_t right_bit;
          unsigned int j;
 
          right_bit = mask & -mask;
@@ -1545,10 +1604,10 @@ ppc_setup_opcodes (void)
              int new_opcode = PPC_OP (op[0].opcode);
 
 #ifdef PRINT_OPCODE_TABLE
-             printf ("%-14s\t#%04u\tmajor op: 0x%x\top: 0x%x\tmask: 0x%x\tflags: 0x%llx\n",
+             printf ("%-14s\t#%04u\tmajor op: 0x%x\top: 0x%llx\tmask: 0x%llx\tflags: 0x%llx\n",
                      op->name, (unsigned int) (op - powerpc_opcodes),
-                     (unsigned int) new_opcode, (unsigned int) op->opcode,
-                     (unsigned int) op->mask, (unsigned long long) op->flags);
+                     (unsigned int) new_opcode, (unsigned long long) op->opcode,
+                     (unsigned long long) op->mask, (unsigned long long) op->flags);
 #endif
 
              /* The major opcodes had better be sorted.  Code in the
@@ -1561,6 +1620,18 @@ ppc_setup_opcodes (void)
                  bad_insn = TRUE;
                }
            }
+         if ((op->flags & PPC_OPCODE_VLE) != 0)
+           {
+             as_bad (_("%s is enabled by vle flag"), op->name);
+             bad_insn = TRUE;
+           }
+         if (PPC_OP (op->opcode) != 4
+             && PPC_OP (op->opcode) != 31
+             && (op->deprecated & PPC_OPCODE_VLE) == 0)
+           {
+             as_bad (_("%s not disabled by vle flag"), op->name);
+             bad_insn = TRUE;
+           }
          bad_insn |= insn_validate (op);
        }
 
@@ -1598,10 +1669,10 @@ ppc_setup_opcodes (void)
              new_seg = VLE_OP_TO_SEG (new_seg);
 
 #ifdef PRINT_OPCODE_TABLE
-             printf ("%-14s\t#%04u\tmajor op: 0x%x\top: 0x%x\tmask: 0x%x\tflags: 0x%llx\n",
+             printf ("%-14s\t#%04u\tmajor op: 0x%x\top: 0x%llx\tmask: 0x%llx\tflags: 0x%llx\n",
                      op->name, (unsigned int) (op - powerpc_opcodes),
-                     (unsigned int) new_seg, (unsigned int) op->opcode,
-                     (unsigned int) op->mask, (unsigned long long) op->flags);
+                     (unsigned int) new_seg, (unsigned long long) op->opcode,
+                     (unsigned long long) op->mask, (unsigned long long) op->flags);
 #endif
              /* The major opcodes had better be sorted.  Code in the
                 disassembler assumes the insns are sorted according to
@@ -1632,9 +1703,53 @@ ppc_setup_opcodes (void)
        }
     }
 
-  if ((ppc_cpu & PPC_OPCODE_VLE) != 0)
-    for (op = vle_opcodes; op < op_end; op++)
-      hash_insert (ppc_hash, op->name, (void *) op);
+  /* SPE2 instructions */
+  if ((ppc_cpu & PPC_OPCODE_SPE2) == PPC_OPCODE_SPE2)
+    {
+      op_end = spe2_opcodes + spe2_num_opcodes;
+      for (op = spe2_opcodes; op < op_end; op++)
+       {
+         if (ENABLE_CHECKING)
+           {
+             if (op != spe2_opcodes)
+               {
+               unsigned old_seg, new_seg;
+
+               old_seg = VLE_OP (op[-1].opcode, op[-1].mask);
+               old_seg = VLE_OP_TO_SEG (old_seg);
+               new_seg = VLE_OP (op[0].opcode, op[0].mask);
+               new_seg = VLE_OP_TO_SEG (new_seg);
+
+               /* The major opcodes had better be sorted.  Code in the
+                   disassembler assumes the insns are sorted according to
+                   major opcode.  */
+               if (new_seg < old_seg)
+                 {
+                 as_bad (_("major opcode is not sorted for %s"), op->name);
+                 bad_insn = TRUE;
+                 }
+               }
+
+             bad_insn |= insn_validate (op);
+           }
+
+         if ((ppc_cpu & op->flags) != 0 && !(ppc_cpu & op->deprecated))
+           {
+             const char *retval;
+
+             retval = hash_insert (ppc_hash, op->name, (void *) op);
+             if (retval != NULL)
+               {
+                 as_bad (_("duplicate instruction %s"),
+                         op->name);
+                 bad_insn = TRUE;
+               }
+           }
+       }
+
+      for (op = spe2_opcodes; op < op_end; op++)
+       hash_insert (ppc_hash, op->name, (void *) op);
+    }
 
   /* Insert the macros into a hash table.  */
   ppc_macro_hash = hash_new ();
@@ -1734,7 +1849,7 @@ ppc_cleanup (void)
     unsigned int i;
 
     /* Create the .PPC.EMB.apuinfo section.  */
-    apuinfo_secp = subseg_new (".PPC.EMB.apuinfo", 0);
+    apuinfo_secp = subseg_new (APUINFO_SECTION_NAME, 0);
     bfd_set_section_flags (stdoutput,
                           apuinfo_secp,
                           SEC_HAS_CONTENTS | SEC_READONLY);
@@ -1749,7 +1864,7 @@ ppc_cleanup (void)
     md_number_to_chars (p, (valueT) 2, 4);
 
     p = frag_more (8);
-    strcpy (p, "APUinfo");
+    strcpy (p, APUINFO_LABEL);
 
     for (i = 0; i < ppc_apuinfo_num; i++)
       {
@@ -1769,15 +1884,15 @@ ppc_cleanup (void)
 
 /* Insert an operand value into an instruction.  */
 
-static unsigned long
-ppc_insert_operand (unsigned long insn,
+static uint64_t
+ppc_insert_operand (uint64_t insn,
                    const struct powerpc_operand *operand,
-                   offsetT val,
+                   int64_t val,
                    ppc_cpu_t cpu,
                    const char *file,
                    unsigned int line)
 {
-  long min, max, right;
+  int64_t min, max, right;
 
   max = operand->bitm;
   right = max & -max;
@@ -1785,17 +1900,15 @@ ppc_insert_operand (unsigned long insn,
 
   if ((operand->flags & PPC_OPERAND_SIGNOPT) != 0)
     {
-      /* Extend the allowed range for addis to [-65536, 65535].
-        Similarly for some VLE high part insns.  For 64-bit it
-        would be good to disable this for signed fields since the
+      /* Extend the allowed range for addis to [-32768, 65535].
+        Similarly for cmpli and some VLE high part insns.  For 64-bit
+        it would be good to disable this for signed fields since the
         value is sign extended into the high 32 bits of the register.
         If the value is, say, an address, then we might care about
         the high bits.  However, gcc as of 2014-06 uses unsigned
         values when loading the high part of 64-bit constants using
-        lis.
-        Use the same extended range for cmpli, to allow at least
-        [-32768, 65535].  */
-      min = ~max & -right;
+        lis.  */
+      min = ~(max >> 1) & -right;
     }
   else if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
     {
@@ -1808,7 +1921,7 @@ ppc_insert_operand (unsigned long insn,
 
   if ((operand->flags & PPC_OPERAND_NEGATIVE) != 0)
     {
-      long tmp = min;
+      int64_t tmp = min;
       min = -max;
       max = -tmp;
     }
@@ -1821,18 +1934,18 @@ ppc_insert_operand (unsigned long insn,
         sign extend the 32-bit value to 64 bits if so doing makes the
         value valid.  */
       if (val > max
-         && (offsetT) (val - 0x80000000 - 0x80000000) >= min
-         && (offsetT) (val - 0x80000000 - 0x80000000) <= max
-         && ((val - 0x80000000 - 0x80000000) & (right - 1)) == 0)
-       val = val - 0x80000000 - 0x80000000;
+         && (val - (1LL << 32)) >= min
+         && (val - (1LL << 32)) <= max
+         && ((val - (1LL << 32)) & (right - 1)) == 0)
+       val = val - (1LL << 32);
 
       /* Similarly, people write expressions like ~(1<<15), and expect
         this to be OK for a 32-bit unsigned value.  */
       else if (val < min
-              && (offsetT) (val + 0x80000000 + 0x80000000) >= min
-              && (offsetT) (val + 0x80000000 + 0x80000000) <= max
-              && ((val + 0x80000000 + 0x80000000) & (right - 1)) == 0)
-       val = val + 0x80000000 + 0x80000000;
+              && (val + (1LL << 32)) >= min
+              && (val + (1LL << 32)) <= max
+              && ((val + (1LL << 32)) & (right - 1)) == 0)
+       val = val + (1LL << 32);
 
       else if (val < min
               || val > max
@@ -1845,14 +1958,14 @@ ppc_insert_operand (unsigned long insn,
       const char *errmsg;
 
       errmsg = NULL;
-      insn = (*operand->insert) (insn, (long) val, cpu, &errmsg);
+      insn = (*operand->insert) (insn, val, cpu, &errmsg);
       if (errmsg != (const char *) NULL)
        as_bad_where (file, line, "%s", errmsg);
     }
   else if (operand->shift >= 0)
-    insn |= ((long) val & operand->bitm) << operand->shift;
+    insn |= (val & operand->bitm) << operand->shift;
   else
-    insn |= ((long) val & operand->bitm) >> -operand->shift;
+    insn |= (val & operand->bitm) >> -operand->shift;
 
   return insn;
 }
@@ -2318,6 +2431,28 @@ ppc_elf_abiversion (int ignore ATTRIBUTE_UNUSED)
   demand_empty_rest_of_line ();
 }
 
+/* Parse a .gnu_attribute directive.  */
+static void
+ppc_elf_gnu_attribute (int ignored ATTRIBUTE_UNUSED)
+{
+  int tag = obj_elf_vendor_attribute (OBJ_ATTR_GNU);
+
+  /* Check validity of defined powerpc tags.  */
+  if (tag == Tag_GNU_Power_ABI_FP
+      || tag == Tag_GNU_Power_ABI_Vector
+      || tag == Tag_GNU_Power_ABI_Struct_Return)
+    {
+      unsigned int val;
+
+      val = bfd_elf_get_obj_attr_int (stdoutput, OBJ_ATTR_GNU, tag);
+
+      if ((tag == Tag_GNU_Power_ABI_FP && val > 15)
+         || (tag == Tag_GNU_Power_ABI_Vector && val > 3)
+         || (tag == Tag_GNU_Power_ABI_Struct_Return && val > 2))
+       as_warn (_("unknown .gnu_attribute value"));
+    }
+}
+
 /* Set ABI version in output file.  */
 void
 ppc_elf_end (void)
@@ -2597,22 +2732,6 @@ struct ppc_fixup
 
 #define MAX_INSN_FIXUPS (5)
 
-/* Form I16L.  */
-#define E_OR2I_INSN            0x7000C000
-#define E_AND2I_DOT_INSN       0x7000C800
-#define E_OR2IS_INSN           0x7000D000
-#define E_LIS_INSN             0x7000E000
-#define        E_AND2IS_DOT_INSN       0x7000E800
-
-/* Form I16A.  */
-#define E_ADD2I_DOT_INSN       0x70008800
-#define E_ADD2IS_INSN          0x70009000
-#define E_CMP16I_INSN          0x70009800
-#define E_MULL2I_INSN          0x7000A000
-#define E_CMPL16I_INSN         0x7000A800
-#define E_CMPH16I_INSN         0x7000B000
-#define E_CMPHL16I_INSN                0x7000B800
-
 /* This routine is called for each instruction to be assembled.  */
 
 void
@@ -2620,7 +2739,7 @@ md_assemble (char *str)
 {
   char *s;
   const struct powerpc_opcode *opcode;
-  unsigned long insn;
+  uint64_t insn;
   const unsigned char *opindex_ptr;
   int skip_optional;
   int need_paren;
@@ -2675,7 +2794,8 @@ md_assemble (char *str)
       const struct powerpc_operand *operand;
 
       operand = &powerpc_operands[*opindex_ptr];
-      if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
+      if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
+         && !((operand->flags & PPC_OPERAND_OPTIONAL32) != 0 && ppc_obj64))
        {
          unsigned int opcount;
          unsigned int num_operands_expected;
@@ -2745,9 +2865,10 @@ md_assemble (char *str)
       /* If this is an optional operand, and we are skipping it, just
         insert a zero.  */
       if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
+         && !((operand->flags & PPC_OPERAND_OPTIONAL32) != 0 && ppc_obj64)
          && skip_optional)
        {
-         long val = ppc_optional_operand_value (operand);
+         int64_t val = ppc_optional_operand_value (operand);
          if (operand->insert)
            {
              insn = (*operand->insert) (insn, val, ppc_cpu, &errmsg);
@@ -2755,9 +2876,9 @@ md_assemble (char *str)
                as_bad ("%s", errmsg);
            }
          else if (operand->shift >= 0)
-           insn |= ((long) val & operand->bitm) << operand->shift;
+           insn |= (val & operand->bitm) << operand->shift;
          else
-           insn |= ((long) val & operand->bitm) >> -operand->shift;
+           insn |= (val & operand->bitm) >> -operand->shift;
 
          if ((operand->flags & PPC_OPERAND_NEXT) != 0)
            next_opindex = *opindex_ptr + 1;
@@ -2910,6 +3031,15 @@ md_assemble (char *str)
        as_bad (_("missing operand"));
       else if (ex.X_op == O_register)
        {
+         if ((ex.X_md
+              & ~operand->flags
+              & (PPC_OPERAND_GPR | PPC_OPERAND_FPR | PPC_OPERAND_VR
+                 | PPC_OPERAND_VSR | PPC_OPERAND_CR_BIT | PPC_OPERAND_CR_REG
+                 | PPC_OPERAND_SPR | PPC_OPERAND_GQR)) != 0
+             && !((ex.X_md & PPC_OPERAND_GPR) != 0
+                  && ex.X_add_number != 0
+                  && (operand->flags & PPC_OPERAND_GPR_0) != 0))
+           as_warn (_("invalid register expression"));
          insn = ppc_insert_operand (insn, operand, ex.X_add_number,
                                     ppc_cpu, (char *) NULL, 0);
        }
@@ -2946,7 +3076,7 @@ md_assemble (char *str)
                      }
                    break;
                  }
-               /* Fall thru */
+               /* Fallthru */
 
              case BFD_RELOC_PPC64_ADDR16_HIGH:
                ex.X_add_number = PPC_HI (ex.X_add_number);
@@ -2968,7 +3098,7 @@ md_assemble (char *str)
                      }
                    break;
                  }
-               /* Fall thru */
+               /* Fallthru */
 
              case BFD_RELOC_PPC64_ADDR16_HIGHA:
                ex.X_add_number = PPC_HA (ex.X_add_number);
@@ -3084,21 +3214,21 @@ md_assemble (char *str)
              /* addpcis.  */
              if (opcode->opcode == (19 << 26) + (2 << 1)
                  && reloc == BFD_RELOC_HI16_S)
-               reloc = BFD_RELOC_PPC_REL16DX_HA;
+               reloc = BFD_RELOC_PPC_16DX_HA;
 
              /* If VLE-mode convert LO/HI/HA relocations.  */
              if (opcode->flags & PPC_OPCODE_VLE)
                {
-                 int tmp_insn = insn & opcode->mask;
+                 uint64_t tmp_insn = insn & opcode->mask;
 
-                 int use_d_reloc = (tmp_insn == E_OR2I_INSN
+                 int use_a_reloc = (tmp_insn == E_OR2I_INSN
                                     || tmp_insn == E_AND2I_DOT_INSN
                                     || tmp_insn == E_OR2IS_INSN
                                     || tmp_insn == E_LIS_INSN
                                     || tmp_insn == E_AND2IS_DOT_INSN);
 
 
-                 int use_a_reloc = (tmp_insn == E_ADD2I_DOT_INSN
+                 int use_d_reloc = (tmp_insn == E_ADD2I_DOT_INSN
                                     || tmp_insn == E_ADD2IS_INSN
                                     || tmp_insn == E_CMP16I_INSN
                                     || tmp_insn == E_MULL2I_INSN
@@ -3381,13 +3511,17 @@ md_assemble (char *str)
          however it'll remain clear for dual-mode instructions on
          dual-mode and, more importantly, standard-mode processors.  */
       if ((ppc_cpu & opcode->flags) == PPC_OPCODE_VLE)
-       ppc_apuinfo_section_add (PPC_APUINFO_VLE, 1);
+       {
+         ppc_apuinfo_section_add (PPC_APUINFO_VLE, 1);
+         if (elf_section_data (now_seg) != NULL)
+           elf_section_data (now_seg)->this_hdr.sh_flags |= SHF_PPC_VLE;
+       }
     }
 #endif
 
   /* Write out the instruction.  */
   /* Differentiate between two and four byte insns.  */
-  if (ppc_mach () == bfd_mach_ppc_vle)
+  if ((ppc_cpu & PPC_OPCODE_VLE) != 0)
     {
       if (PPC_OP_SE_VLE (insn))
         insn_length = 2;
@@ -3404,7 +3538,7 @@ md_assemble (char *str)
   f = frag_more (insn_length);
   if (frag_now->has_code && frag_now->insn_addr != addr_mod)
     {
-      if (ppc_mach() == bfd_mach_ppc_vle)
+      if ((ppc_cpu & PPC_OPCODE_VLE) != 0)
         as_bad (_("instruction address is not a multiple of 2"));
       else
         as_bad (_("instruction address is not a multiple of 4"));
@@ -3559,6 +3693,16 @@ ppc_section_flags (flagword flags, bfd_vma attr ATTRIBUTE_UNUSED, int type)
 
   return flags;
 }
+
+bfd_vma
+ppc_elf_section_letter (int letter, const char **ptrmsg)
+{
+  if (letter == 'v')
+    return SHF_PPC_VLE;
+
+  *ptrmsg = _("bad .section directive: want a,e,v,w,x,M,S,G,T in string");
+  return -1;
+}
 #endif /* OBJ_ELF */
 
 \f
@@ -4163,7 +4307,7 @@ ppc_lglobl (int ignore ATTRIBUTE_UNUSED)
 
    (In principle, there's no reason why the relocations _have_ to be at
    the beginning.  Anywhere in the csect would do.  However, inserting
-   at the beginning is what the native assmebler does, and it helps to
+   at the beginning is what the native assembler does, and it helps to
    deal with cases where the .ref statements follow the section contents.)
 
    ??? .refs don't work for empty .csects.  However, the native assembler
@@ -5098,7 +5242,7 @@ ppc_ydata (int ignore ATTRIBUTE_UNUSED)
    initial:   .section .reldata "drw3"
              d - initialized data
              r - readable
-             w - writeable
+             w - writable
              3 - double word aligned (that would be 8 byte boundary)
 
    commentary:
@@ -5334,13 +5478,13 @@ ppc_pe_comm (int lcomm)
  *
  * Section Protection:
  * 'r' - section is readable
- * 'w' - section is writeable
+ * 'w' - section is writable
  * 'x' - section is executable
  * 's' - section is sharable
  *
  * Section Alignment:
  * '0' - align to byte boundary
- * '1' - align to halfword undary
+ * '1' - align to halfword boundary
  * '2' - align to word boundary
  * '3' - align to doubleword boundary
  * '4' - align to quadword boundary
@@ -5441,7 +5585,7 @@ ppc_pe_section (int ignore ATTRIBUTE_UNUSED)
                case 'r': /* section is readable */
                  flags |= IMAGE_SCN_MEM_READ;
                  break;
-               case 'w': /* section is writeable */
+               case 'w': /* section is writable */
                  flags |= IMAGE_SCN_MEM_WRITE;
                  break;
                case 'x': /* section is executable */
@@ -6350,7 +6494,7 @@ ppc_frag_check (struct frag *fragP)
   if (!fragP->has_code)
     return;
 
-  if (ppc_mach() == bfd_mach_ppc_vle)
+  if ((ppc_cpu & PPC_OPCODE_VLE) != 0)
     {
       if (((fragP->fr_address + fragP->insn_addr) & 1) != 0)
         as_bad (_("instruction address is not a multiple of 2"));
@@ -6371,7 +6515,7 @@ ppc_handle_align (struct frag *fragP)
   valueT count = (fragP->fr_next->fr_address
                  - (fragP->fr_address + fragP->fr_fix));
 
-  if (ppc_mach() == bfd_mach_ppc_vle && count != 0 && (count & 1) == 0)
+  if ((ppc_cpu & PPC_OPCODE_VLE) != 0 && count != 0 && (count & 1) == 0)
     {
       char *dest = fragP->fr_literal + fragP->fr_fix;
 
@@ -6495,10 +6639,50 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
     }
 #endif
 
-  if (fixP->fx_subsy != (symbolS *) NULL)
+  /* We are only able to convert some relocs to pc-relative.  */
+  if (fixP->fx_pcrel)
+    {
+      switch (fixP->fx_r_type)
+       {
+       case BFD_RELOC_LO16:
+         fixP->fx_r_type = BFD_RELOC_LO16_PCREL;
+         break;
+
+       case BFD_RELOC_HI16:
+         fixP->fx_r_type = BFD_RELOC_HI16_PCREL;
+         break;
+
+       case BFD_RELOC_HI16_S:
+         fixP->fx_r_type = BFD_RELOC_HI16_S_PCREL;
+         break;
+
+       case BFD_RELOC_64:
+         fixP->fx_r_type = BFD_RELOC_64_PCREL;
+         break;
+
+       case BFD_RELOC_32:
+         fixP->fx_r_type = BFD_RELOC_32_PCREL;
+         break;
+
+       case BFD_RELOC_16:
+         fixP->fx_r_type = BFD_RELOC_16_PCREL;
+         break;
+
+       case BFD_RELOC_PPC_16DX_HA:
+         fixP->fx_r_type = BFD_RELOC_PPC_REL16DX_HA;
+         break;
+
+       default:
+         break;
+       }
+    }
+  else if (!fixP->fx_done
+          && fixP->fx_r_type == BFD_RELOC_PPC_16DX_HA)
     {
-      /* We can't actually support subtracting a symbol.  */
-      as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
+      /* addpcis is relative to next insn address.  */
+      value -= 4;
+      fixP->fx_r_type = BFD_RELOC_PPC_REL16DX_HA;
+      fixP->fx_pcrel = 1;
     }
 
   operand = NULL;
@@ -6569,7 +6753,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
            }
          break;
        }
-      /* Fall thru */
+      /* Fallthru */
 
     case BFD_RELOC_PPC_VLE_HI16A:
     case BFD_RELOC_PPC_VLE_HI16D:
@@ -6580,6 +6764,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
 
     case BFD_RELOC_HI16_S:
     case BFD_RELOC_HI16_S_PCREL:
+    case BFD_RELOC_PPC_16DX_HA:
     case BFD_RELOC_PPC_REL16DX_HA:
 #ifdef OBJ_ELF
       if (REPORT_OVERFLOW_HI && ppc_obj64)
@@ -6592,7 +6777,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
            }
          break;
        }
-      /* Fall thru */
+      /* Fallthru */
 
     case BFD_RELOC_PPC_VLE_HA16A:
     case BFD_RELOC_PPC_VLE_HA16D:
@@ -6734,7 +6919,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
        case BFD_RELOC_PPC_VLE_SDAREL_HA16A:
        case BFD_RELOC_PPC_VLE_SDAREL_HA16D:
          gas_assert (fixP->fx_addsy != NULL);
-         /* Fall thru */
+         /* Fallthru */
 
        case BFD_RELOC_PPC_TLS:
        case BFD_RELOC_PPC_TLSGD:
@@ -6858,7 +7043,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
              && !S_IS_DEFINED (fixP->fx_addsy)
              && !S_IS_WEAK (fixP->fx_addsy))
            S_SET_WEAK (fixP->fx_addsy);
-         /* Fall thru */
+         /* Fallthru */
 
        case BFD_RELOC_VTABLE_ENTRY:
          fixP->fx_done = 0;
@@ -7007,83 +7192,6 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
                       _("data in executable section"));
     }
 
-  /* We are only able to convert some relocs to pc-relative.  */
-  if (!fixP->fx_done && fixP->fx_pcrel)
-    {
-      switch (fixP->fx_r_type)
-       {
-       case BFD_RELOC_LO16:
-         fixP->fx_r_type = BFD_RELOC_LO16_PCREL;
-         break;
-
-       case BFD_RELOC_HI16:
-         fixP->fx_r_type = BFD_RELOC_HI16_PCREL;
-         break;
-
-       case BFD_RELOC_HI16_S:
-         fixP->fx_r_type = BFD_RELOC_HI16_S_PCREL;
-         break;
-
-       case BFD_RELOC_64:
-         fixP->fx_r_type = BFD_RELOC_64_PCREL;
-         break;
-
-       case BFD_RELOC_32:
-         fixP->fx_r_type = BFD_RELOC_32_PCREL;
-         break;
-
-       case BFD_RELOC_16:
-         fixP->fx_r_type = BFD_RELOC_16_PCREL;
-         break;
-
-         /* Some of course are already pc-relative.  */
-       case BFD_RELOC_LO16_PCREL:
-       case BFD_RELOC_HI16_PCREL:
-       case BFD_RELOC_HI16_S_PCREL:
-       case BFD_RELOC_PPC_REL16DX_HA:
-       case BFD_RELOC_64_PCREL:
-       case BFD_RELOC_32_PCREL:
-       case BFD_RELOC_16_PCREL:
-       case BFD_RELOC_PPC_B16:
-       case BFD_RELOC_PPC_B16_BRTAKEN:
-       case BFD_RELOC_PPC_B16_BRNTAKEN:
-       case BFD_RELOC_PPC_B26:
-       case BFD_RELOC_PPC_LOCAL24PC:
-       case BFD_RELOC_24_PLT_PCREL:
-       case BFD_RELOC_32_PLT_PCREL:
-       case BFD_RELOC_64_PLT_PCREL:
-       case BFD_RELOC_PPC_VLE_REL8:
-       case BFD_RELOC_PPC_VLE_REL15:
-       case BFD_RELOC_PPC_VLE_REL24:
-         break;
-
-       default:
-         if (fixP->fx_addsy)
-           {
-             const char *sfile;
-             unsigned int sline;
-
-             /* 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,
-                             _("unresolved expression that must"
-                               " be resolved"));
-             else
-               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));
-           }
-         else
-           as_bad_where (fixP->fx_file, fixP->fx_line,
-                         _("unable to resolve expression"));
-         fixP->fx_done = 1;
-         break;
-       }
-    }
-
 #ifdef OBJ_ELF
   ppc_elf_validate_fix (fixP, seg);
   fixP->fx_addnumber = value;
This page took 0.053602 seconds and 4 git commands to generate.