gas: blackfin: gas: blackfin: reject invalid BYTEOP16P insns
[binutils-gdb.git] / gas / dw2gencfi.c
index 5d35712bb60e2ef4e163d1477700d03a5d5ce4ac..7a051e35c3b31e76254205475b6305e8c8235445 100644 (file)
@@ -1,5 +1,5 @@
 /* dw2gencfi.c - Support for generating Dwarf2 CFI information.
-   Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
    Contributed by Michal Ludvig <mludvig@suse.cz>
 
 # endif
 #endif
 
+#ifndef CFI_DIFF_LSDA_OK
+# define CFI_DIFF_LSDA_OK CFI_DIFF_EXPR_OK
+#endif
+
+#if CFI_DIFF_EXPR_OK == 1 && CFI_DIFF_LSDA_OK == 0
+# error "CFI_DIFF_EXPR_OK should imply CFI_DIFF_LSDA_OK"
+#endif
+
 /* We re-use DWARF2_LINE_MIN_INSN_LENGTH for the code alignment field
    of the CIE.  Default to 1 if not otherwise specified.  */
 #ifndef  DWARF2_LINE_MIN_INSN_LENGTH
 # define DWARF2_ADDR_SIZE(bfd) (bfd_arch_bits_per_address (bfd) / 8)
 #endif
 
+/* ??? Share this with dwarf2cfg.c.  */
+#ifndef TC_DWARF2_EMIT_OFFSET
+#define TC_DWARF2_EMIT_OFFSET  generic_dwarf2_emit_offset
+
+/* Create an offset to .dwarf2_*.  */
+
+static void
+generic_dwarf2_emit_offset (symbolS *symbol, unsigned int size)
+{
+  expressionS exp;
+
+  exp.X_op = O_symbol;
+  exp.X_add_symbol = symbol;
+  exp.X_add_number = 0;
+  emit_expr (&exp, size);
+}
+#endif
+
 struct cfi_escape_data {
   struct cfi_escape_data *next;
   expressionS exp;
@@ -758,7 +784,7 @@ dot_cfi_lsda (int ignored ATTRIBUTE_UNUSED)
 
   if ((encoding & 0xff) != encoding
       || ((encoding & 0x70) != 0
-#if CFI_DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
+#if CFI_DIFF_LSDA_OK || defined tc_cfi_emit_pcrel_expr
          && (encoding & 0x70) != DW_EH_PE_pcrel
 #endif
          )
@@ -1295,9 +1321,9 @@ output_cie (struct cie_entry *cie, bfd_boolean eh_frame, int align)
       if (cie->lsda_encoding != DW_EH_PE_omit)
        out_one ('L');
       out_one ('R');
-      if (cie->signal_frame)
-       out_one ('S');
     }
+  if (cie->signal_frame)
+    out_one ('S');
   out_one (0);
   out_uleb128 (DWARF2_LINE_MIN_INSN_LENGTH);   /* Code alignment.  */
   out_sleb128 (DWARF2_CIE_DATA_ALIGNMENT);     /* Data alignment.  */
@@ -1311,29 +1337,31 @@ output_cie (struct cie_entry *cie, bfd_boolean eh_frame, int align)
       if (cie->per_encoding != DW_EH_PE_omit)
        augmentation_size += 1 + encoding_size (cie->per_encoding);
       out_uleb128 (augmentation_size);         /* Augmentation size.  */
-    }
-  if (cie->per_encoding != DW_EH_PE_omit)
-    {
-      offsetT size = encoding_size (cie->per_encoding);
-      out_one (cie->per_encoding);
-      exp = cie->personality;
-      if ((cie->per_encoding & 0x70) == DW_EH_PE_pcrel)
+
+      if (cie->per_encoding != DW_EH_PE_omit)
        {
+         offsetT size = encoding_size (cie->per_encoding);
+         out_one (cie->per_encoding);
+         exp = cie->personality;
+         if ((cie->per_encoding & 0x70) == DW_EH_PE_pcrel)
+           {
 #if CFI_DIFF_EXPR_OK
-         exp.X_op = O_subtract;
-         exp.X_op_symbol = symbol_temp_new_now ();
-         emit_expr (&exp, size);
+             exp.X_op = O_subtract;
+             exp.X_op_symbol = symbol_temp_new_now ();
+             emit_expr (&exp, size);
 #elif defined (tc_cfi_emit_pcrel_expr)
-         tc_cfi_emit_pcrel_expr (&exp, size);
+             tc_cfi_emit_pcrel_expr (&exp, size);
 #else
-         abort ();
+             abort ();
 #endif
+           }
+         else
+           emit_expr (&exp, size);
        }
-      else
-       emit_expr (&exp, size);
+
+      if (cie->lsda_encoding != DW_EH_PE_omit)
+       out_one (cie->lsda_encoding);
     }
