* dw2gencfi.c (cfi_pseudo_table): Add cfi_gnu_window_save.
authorJakub Jelinek <jakub@redhat.com>
Fri, 29 Aug 2003 20:20:18 +0000 (20:20 +0000)
committerJakub Jelinek <jakub@redhat.com>
Fri, 29 Aug 2003 20:20:18 +0000 (20:20 +0000)
(dot_cfi, output_cfi_insn): Handle DW_CFA_GNU_window_save.
(output_cie): Don't use DW_EH_PE_pcrel if neither DIFF_EXPR_OK
nor tc_cfi_emit_pcrel_expr are defined.
(output_fde): Use tc_cfi_emit_pcrel_expr if available and
DIFF_EXPR_OK is not defined.
* config/tc-sparc.h (TARGET_USE_CFIPOP): Define.
(tc_cfi_frame_initial_instructions, tc_regname_to_dw2regnum,
tc_cfi_emit_pcrel_expr): Define.
(sparc_cfi_frame_initial_instructions, sparc_regname_to_dw2regnum,
sparc_cfi_emit_pcrel_expr): New prototypes.
(sparc_cie_data_alignment): New decl.
(DWARF2_DEFAULT_RETURN_COLUMN, DWARF2_CIE_DATA_ALIGNMENT): Define.
* config/tc-sparc.c: Include dw2gencfi.h.
(sparc_cie_data_alignment): New variable.
(md_begin): Initialize it.
(sparc_cfi_frame_initial_instructions): New function.
(sparc_regname_to_dw2regnum): Likewise.
(sparc_cfi_emit_pcrel_expr): Likewise.
* doc/as.texinfo: Document .cfi_gnu_window_save.

* config/tc-sparc.c (s_common): Cast last argument to long and
change format string to shut up warning.
testsuite/
* gas/cfi/cfi-sparc-1.s: New test.
* gas/cfi/cfi-sparc-1.d: New test.
* gas/cfi/cfi-sparc64-1.s: New test.
* gas/cfi/cfi-sparc64-1.d: New test.
* gas/cfi/cfi.exp: Run them.

gas/ChangeLog
gas/config/tc-sparc.c
gas/config/tc-sparc.h
gas/doc/as.texinfo
gas/dw2gencfi.c
gas/testsuite/ChangeLog
gas/testsuite/gas/cfi/cfi-sparc-1.d [new file with mode: 0644]
gas/testsuite/gas/cfi/cfi-sparc-1.s [new file with mode: 0644]
gas/testsuite/gas/cfi/cfi-sparc64-1.d [new file with mode: 0644]
gas/testsuite/gas/cfi/cfi-sparc64-1.s [new file with mode: 0644]
gas/testsuite/gas/cfi/cfi.exp

index 78705d38a7b8bb92adb9739eeac23da4ae9d0828..a23bce27b1db101e15902a743d680f131d4bdadf 100644 (file)
@@ -1,3 +1,29 @@
+2003-08-29  Jakub Jelinek  <jakub@redhat.com>
+
+       * dw2gencfi.c (cfi_pseudo_table): Add cfi_gnu_window_save.
+       (dot_cfi, output_cfi_insn): Handle DW_CFA_GNU_window_save.
+       (output_cie): Don't use DW_EH_PE_pcrel if neither DIFF_EXPR_OK
+       nor tc_cfi_emit_pcrel_expr are defined.
+       (output_fde): Use tc_cfi_emit_pcrel_expr if available and
+       DIFF_EXPR_OK is not defined.
+       * config/tc-sparc.h (TARGET_USE_CFIPOP): Define.
+       (tc_cfi_frame_initial_instructions, tc_regname_to_dw2regnum,
+       tc_cfi_emit_pcrel_expr): Define.
+       (sparc_cfi_frame_initial_instructions, sparc_regname_to_dw2regnum,
+       sparc_cfi_emit_pcrel_expr): New prototypes.
+       (sparc_cie_data_alignment): New decl.
+       (DWARF2_DEFAULT_RETURN_COLUMN, DWARF2_CIE_DATA_ALIGNMENT): Define.
+       * config/tc-sparc.c: Include dw2gencfi.h.
+       (sparc_cie_data_alignment): New variable.
+       (md_begin): Initialize it.
+       (sparc_cfi_frame_initial_instructions): New function.
+       (sparc_regname_to_dw2regnum): Likewise.
+       (sparc_cfi_emit_pcrel_expr): Likewise.
+       * doc/as.texinfo: Document .cfi_gnu_window_save.
+
+       * config/tc-sparc.c (s_common): Cast last argument to long and
+       change format string to shut up warning.
+
 2003-08-25  Jason Eckhardt  <jle@rice.edu>
 
        * doc/c-i860.texi: Update text about relocatable address expansions.
