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. */
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
--- /dev/null
+#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
-#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:
+++ /dev/null
-#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
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"
}
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)
{
/* 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);
!= 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");