-  if (cie->lsda_encoding != DW_EH_PE_omit)
-    out_one (cie->lsda_encoding);
 
   switch (DWARF2_FDE_RELOC_SIZE)
     {
@@ -1395,19 +1423,21 @@ output_fde (struct fde_entry *fde, struct cie_entry *cie,
 
   if (eh_frame)
     {
+      exp.X_op = O_subtract;
       exp.X_add_symbol = after_size_address;
       exp.X_op_symbol = cie->start_address;
+      exp.X_add_number = 0;
+      emit_expr (&exp, offset_size);           /* CIE offset.  */
     }
   else
     {
-      exp.X_op = O_symbol;
-      exp.X_add_symbol = cie->start_address;
-      exp.X_op_symbol = NULL;
+      TC_DWARF2_EMIT_OFFSET (cie->start_address, offset_size);
     }
-  emit_expr (&exp, offset_size);               /* CIE offset.  */
 
   if (eh_frame)
     {
+      exp.X_op = O_subtract;
+      exp.X_add_number = 0;
 #if CFI_DIFF_EXPR_OK
       exp.X_add_symbol = fde->start_address;
       exp.X_op_symbol = symbol_temp_new_now ();
@@ -1415,7 +1445,6 @@ output_fde (struct fde_entry *fde, struct cie_entry *cie,
 #else
       exp.X_op = O_symbol;
       exp.X_add_symbol = fde->start_address;
-      exp.X_op_symbol = NULL;
 #ifdef tc_cfi_emit_pcrel_expr
       tc_cfi_emit_pcrel_expr (&exp, DWARF2_FDE_RELOC_SIZE);     /* Code offset.  */
 #else
@@ -1426,7 +1455,9 @@ output_fde (struct fde_entry *fde, struct cie_entry *cie,
     }
   else
     {
+      exp.X_op = O_symbol;
       exp.X_add_symbol = fde->start_address;
+      exp.X_add_number = 0;
       addr_size = DWARF2_ADDR_SIZE (stdoutput);
       emit_expr (&exp, addr_size);
     }
@@ -1434,6 +1465,7 @@ output_fde (struct fde_entry *fde, struct cie_entry *cie,
   exp.X_op = O_subtract;
   exp.X_add_symbol = fde->end_address;
   exp.X_op_symbol = fde->start_address;                /* Code length.  */
+  exp.X_add_number = 0;
   emit_expr (&exp, addr_size);
 
   augmentation_size = encoding_size (fde->lsda_encoding);
@@ -1445,7 +1477,7 @@ output_fde (struct fde_entry *fde, struct cie_entry *cie,
       exp = fde->lsda;
       if ((fde->lsda_encoding & 0x70) == DW_EH_PE_pcrel)
        {
-#if CFI_DIFF_EXPR_OK
+#if CFI_DIFF_LSDA_OK
          exp.X_op = O_subtract;
          exp.X_op_symbol = symbol_temp_new_now ();
          emit_expr (&exp, augmentation_size);
@@ -1708,7 +1740,6 @@ cfi_finish (void)
       for (fde = all_fde_data; fde ; fde = fde->next)
        {
          struct cfi_insn_data *first;
-         struct cie_entry *cie;
 
          if (fde->end_address == NULL)
            {
@@ -1726,6 +1757,43 @@ cfi_finish (void)
 }
 
 #else /* TARGET_USE_CFIPOP */
+
+/* Emit an intelligible error message for missing support.  */
+
+static void
+dot_cfi_dummy (int ignored ATTRIBUTE_UNUSED)
+{
+  as_bad (_("CFI is not supported for this target"));
+  ignore_rest_of_line ();
+}
+
+const pseudo_typeS cfi_pseudo_table[] =
+  {
+    { "cfi_sections", dot_cfi_dummy, 0 },
+    { "cfi_startproc", dot_cfi_dummy, 0 },
+    { "cfi_endproc", dot_cfi_dummy, 0 },
+    { "cfi_def_cfa", dot_cfi_dummy, 0 },
+    { "cfi_def_cfa_register", dot_cfi_dummy, 0 },
+    { "cfi_def_cfa_offset", dot_cfi_dummy, 0 },
+    { "cfi_adjust_cfa_offset", dot_cfi_dummy, 0 },
+    { "cfi_offset", dot_cfi_dummy, 0 },
+    { "cfi_rel_offset", dot_cfi_dummy, 0 },
+    { "cfi_register", dot_cfi_dummy, 0 },
+    { "cfi_return_column", dot_cfi_dummy, 0 },
+    { "cfi_restore", dot_cfi_dummy, 0 },
+    { "cfi_undefined", dot_cfi_dummy, 0 },
+    { "cfi_same_value", dot_cfi_dummy, 0 },
+    { "cfi_remember_state", dot_cfi_dummy, 0 },
+    { "cfi_restore_state", dot_cfi_dummy, 0 },
+    { "cfi_window_save", dot_cfi_dummy, 0 },
+    { "cfi_escape", dot_cfi_dummy, 0 },
+    { "cfi_signal_frame", dot_cfi_dummy, 0 },
+    { "cfi_personality", dot_cfi_dummy, 0 },
+    { "cfi_lsda", dot_cfi_dummy, 0 },
+    { "cfi_val_encoded_addr", dot_cfi_dummy, 0 },
+    { NULL, NULL, 0 }
+  };
+
 void
 cfi_finish (void)
 {