index 2278411d61535e3011c95532334a1bcba1e599eb..f3ef720147e57944e696ae0e907ade99e5e5d21f 100644 (file)
@@ -26,6 +26,7 @@
 #include "subsegs.h"
 
 #include "opcode/sparc.h"
+#include "dw2gencfi.h"
 
 #ifdef OBJ_ELF
 #include "elf/sparc.h"
@@ -116,6 +117,9 @@ static int target_little_endian_data;
 /* Symbols for global registers on v9.  */
 static symbolS *globals[8];
 
+/* The dwarf2 data alignment, adjusted for 32 or 64 bit.  */
+int sparc_cie_data_alignment;
+
 /* V9 and 86x have big and little endian data, but instructions are always big
    endian.  The sparclet has bi-endian support but both data and insns have
    the same endianness.  Global `target_big_endian' is used for data.
@@ -798,6 +802,7 @@ md_begin ()
   if (! default_init_p)
     init_default_arch ();
 
+  sparc_cie_data_alignment = sparc_arch_size == 64 ? -8 : -4;
   op_hash = hash_new ();
 
   while (i < (unsigned int) sparc_num_opcodes)
@@ -3804,8 +3809,8 @@ s_common (ignore)
     {
       if (S_GET_VALUE (symbolP) != (valueT) size)
        {
-         as_warn (_("Length of .comm \"%s\" is already %ld. Not changed to %d."),
-                  S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size);
+         as_warn (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."),
+                  S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), (long) size);
        }
     }
   else
@@ -4482,4 +4487,63 @@ cons_fix_new_sparc (frag, where, nbytes, exp)
    }
 
   fix_new_exp (frag, where, (int) nbytes, exp, 0, r);
+  sparc_cons_special_reloc = NULL;
+}
+
+void
+sparc_cfi_frame_initial_instructions ()
+{
+  cfi_add_CFA_def_cfa (14, sparc_arch_size == 64 ? 0x7ff : 0);
+}
+
+int
+sparc_regname_to_dw2regnum (const char *regname)
+{
+  char *p, *q;
+
+  if (!regname[0])
+    return -1;
+
+  q = "goli";
+  p = strchr (q, regname[0]);
+  if (p)
+    {
+      if (regname[1] < '0' || regname[1] > '8' || regname[2])
+       return -1;
+      return (p - q) * 8 + regname[1] - '0';
+    }
+  if (regname[0] == 's' && regname[1] == 'p' && !regname[2])
+    return 14;
+  if (regname[0] == 'f' && regname[1] == 'p' && !regname[2])
+    return 30;
+  if (regname[0] == 'f' || regname[0] == 'r')
+    {
+      unsigned int regnum;
+
+      regnum = strtoul (regname + 1, &q, 10);
+      if (p == q || *q)
+        return -1;
+      if (regnum >= ((regname[0] == 'f'
+                     && SPARC_OPCODE_ARCH_V9_P (max_architecture))
+                    ? 64 : 32))
+       return -1;
+      if (regname[0] == 'f')
+       {
+          regnum += 32;
+          if (regnum >= 64 && (regnum & 1))
+           return -1;
+        }
+      return regnum;
+    }
+  return -1;
+}
+
+void
+sparc_cfi_emit_pcrel_expr (expressionS *exp, unsigned int nbytes)
+{
+  sparc_cons_special_reloc = "disp";
+  sparc_no_align_cons = 1;
+  emit_expr (exp, nbytes);
+  sparc_no_align_cons = 0;
+  sparc_cons_special_reloc = NULL;
 }
index 17b3b6fb983d893dfb9dbaed53fc9934dedcaae5..e99222bab589a001ea180c752da76fec691c5430 100644 (file)
@@ -174,6 +174,21 @@ extern void cons_fix_new_sparc
     }                                                                  \
   while (0)
 
-#define DWARF2_LINE_MIN_INSN_LENGTH 4
+#define TARGET_USE_CFIPOP 1
+
+#define tc_cfi_frame_initial_instructions sparc_cfi_frame_initial_instructions
+extern void sparc_cfi_frame_initial_instructions PARAMS ((void));
+
+#define tc_regname_to_dw2regnum sparc_regname_to_dw2regnum
+extern int sparc_regname_to_dw2regnum PARAMS ((const char *regname));
+
+#define tc_cfi_emit_pcrel_expr sparc_cfi_emit_pcrel_expr
+extern void sparc_cfi_emit_pcrel_expr PARAMS ((expressionS *, unsigned int));
+
+extern int sparc_cie_data_alignment;
+
+#define DWARF2_LINE_MIN_INSN_LENGTH     4
+#define DWARF2_DEFAULT_RETURN_COLUMN    15
+#define DWARF2_CIE_DATA_ALIGNMENT       sparc_cie_data_alignment
 
 /* end of tc-sparc.h */
