[Arm, 2/3] Add instruction SB for AArch32
[deliverable/binutils-gdb.git] / gas / config / tc-arm.c
index ac403cc74e9871721f1b522239997241eddefb4f..1ecaa4594ad5236d5087d7bf283c0e7326459a4e 100644 (file)
@@ -75,6 +75,9 @@ static struct
   unsigned       sp_restored:1;
 } unwind;
 
+/* Whether --fdpic was given.  */
+static int arm_fdpic;
+
 #endif /* OBJ_ELF */
 
 /* Results from operand parsing worker functions.  */
@@ -253,6 +256,8 @@ static const arm_feature_set arm_ext_v8_2 =
   ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8_2A);
 static const arm_feature_set arm_ext_v8_3 =
   ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8_3A);
+static const arm_feature_set arm_ext_sb =
+  ARM_FEATURE_CORE_HIGH (ARM_EXT2_SB);
 
 static const arm_feature_set arm_arch_any = ARM_ANY;
 #ifdef OBJ_ELF
@@ -1040,7 +1045,6 @@ static int
 my_get_expression (expressionS * ep, char ** str, int prefix_mode)
 {
   char * save_in;
-  segT  seg;
 
   /* In unified syntax, all prefixes are optional.  */
   if (unified_syntax)
@@ -1072,7 +1076,7 @@ my_get_expression (expressionS * ep, char ** str, int prefix_mode)
   save_in = input_line_pointer;
   input_line_pointer = *str;
   in_my_get_expression = TRUE;
-  seg = expression (ep);
+  expression (ep);
   in_my_get_expression = FALSE;
 
   if (ep->X_op == O_illegal || ep->X_op == O_absent)
@@ -1086,22 +1090,6 @@ my_get_expression (expressionS * ep, char ** str, int prefix_mode)
       return 1;
     }
 
-#ifdef OBJ_AOUT
-  if (seg != absolute_section
-      && seg != text_section
-      && seg != data_section
-      && seg != bss_section
-      && seg != undefined_section)
-    {
-      inst.error = _("bad segment");
-      *str = input_line_pointer;
-      input_line_pointer = save_in;
-      return 1;
-    }
-#else
-  (void) seg;
-#endif
-
   /* Get rid of any bignums now, so that we don't generate an error for which
      we can't establish a line number later on.         Big numbers are never valid
      in instructions, which is where this routine is always called.  */
@@ -8433,11 +8421,12 @@ do_adr (void)
   inst.reloc.pc_rel = 1;
   inst.reloc.exp.X_add_number -= 8;
 
