aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
Diffstat (limited to 'gas')
-rw-r--r--gas/doc/as.texinfo3
-rw-r--r--gas/dw2gencfi.c42
-rw-r--r--gas/dw2gencfi.h1
-rw-r--r--gas/testsuite/gas/cfi/cfi-common-8.d23
-rw-r--r--gas/testsuite/gas/cfi/cfi-common-8.s6
-rw-r--r--gas/testsuite/gas/cfi/cfi.exp1
6 files changed, 76 insertions, 0 deletions
diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo
index cdaeb6b..82cc72d 100644
--- a/gas/doc/as.texinfo
+++ b/gas/doc/as.texinfo
@@ -4831,6 +4831,9 @@ value that is added/substracted from the previous offset.
Previous value of @var{register} is saved at offset @var{offset} from
CFA.
+@subsection @code{.cfi_val_offset @var{register}, @var{offset}}
+Previous value of @var{register} is CFA + @var{offset}.
+
@subsection @code{.cfi_rel_offset @var{register}, @var{offset}}
Previous value of @var{register} is saved at offset @var{offset} from
the current CFA register. This is transformed to @code{.cfi_offset}
diff --git a/gas/dw2gencfi.c b/gas/dw2gencfi.c
index fb3e302..4fbdf42 100644
--- a/gas/dw2gencfi.c
+++ b/gas/dw2gencfi.c
@@ -600,6 +600,22 @@ cfi_add_CFA_offset (unsigned regno, offsetT offset)
as_bad (_("register save offset not a multiple of %u"), abs_data_align);
}
+/* Add a DW_CFA_val_offset record to the CFI data. */
+
+void
+cfi_add_CFA_val_offset (unsigned regno, offsetT offset)
+{
+ unsigned int abs_data_align;
+
+ gas_assert (DWARF2_CIE_DATA_ALIGNMENT != 0);
+ cfi_add_CFA_insn_reg_offset (DW_CFA_val_offset, regno, offset);
+
+ abs_data_align = (DWARF2_CIE_DATA_ALIGNMENT < 0
+ ? -DWARF2_CIE_DATA_ALIGNMENT : DWARF2_CIE_DATA_ALIGNMENT);
+ if (offset % abs_data_align)
+ as_bad (_("register save offset not a multiple of %u"), abs_data_align);
+}
+
/* Add a DW_CFA_def_cfa record to the CFI data. */
void
@@ -727,6 +743,7 @@ const pseudo_typeS cfi_pseudo_table[] =
{ "cfi_val_encoded_addr", dot_cfi_val_encoded_addr, 0 },
{ "cfi_inline_lsda", dot_cfi_inline_lsda, 0 },
{ "cfi_label", dot_cfi_label, 0 },
+ { "cfi_val_offset", dot_cfi, DW_CFA_val_offset },
{ NULL, NULL, 0 }
};
@@ -827,6 +844,13 @@ dot_cfi (int arg)
cfi_add_CFA_offset (reg1, offset);
break;
+ case DW_CFA_val_offset:
+ reg1 = cfi_parse_reg ();
+ cfi_parse_separator ();
+ offset = cfi_parse_const ();
+ cfi_add_CFA_val_offset (reg1, offset);
+ break;
+
case CFI_rel_offset:
reg1 = cfi_parse_reg ();
cfi_parse_separator ();
@@ -1680,6 +1704,23 @@ output_cfi_insn (struct cfi_insn_data *insn)
}
break;
+ case DW_CFA_val_offset:
+ regno = insn->u.ri.reg;
+ offset = insn->u.ri.offset / DWARF2_CIE_DATA_ALIGNMENT;
+ if (offset < 0)
+ {
+ out_one (DW_CFA_val_offset_sf);
+ out_uleb128 (regno);
+ out_sleb128 (offset);
+ }
+ else
+ {
+ out_one (DW_CFA_val_offset);
+ out_uleb128 (regno);
+ out_uleb128 (offset);
+ }
+ break;
+
case DW_CFA_register:
out_one (DW_CFA_register);
out_uleb128 (insn->u.rr.reg1);
@@ -2516,6 +2557,7 @@ const pseudo_typeS cfi_pseudo_table[] =
{ "cfi_val_encoded_addr", dot_cfi_dummy, 0 },
{ "cfi_label", dot_cfi_dummy, 0 },
{ "cfi_inline_lsda", dot_cfi_dummy, 0 },
+ { "cfi_val_offset", dot_cfi_dummy, 0 },
{ NULL, NULL, 0 }
};
diff --git a/gas/dw2gencfi.h b/gas/dw2gencfi.h
index 9ef1020..cbc4233 100644
--- a/gas/dw2gencfi.h
+++ b/gas/dw2gencfi.h
@@ -41,6 +41,7 @@ extern void cfi_add_advance_loc (struct symbol *);
extern void cfi_add_label (const char *);
extern void cfi_add_CFA_offset (unsigned, offsetT);
+extern void cfi_add_CFA_val_offset (unsigned, offsetT);
extern void cfi_add_CFA_def_cfa (unsigned, offsetT);
extern void cfi_add_CFA_register (unsigned, unsigned);
extern void cfi_add_CFA_def_cfa_register (unsigned);
diff --git a/gas/testsuite/gas/cfi/cfi-common-8.d b/gas/testsuite/gas/cfi/cfi-common-8.d
new file mode 100644
index 0000000..6155690
--- /dev/null
+++ b/gas/testsuite/gas/cfi/cfi-common-8.d
@@ -0,0 +1,23 @@
+#objdump: -Wf
+#name: CFI common 8
+#...
+Contents of the .eh_frame section:
+
+00000000 0+0010 0+0000 CIE
+ Version: 1
+ Augmentation: "zR"
+ Code alignment factor: .*
+ Data alignment factor: .*
+ Return address column: .*
+ Augmentation data: [01]b
+
+ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+
+00000014 0+00(18|1c|20) 0+0018 FDE cie=0+0000 pc=.*
+ DW_CFA_advance_loc: 4 to .*
+ DW_CFA_def_cfa: r0( \([er]ax\)|) ofs 16
+ DW_CFA_val_offset(_sf|): r1( \((rdx|ecx)\)|) is cfa\+8
+ DW_CFA_val_offset(_sf|): r2( \((rcx|edx)\)|) is cfa-32
+#...
diff --git a/gas/testsuite/gas/cfi/cfi-common-8.s b/gas/testsuite/gas/cfi/cfi-common-8.s
new file mode 100644
index 0000000..8477ff0
--- /dev/null
+++ b/gas/testsuite/gas/cfi/cfi-common-8.s
@@ -0,0 +1,6 @@
+ .cfi_startproc simple
+ .long 0
+ .cfi_def_cfa 0, 16
+ .cfi_val_offset 1, 8
+ .cfi_val_offset 2, -32
+ .cfi_endproc
diff --git a/gas/testsuite/gas/cfi/cfi.exp b/gas/testsuite/gas/cfi/cfi.exp
index 9b6012e..3056856 100644
--- a/gas/testsuite/gas/cfi/cfi.exp
+++ b/gas/testsuite/gas/cfi/cfi.exp
@@ -135,4 +135,5 @@ if { ![istarget "hppa64*-*"] } then {
run_dump_test "cfi-common-6"
}
run_dump_test "cfi-common-7"
+ run_dump_test "cfi-common-8"
}