aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/gen-sframe.c35
-rw-r--r--gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-1.d22
-rw-r--r--gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-1.s (renamed from gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-2.s)0
-rw-r--r--gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-1.d4
-rw-r--r--gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-2.d15
-rw-r--r--gas/testsuite/gas/cfi-sframe/cfi-sframe.exp2
-rw-r--r--libsframe/sframe-dump.c22
7 files changed, 80 insertions, 20 deletions
diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c
index dd97d4f..0bb7afb 100644
--- a/gas/gen-sframe.c
+++ b/gas/gen-sframe.c
@@ -1152,6 +1152,37 @@ sframe_xlate_do_val_offset (struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED,
return SFRAME_XLATE_OK;
}
+/* S390-specific translate DW_CFA_register into SFrame context.
+ Return SFRAME_XLATE_OK if success. */
+
+static int
+s390_sframe_xlate_do_register (struct sframe_xlate_ctx *xlate_ctx,
+ struct cfi_insn_data *cfi_insn)
+{
+ /* The scratchpad FRE currently being updated with each cfi_insn
+ being interpreted. This FRE eventually gets linked in into the
+ list of FREs for the specific function. */
+ struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
+
+ gas_assert (cur_fre);
+
+ /* Change the rule for the register indicated by the register number to
+ be the specified register. Encode the register number as offset by
+ shifting it to the left by one and setting the least-significant bit
+ (LSB). The LSB can be used to differentiate offsets from register
+ numbers, as offsets from CFA are always a multiple of -8 on s390x. */
+ if (cfi_insn->u.rr.reg1 == SFRAME_CFA_FP_REG)
+ sframe_fre_set_bp_track (cur_fre, cfi_insn->u.rr.reg2 << 1 | 1);
+#ifdef SFRAME_FRE_RA_TRACKING
+ else if (sframe_ra_tracking_p ()
+ && cfi_insn->u.rr.reg1 == SFRAME_CFA_RA_REG)
+ sframe_fre_set_ra_track (cur_fre, cfi_insn->u.rr.reg2 << 1 | 1);
+#endif
+
+ /* Safe to skip. */
+ return SFRAME_XLATE_OK;
+}
+
/* Translate DW_CFA_register into SFrame context.
Return SFRAME_XLATE_OK if success. */
@@ -1159,6 +1190,10 @@ static int
sframe_xlate_do_register (struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_UNUSED,
struct cfi_insn_data *cfi_insn)
{
+ /* Conditionally invoke S390-specific implementation. */
+ if (sframe_get_abi_arch () == SFRAME_ABI_S390_ENDIAN_BIG)
+ return s390_sframe_xlate_do_register (xlate_ctx, cfi_insn);
+
/* Previous value of register1 is register2. However, if the specified
register1 is not interesting (FP or RA reg), the current DW_CFA_register
instruction can be safely skipped without sacrificing the asynchronicity of
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-1.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-1.d
new file mode 100644
index 0000000..7368698
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-1.d
@@ -0,0 +1,22 @@
+#objdump: --sframe=.sframe
+#name: SFrame generation on s390 - FP and RA registers saved in FPR registers
+#...
+Contents of the SFrame section .sframe:
+
+ Header :
+
+ Version: SFRAME_VERSION_2
+ Flags: NONE
+ Num FDEs: 1
+ Num FREs: 5
+
+ Function Index :
+
+ func idx \[0\]: pc = 0x0, size = 26 bytes
+ STARTPC +CFA +FP +RA +
+ 0+0000 +sp\+160 +u +u +
+ 0+0004 +sp\+160 +u +r16 +
+ 0+0008 +sp\+160 +r17 +r16 +
+ 0+0014 +sp\+160 +u +r16 +
+ 0+0018 +sp\+160 +u +u +
+#pass
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-2.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-1.s
index 1d44971..1d44971 100644
--- a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-2.s
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-1.s
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-1.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-1.d
index 2b9456b..49d4e4a 100644
--- a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-1.d
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-1.d
@@ -1,6 +1,6 @@
-#name: SFrame generation on s390 - FP and RA saved in register
+#name: SFrame generation on s390 - FP without RA saved in register
#as: --gsframe
-#warning: skipping SFrame FDE due to .cfi_register specifying FP register
+#warning: skipping SFrame FDE due to FP without RA on stack
#objdump: --sframe=.sframe
#...
Contents of the SFrame section .sframe:
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-2.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-2.d
deleted file mode 100644
index 4c15bd0..0000000
--- a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-2.d
+++ /dev/null
@@ -1,15 +0,0 @@
-#name: SFrame generation on s390 - FP and RA saved in register
-#as: --gsframe
-#warning: skipping SFrame FDE due to .cfi_register specifying RA register
-#objdump: --sframe=.sframe
-#...
-Contents of the SFrame section .sframe:
-
- Header :
-
- Version: SFRAME_VERSION_2
- Flags: NONE
- Num FDEs: 0
- Num FREs: 0
-
-#pass
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
index 67735d4..77281a1 100644
--- a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
@@ -110,6 +110,6 @@ if { [istarget "s390x*-*-*"] && [gas_sframe_check] } then {
run_dump_test "cfi-sframe-s390-err-3"
run_dump_test "cfi-sframe-s390-fpra-offset-1"
run_dump_test "cfi-sframe-s390-fpra-offset-err-1"
+ run_dump_test "cfi-sframe-s390-fpra-register-1"
run_dump_test "cfi-sframe-s390-fpra-register-err-1"
- run_dump_test "cfi-sframe-s390-fpra-register-err-2"
}
diff --git a/libsframe/sframe-dump.c b/libsframe/sframe-dump.c
index 69633d5..40ea531 100644
--- a/libsframe/sframe-dump.c
+++ b/libsframe/sframe-dump.c
@@ -40,6 +40,14 @@ is_sframe_abi_arch_aarch64 (sframe_decoder_ctx *sfd_ctx)
return aarch64_p;
}
+/* Return TRUE if the SFrame section is associated with the s390 ABIs. */
+
+static bool
+is_sframe_abi_arch_s390 (sframe_decoder_ctx *sfd_ctx)
+{
+ return sframe_decoder_get_abi_arch (sfd_ctx) == SFRAME_ABI_S390_ENDIAN_BIG;
+}
+
static void
dump_sframe_header (sframe_decoder_ctx *sfd_ctx)
{
@@ -175,7 +183,12 @@ dump_sframe_func_with_fres (sframe_decoder_ctx *sfd_ctx,
/* Dump SP/FP info. */
if (err[1] == 0)
- sprintf (temp, "c%+d", fp_offset);
+ {
+ if (is_sframe_abi_arch_s390 (sfd_ctx) && (fp_offset & 1))
+ sprintf (temp, "r%d", fp_offset >> 1);
+ else
+ sprintf (temp, "c%+d", fp_offset);
+ }
else
strcpy (temp, "u");
printf ("%-10s", temp);
@@ -187,7 +200,12 @@ dump_sframe_func_with_fres (sframe_decoder_ctx *sfd_ctx,
!= SFRAME_CFA_FIXED_RA_INVALID)
strcpy (temp, "f");
else if (err[2] == 0)
- sprintf (temp, "c%+d", ra_offset);
+ {
+ if (is_sframe_abi_arch_s390 (sfd_ctx) && (ra_offset & 1))
+ sprintf (temp, "r%d", ra_offset >> 1);
+ else
+ sprintf (temp, "c%+d", ra_offset);
+ }
else
strcpy (temp, "u");