-  if (inst.reloc.exp.X_op == O_symbol
+  if (support_interwork
+      && inst.reloc.exp.X_op == O_symbol
       && inst.reloc.exp.X_add_symbol != NULL
       && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
       && THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
-    inst.reloc.exp.X_add_number += 1;
+    inst.reloc.exp.X_add_number |= 1;
 }
 
 /* This is a pseudo-op of the form "adrl rd, label" to be converted
@@ -8457,11 +8446,12 @@ do_adrl (void)
   inst.size                   = INSN_SIZE * 2;
   inst.reloc.exp.X_add_number -= 8;
 
-  if (inst.reloc.exp.X_op == O_symbol
+  if (support_interwork
+      && inst.reloc.exp.X_op == O_symbol
       && inst.reloc.exp.X_add_symbol != NULL
       && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
       && THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
-    inst.reloc.exp.X_add_number += 1;
+    inst.reloc.exp.X_add_number |= 1;
 }
 
 static void
@@ -16704,7 +16694,26 @@ do_neon_mov (void)
     case NS_HI:
     case NS_FI:  /* case 10 (fconsts).  */
       ldconst = "fconsts";
-      encode_fconstd:
+    encode_fconstd:
+      if (!inst.operands[1].immisfloat)
+       {
+         unsigned new_imm;
+         /* Immediate has to fit in 8 bits so float is enough.  */
+         float imm = (float) inst.operands[1].imm;
+         memcpy (&new_imm, &imm, sizeof (float));
+         /* But the assembly may have been written to provide an integer
+            bit pattern that equates to a float, so check that the
+            conversion has worked.  */
+         if (is_quarter_float (new_imm))
+           {
+             if (is_quarter_float (inst.operands[1].imm))
+               as_warn (_("immediate constant is valid both as a bit-pattern and a floating point value (using the fp value)"));
+
+             inst.operands[1].imm = new_imm;
+             inst.operands[1].immisfloat = 1;
+           }
+       }
+
       if (is_quarter_float (inst.operands[1].imm))
        {
          inst.operands[1].imm = neon_qfloat_bits (inst.operands[1].imm);
@@ -19317,7 +19326,16 @@ static struct reloc_entry reloc_names[] =
   { "tlscall", BFD_RELOC_ARM_TLS_CALL},
        { "TLSCALL", BFD_RELOC_ARM_TLS_CALL},
   { "tlsdescseq", BFD_RELOC_ARM_TLS_DESCSEQ},
-       { "TLSDESCSEQ", BFD_RELOC_ARM_TLS_DESCSEQ}
+       { "TLSDESCSEQ", BFD_RELOC_ARM_TLS_DESCSEQ},
+  { "gotfuncdesc", BFD_RELOC_ARM_GOTFUNCDESC },
+       { "GOTFUNCDESC", BFD_RELOC_ARM_GOTFUNCDESC },
+  { "gotofffuncdesc", BFD_RELOC_ARM_GOTOFFFUNCDESC },
+       { "GOTOFFFUNCDESC", BFD_RELOC_ARM_GOTOFFFUNCDESC },
+  { "funcdesc", BFD_RELOC_ARM_FUNCDESC },
+       { "FUNCDESC", BFD_RELOC_ARM_FUNCDESC },
+   { "tlsgd_fdpic", BFD_RELOC_ARM_TLS_GD32_FDPIC },      { "TLSGD_FDPIC", BFD_RELOC_ARM_TLS_GD32_FDPIC },
+   { "tlsldm_fdpic", BFD_RELOC_ARM_TLS_LDM32_FDPIC },    { "TLSLDM_FDPIC", BFD_RELOC_ARM_TLS_LDM32_FDPIC },
+   { "gottpoff_fdpic", BFD_RELOC_ARM_TLS_IE32_FDPIC },   { "GOTTPOFF_FDIC", BFD_RELOC_ARM_TLS_IE32_FDPIC },
 };
 #endif
 
@@ -20046,6 +20064,8 @@ static const struct asm_opcode insns[] =
 #define THUMB_VARIANT  & arm_ext_v6t2
 
  TUE("csdb",   320f014, f3af8014, 0, (), noargs, t_csdb),
+ TUF("ssbb",   57ff040, f3bf8f40, 0, (), noargs, t_csdb),
+ TUF("pssbb",  57ff044, f3bf8f44, 0, (), noargs, t_csdb),
 
 #undef  ARM_VARIANT
 #define ARM_VARIANT    & arm_ext_v6t2
@@ -21498,6 +21518,13 @@ static const struct asm_opcode insns[] =
  cCE("cfmadda32", e200600, 4, (RMAX, RMAX, RMFX, RMFX), mav_quad),
  cCE("cfmsuba32", e300600, 4, (RMAX, RMAX, RMFX, RMFX), mav_quad),
 
+ /* ARMv8.5-A instructions.  */
+#undef  ARM_VARIANT
+#define ARM_VARIANT   & arm_ext_sb
+#undef  THUMB_VARIANT
+#define THUMB_VARIANT & arm_ext_sb
+ TUF("sb", 57ff070, f3bf8f70, 0, (), noargs, noargs),
+
  /* ARMv8-M instructions.  */
 #undef  ARM_VARIANT
 #define ARM_VARIANT NULL
@@ -22060,21 +22087,6 @@ valueT
 md_section_align (segT  segment ATTRIBUTE_UNUSED,
                  valueT size)
 {
-#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
-  if (OUTPUT_FLAVOR == bfd_target_aout_flavour)
-    {
-      /* For a.out, force the section size to be aligned.  If we don't do
-        this, BFD will align it for us, but it will not write out the
-        final bytes of the section.  This may be a bug in BFD, but it is
-        easier to fix it here since that is how the other a.out targets
-        work.  */
-      int align;
-
-      align = bfd_get_section_alignment (stdoutput, segment);
-      size = ((size + (1 << align) - 1) & (-((valueT) 1 << align)));
-    }
-#endif
-
   return size;
 }
 
@@ -24005,6 +24017,21 @@ md_apply_fix (fixS *   fixP,
       S_SET_THREAD_LOCAL (fixP->fx_addsy);
       break;
 
+      /* Same handling as above, but with the arm_fdpic guard.  */
+    case BFD_RELOC_ARM_TLS_GD32_FDPIC:
+    case BFD_RELOC_ARM_TLS_IE32_FDPIC:
+    case BFD_RELOC_ARM_TLS_LDM32_FDPIC:
+      if (arm_fdpic)
+       {
+         S_SET_THREAD_LOCAL (fixP->fx_addsy);
+       }
+      else
+       {
+         as_bad_where (fixP->fx_file, fixP->fx_line,
+                       _("Relocation supported only in FDPIC mode"));
+       }
+      break;
+
     case BFD_RELOC_ARM_GOT32:
     case BFD_RELOC_ARM_GOTOFF:
       break;
@@ -24021,6 +24048,22 @@ md_apply_fix (fixS *   fixP,
       if (fixP->fx_done || !seg->use_rela_p)
        md_number_to_chars (buf, fixP->fx_offset, 4);
       break;
+
+      /* Relocations for FDPIC.  */
+    case BFD_RELOC_ARM_GOTFUNCDESC:
+    case BFD_RELOC_ARM_GOTOFFFUNCDESC:
+    case BFD_RELOC_ARM_FUNCDESC:
+      if (arm_fdpic)
+       {
+         if (fixP->fx_done || !seg->use_rela_p)
+           md_number_to_chars (buf, 0, 4);
+       }
+      else
+       {
+         as_bad_where (fixP->fx_file, fixP->fx_line,
+                       _("Relocation supported only in FDPIC mode"));
+      }
+      break;
 #endif
 
     case BFD_RELOC_RVA:
@@ -24782,14 +24825,20 @@ tc_gen_reloc (asection *section, fixS *fixp)
     case BFD_RELOC_ARM_THUMB_ALU_ABS_G1_NC:
     case BFD_RELOC_ARM_THUMB_ALU_ABS_G2_NC:
     case BFD_RELOC_ARM_THUMB_ALU_ABS_G3_NC:
+    case BFD_RELOC_ARM_GOTFUNCDESC:
+    case BFD_RELOC_ARM_GOTOFFFUNCDESC:
+    case BFD_RELOC_ARM_FUNCDESC:
       code = fixp->fx_r_type;
       break;
 
     case BFD_RELOC_ARM_TLS_GOTDESC:
     case BFD_RELOC_ARM_TLS_GD32:
+    case BFD_RELOC_ARM_TLS_GD32_FDPIC:
     case BFD_RELOC_ARM_TLS_LE32:
     case BFD_RELOC_ARM_TLS_IE32:
+    case BFD_RELOC_ARM_TLS_IE32_FDPIC:
     case BFD_RELOC_ARM_TLS_LDM32:
+    case BFD_RELOC_ARM_TLS_LDM32_FDPIC:
       /* BFD will include the symbol's address in the addend.
         But we don't want that, so subtract it out again here.  */
       if (!S_IS_COMMON (fixp->fx_addsy))
@@ -25055,9 +25104,12 @@ arm_fix_adjustable (fixS * fixP)
       || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
       || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF
       || fixP->fx_r_type == BFD_RELOC_ARM_TLS_GD32
+      || fixP->fx_r_type == BFD_RELOC_ARM_TLS_GD32_FDPIC
       || fixP->fx_r_type == BFD_RELOC_ARM_TLS_LE32
       || fixP->fx_r_type == BFD_RELOC_ARM_TLS_IE32
+      || fixP->fx_r_type == BFD_RELOC_ARM_TLS_IE32_FDPIC
       || fixP->fx_r_type == BFD_RELOC_ARM_TLS_LDM32
+      || fixP->fx_r_type == BFD_RELOC_ARM_TLS_LDM32_FDPIC
       || fixP->fx_r_type == BFD_RELOC_ARM_TLS_LDO32
       || fixP->fx_r_type == BFD_RELOC_ARM_TLS_GOTDESC
       || fixP->fx_r_type == BFD_RELOC_ARM_TLS_CALL
@@ -25111,10 +25163,20 @@ elf32_arm_target_format (void)
          ? "elf32-bigarm-nacl"
          : "elf32-littlearm-nacl");
 #else
-  if (target_big_endian)
-    return "elf32-bigarm";
+  if (arm_fdpic)
+    {
+      if (target_big_endian)
+       return "elf32-bigarm-fdpic";
+      else
+       return "elf32-littlearm-fdpic";
+    }
   else
-    return "elf32-littlearm";
+    {
+      if (target_big_endian)
+       return "elf32-bigarm";
+      else
+       return "elf32-littlearm";
+    }
 #endif
 }
 
@@ -25407,7 +25469,7 @@ md_begin (void)
         from the processor.  */
       if (mcpu_fpu_opt)
        selected_fpu = *mcpu_fpu_opt;
-      else
+      else if (march_fpu_opt)
        selected_fpu = *march_fpu_opt;
 #else
       selected_fpu = fpu_default;
@@ -25634,6 +25696,7 @@ const char * md_shortopts = "m:k";
 #endif
 #endif
 #define OPTION_FIX_V4BX (OPTION_MD_BASE + 2)
+#define OPTION_FDPIC (OPTION_MD_BASE + 3)
 
 struct option md_longopts[] =
 {
@@ -25644,6 +25707,9 @@ struct option md_longopts[] =
   {"EL", no_argument, NULL, OPTION_EL},
 #endif
   {"fix-v4bx", no_argument, NULL, OPTION_FIX_V4BX},
+#ifdef OBJ_ELF
+  {"fdpic", no_argument, NULL, OPTION_FDPIC},
+#endif
   {NULL, no_argument, NULL, 0}
 };
 
@@ -26121,6 +26187,9 @@ static const struct arm_cpu_option_table arm_cpus[] =
   ARM_CPU_OPT ("cortex-a75",    "Cortex-A75",         ARM_ARCH_V8_2A,
               ARM_FEATURE_CORE_HIGH (ARM_EXT2_FP16_INST),
               FPU_ARCH_CRYPTO_NEON_VFP_ARMV8_DOTPROD),
+  ARM_CPU_OPT ("cortex-a76",    "Cortex-A76",         ARM_ARCH_V8_2A,
+              ARM_FEATURE_CORE_HIGH (ARM_EXT2_FP16_INST),
+              FPU_ARCH_CRYPTO_NEON_VFP_ARMV8_DOTPROD),
   ARM_CPU_OPT ("cortex-r4",      "Cortex-R4",         ARM_ARCH_V7R,
               ARM_ARCH_NONE,
               FPU_NONE),
@@ -26275,6 +26344,7 @@ static const struct arm_arch_option_table arm_archs[] =
   ARM_ARCH_OPT ("armv8.3-a",   ARM_ARCH_V8_3A,  FPU_ARCH_VFP),
   ARM_ARCH_OPT ("armv8-r",     ARM_ARCH_V8R,    FPU_ARCH_VFP),
   ARM_ARCH_OPT ("armv8.4-a",   ARM_ARCH_V8_4A,  FPU_ARCH_VFP),
+  ARM_ARCH_OPT ("armv8.5-a",   ARM_ARCH_V8_5A,  FPU_ARCH_VFP),
   ARM_ARCH_OPT ("xscale",      ARM_ARCH_XSCALE, FPU_ARCH_VFP),
   ARM_ARCH_OPT ("iwmmxt",      ARM_ARCH_IWMMXT, FPU_ARCH_VFP),
   ARM_ARCH_OPT ("iwmmxt2",     ARM_ARCH_IWMMXT2,FPU_ARCH_VFP),
@@ -26357,6 +26427,9 @@ static const struct arm_option_extension_value_table arm_extensions[] =
   ARM_EXT_OPT ("rdma",  FPU_ARCH_NEON_VFP_ARMV8_1,
                        ARM_FEATURE_COPROC (FPU_NEON_ARMV8 | FPU_NEON_EXT_RDMA),
                        ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8A)),