index 8d3bfc55908a1d9f9d98c1995c8abe356a272324..90bf7cabaf9b2c8004caf5a79cb023e1bacb3cb2 100644 (file)
@@ -4050,6 +4050,9 @@ using the known displacement of the CFA register from the CFA.
 This is often easier to use, because the number will match the
 code it's annotating.
 
+@section @code{.cfi_gnu_window_save}
+SPARC register window has been saved.
+
 @section @code{.cfi_escape} @var{expression}[, @dots{}]
 Allows the user to add arbitrary bytes to the unwind info.  One
 might use this to add OS-specific CFI opcodes, or generic CFI
index c7c62a71682c3a6eb16a5acf28d920d5d528b429..c6f1a2e7bb8798e3ebfc388d59478e5fb47554a7 100644 (file)
@@ -374,6 +374,7 @@ const pseudo_typeS cfi_pseudo_table[] =
     { "cfi_same_value", dot_cfi, DW_CFA_same_value },
     { "cfi_remember_state", dot_cfi, DW_CFA_remember_state },
     { "cfi_restore_state", dot_cfi, DW_CFA_restore_state },
+    { "cfi_gnu_window_save", dot_cfi, DW_CFA_GNU_window_save },
     { "cfi_escape", dot_cfi_escape, 0 },
     { NULL, NULL, 0 }
   };
@@ -529,6 +530,10 @@ dot_cfi (int arg)
       cfi_add_CFA_restore_state ();
       break;
 
+    case DW_CFA_GNU_window_save:
+      cfi_add_CFA_insn (DW_CFA_GNU_window_save);
+      break;
+
     default:
       abort ();
     }
@@ -798,6 +803,10 @@ output_cfi_insn (struct cfi_insn_data *insn)
       out_one (insn->insn);
       break;
 