+  ARM_EXT_OPT ("sb",   ARM_FEATURE_CORE_HIGH (ARM_EXT2_SB),
+                       ARM_FEATURE_CORE_HIGH (ARM_EXT2_SB),
+                       ARM_ARCH_V8A),
   ARM_EXT_OPT2 ("sec", ARM_FEATURE_CORE_LOW (ARM_EXT_SEC),
                        ARM_FEATURE_CORE_LOW (ARM_EXT_SEC),
                        ARM_FEATURE_CORE_LOW (ARM_EXT_V6K),
@@ -26815,6 +26888,12 @@ md_parse_option (int c, const char * arg)
       fix_v4bx = TRUE;
       break;
 
+#ifdef OBJ_ELF
+    case OPTION_FDPIC:
+      arm_fdpic = TRUE;
+      break;
+#endif /* OBJ_ELF */
+
     case 'a':
       /* Listing option.  Just ignore these, we don't support additional
         ones.  */
@@ -26909,6 +26988,11 @@ md_show_usage (FILE * fp)
 
   fprintf (fp, _("\
   --fix-v4bx              Allow BX in ARMv4 code\n"));
+
+#ifdef OBJ_ELF
+  fprintf (fp, _("\
+  --fdpic                 generate an FDPIC object file\n"));
+#endif /* OBJ_ELF */
 }
 
 #ifdef OBJ_ELF
@@ -26926,30 +27010,30 @@ typedef struct
    stable when new architectures are added.  */
 static const cpu_arch_ver_table cpu_arch_ver[] =
 {
-    {0, ARM_ARCH_V1},
-    {0, ARM_ARCH_V2},
-    {0, ARM_ARCH_V2S},
-    {0, ARM_ARCH_V3},
-    {0, ARM_ARCH_V3M},
-    {1, ARM_ARCH_V4xM},
-    {1, ARM_ARCH_V4},
-    {2, ARM_ARCH_V4TxM},
-    {2, ARM_ARCH_V4T},
-    {3, ARM_ARCH_V5xM},
-    {3, ARM_ARCH_V5},
-    {3, ARM_ARCH_V5TxM},
-    {3, ARM_ARCH_V5T},
-    {4, ARM_ARCH_V5TExP},
-    {4, ARM_ARCH_V5TE},
-    {5, ARM_ARCH_V5TEJ},
-    {6, ARM_ARCH_V6},
-    {7, ARM_ARCH_V6Z},
-    {7, ARM_ARCH_V6KZ},
-    {9, ARM_ARCH_V6K},
-    {8, ARM_ARCH_V6T2},
-    {8, ARM_ARCH_V6KT2},
-    {8, ARM_ARCH_V6ZT2},
-    {8, ARM_ARCH_V6KZT2},
+    {TAG_CPU_ARCH_PRE_V4,   ARM_ARCH_V1},
+    {TAG_CPU_ARCH_PRE_V4,   ARM_ARCH_V2},
+    {TAG_CPU_ARCH_PRE_V4,   ARM_ARCH_V2S},
+    {TAG_CPU_ARCH_PRE_V4,   ARM_ARCH_V3},
+    {TAG_CPU_ARCH_PRE_V4,   ARM_ARCH_V3M},
+    {TAG_CPU_ARCH_V4,      ARM_ARCH_V4xM},
+    {TAG_CPU_ARCH_V4,      ARM_ARCH_V4},
+    {TAG_CPU_ARCH_V4T,     ARM_ARCH_V4TxM},
+    {TAG_CPU_ARCH_V4T,     ARM_ARCH_V4T},
+    {TAG_CPU_ARCH_V5T,     ARM_ARCH_V5xM},
+    {TAG_CPU_ARCH_V5T,     ARM_ARCH_V5},
+    {TAG_CPU_ARCH_V5T,     ARM_ARCH_V5TxM},
+    {TAG_CPU_ARCH_V5T,     ARM_ARCH_V5T},
+    {TAG_CPU_ARCH_V5TE,            ARM_ARCH_V5TExP},
+    {TAG_CPU_ARCH_V5TE,            ARM_ARCH_V5TE},
+    {TAG_CPU_ARCH_V5TEJ,    ARM_ARCH_V5TEJ},
+    {TAG_CPU_ARCH_V6,      ARM_ARCH_V6},
+    {TAG_CPU_ARCH_V6KZ,            ARM_ARCH_V6Z},
+    {TAG_CPU_ARCH_V6KZ,            ARM_ARCH_V6KZ},
+    {TAG_CPU_ARCH_V6K,     ARM_ARCH_V6K},
+    {TAG_CPU_ARCH_V6T2,            ARM_ARCH_V6T2},
+    {TAG_CPU_ARCH_V6T2,            ARM_ARCH_V6KT2},
+    {TAG_CPU_ARCH_V6T2,            ARM_ARCH_V6ZT2},
+    {TAG_CPU_ARCH_V6T2,            ARM_ARCH_V6KZT2},
 
     /* When assembling a file with only ARMv6-M or ARMv6S-M instruction, GNU as
        always selected build attributes to match those of ARMv6-M
@@ -26958,24 +27042,25 @@ static const cpu_arch_ver_table cpu_arch_ver[] =
        would be selected when fully respecting chronology of architectures.
        It is thus necessary to make a special case of ARMv6-M and ARMv6S-M and
        move them before ARMv7 architectures.  */
-    {11, ARM_ARCH_V6M},
-    {12, ARM_ARCH_V6SM},
-
-    {10, ARM_ARCH_V7},
-    {10, ARM_ARCH_V7A},
-    {10, ARM_ARCH_V7R},
-    {10, ARM_ARCH_V7M},
-    {10, ARM_ARCH_V7VE},
-    {13, ARM_ARCH_V7EM},
-    {14, ARM_ARCH_V8A},
-    {14, ARM_ARCH_V8_1A},
-    {14, ARM_ARCH_V8_2A},
-    {14, ARM_ARCH_V8_3A},
-    {16, ARM_ARCH_V8M_BASE},
-    {17, ARM_ARCH_V8M_MAIN},
-    {15, ARM_ARCH_V8R},
-    {14, ARM_ARCH_V8_4A},
-    {-1, ARM_ARCH_NONE}
+    {TAG_CPU_ARCH_V6_M,            ARM_ARCH_V6M},
+    {TAG_CPU_ARCH_V6S_M,    ARM_ARCH_V6SM},
+
+    {TAG_CPU_ARCH_V7,      ARM_ARCH_V7},
+    {TAG_CPU_ARCH_V7,      ARM_ARCH_V7A},
+    {TAG_CPU_ARCH_V7,      ARM_ARCH_V7R},
+    {TAG_CPU_ARCH_V7,      ARM_ARCH_V7M},
+    {TAG_CPU_ARCH_V7,      ARM_ARCH_V7VE},
+    {TAG_CPU_ARCH_V7E_M,    ARM_ARCH_V7EM},
+    {TAG_CPU_ARCH_V8,      ARM_ARCH_V8A},
+    {TAG_CPU_ARCH_V8,      ARM_ARCH_V8_1A},
+    {TAG_CPU_ARCH_V8,      ARM_ARCH_V8_2A},
+    {TAG_CPU_ARCH_V8,      ARM_ARCH_V8_3A},
+    {TAG_CPU_ARCH_V8M_BASE, ARM_ARCH_V8M_BASE},
+    {TAG_CPU_ARCH_V8M_MAIN, ARM_ARCH_V8M_MAIN},
+    {TAG_CPU_ARCH_V8R,     ARM_ARCH_V8R},
+    {TAG_CPU_ARCH_V8,      ARM_ARCH_V8_4A},
+    {TAG_CPU_ARCH_V8,      ARM_ARCH_V8_5A},
+    {-1,                   ARM_ARCH_NONE}
 };
 
 /* Set an attribute if it has not already been set by the user.  */
This page took 0.039981 seconds and 4 git commands to generate.