+    case DW_CFA_GNU_window_save:
+      out_one (DW_CFA_GNU_window_save);
+      break;
+
     case CFI_escape:
       {
        struct cfi_escape_data *e;
@@ -838,7 +847,11 @@ output_cie (struct cie_entry *cie)
   out_sleb128 (DWARF2_CIE_DATA_ALIGNMENT);     /* Data alignment */
   out_one (cie->return_column);                        /* Return column */
   out_uleb128 (1);                             /* Augmentation size */
+#if defined DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
   out_one (DW_EH_PE_pcrel | DW_EH_PE_sdata4);
+#else
+  out_one (DW_EH_PE_sdata4);
+#endif
 
   if (cie->first)
     for (i = cie->first; i != cie->last; i = i->next)
@@ -867,10 +880,22 @@ output_fde (struct fde_entry *fde, struct cie_entry *cie,
   exp.X_add_symbol = after_size_address;
   exp.X_op_symbol = cie->start_address;
   emit_expr (&exp, 4);                         /* CIE offset */
-  
+
+#ifdef DIFF_EXPR_OK  
   exp.X_add_symbol = fde->start_address;
   exp.X_op_symbol = symbol_temp_new_now ();
   emit_expr (&exp, 4);                         /* Code offset */
+#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, 4);            /* Code offset */
+#else
+  emit_expr (&exp, 4);                         /* Code offset */
+#endif
+  exp.X_op = O_subtract;
+#endif
 
   exp.X_add_symbol = fde->end_address;
   exp.X_op_symbol = fde->start_address;                /* Code length */
index e0689225444abca927605f976f82c80e6f8f9d13..28754a4787eafa6b57b931eea4dd1a01ddbbb5c4 100644 (file)
@@ -1,3 +1,11 @@
+2003-08-29  Jakub Jelinek  <jakub@redhat.com>
+
+       * gas/cfi/cfi-sparc-1.s: New test.
+       * gas/cfi/cfi-sparc-1.d: New test.
+       * gas/cfi/cfi-sparc64-1.s: New test.
+       * gas/cfi/cfi-sparc64-1.d: New test.
+       * gas/cfi/cfi.exp: Run them.
+
 2003-08-19  Nick Clifton  <nickc@redhat.com>
 
        * gas/arm/copro.s: Add tests of Addressing Mode 5 (Unindexed).
diff --git a/gas/testsuite/gas/cfi/cfi-sparc-1.d b/gas/testsuite/gas/cfi/cfi-sparc-1.d
new file mode 100644 (file)
index 0000000..ac927ac
--- /dev/null
@@ -0,0 +1,22 @@
+#readelf: -wf
+#name: CFI on SPARC 32-bit
+#as: -32
+
+The section .eh_frame contains:
+
+00000000 00000010 00000000 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 4
+  Data alignment factor: -4
+  Return address column: 15
+  Augmentation data:     1b
+
+  DW_CFA_def_cfa: r14 ofs 0
+
+00000014 00000014 00000018 FDE cie=00000000 pc=0000001c..00000040
+  DW_CFA_advance_loc: 4 to 00000020
+  DW_CFA_def_cfa_reg: r30
+  DW_CFA_GNU_window_save
+  DW_CFA_register: r15 in r31
+
diff --git a/gas/testsuite/gas/cfi/cfi-sparc-1.s b/gas/testsuite/gas/cfi/cfi-sparc-1.s
new file mode 100644 (file)
index 0000000..5e7812a
--- /dev/null
@@ -0,0 +1,23 @@
+#; $ as -o test.o -32 gas-cfi-test.s && gcc -m32 -nostdlib -o test test.o
+
+       .file   "a.c"
+       .text
+       .align  4
+       .globl foo
+       .type   foo, @function
+foo:
+       .cfi_startproc
+        save    %sp, -104, %sp
+       .cfi_def_cfa_register   %fp
+       .cfi_gnu_window_save
+       .cfi_register   %o7, %i7
+       add     %i0, 1, %o0
+       call    bar, 0
+       add     %i0, 2, %i0
+       call    bar, 0
+       mov     %i0, %o0
+       add     %o0, 3, %o0
+       ret
+       restore %g0, %o0, %o0
+       .cfi_endproc
+       .size   foo, .-foo
diff --git a/gas/testsuite/gas/cfi/cfi-sparc64-1.d b/gas/testsuite/gas/cfi/cfi-sparc64-1.d
new file mode 100644 (file)
index 0000000..ffe6239
--- /dev/null
@@ -0,0 +1,25 @@
+#readelf: -wf
+#name: CFI on SPARC 64-bit
+#as: -64
+
+The section .eh_frame contains:
+
+00000000 00000011 00000000 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 4
+  Data alignment factor: -8
+  Return address column: 15
+  Augmentation data:     1b
+
+  DW_CFA_def_cfa: r14 ofs 2047
+
+00000015 00000017 00000019 FDE cie=00000000 pc=0000001d..0000004d
+  DW_CFA_advance_loc: 4 to 00000021
+  DW_CFA_def_cfa_reg: r30
+  DW_CFA_GNU_window_save
+  DW_CFA_register: r15 in r31
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
diff --git a/gas/testsuite/gas/cfi/cfi-sparc64-1.s b/gas/testsuite/gas/cfi/cfi-sparc64-1.s
new file mode 100644 (file)
index 0000000..0ddf8e1
--- /dev/null
@@ -0,0 +1,26 @@
+#; $ as -o test.o -64 gas-cfi-test.s && gcc -m64 -nostdlib -o test test.o
+
+       .file   "a.c"
+       .text
+       .align  4
+       .globl foo
+       .type   foo, @function
+foo:
+       .cfi_startproc
+       save    %sp, -192, %sp
+       .cfi_def_cfa_register   %fp
+       .cfi_gnu_window_save
+       .cfi_register   %o7, %i7
+       add     %i0, 1, %o0
+       add     %i0, 2, %i0
+       call    bar, 0
+       sra     %o0, 0, %o0
+       sra     %i0, 0, %i0
+       call    bar, 0
+       mov     %i0, %o0
+       add     %o0, 3, %o0
+       sra     %o0, 0, %o0
+       ret
+       restore %g0, %o0, %o0
+       .cfi_endproc
+       .size   foo, .-foo
index d1b1ca876b1d188b9cc6a7c2c8d1dc0a8cd9562c..d09d6fd1d67dfbf9844e9c90a0335b925b962441 100644 (file)
@@ -39,6 +39,16 @@ if [istarget "x86_64-*"] then {
 } elseif { [istarget "m68*-*"] } then {
     run_dump_test "cfi-m68k"
 
+} elseif { [istarget sparc*-*-*] } then {
+    global NM
+    global NMFLAGS
+    global srcdir
+
+    catch "exec $srcdir/lib/run $NM $NMFLAGS --help" nm_help
+    run_dump_test "cfi-sparc-1"
+    if { [regexp "elf64\[_-\]sparc" $nm_help] } then {
+       run_dump_test "cfi-sparc64-1"
+    }
 } else {
     return
 }