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_fp_track (cur_fre,
- SFRAME_V2_S390X_OFFSET_ENCODE_REGNUM (cfi_insn->u.rr.reg2));
+ SFRAME_V3_S390X_OFFSET_ENCODE_REGNUM (cfi_insn->u.rr.reg2));
else if (sframe_ra_tracking_p ()
&& cfi_insn->u.rr.reg1 == SFRAME_CFA_RA_REG)
sframe_fre_set_ra_track (cur_fre,
- SFRAME_V2_S390X_OFFSET_ENCODE_REGNUM (cfi_insn->u.rr.reg2));
+ SFRAME_V3_S390X_OFFSET_ENCODE_REGNUM (cfi_insn->u.rr.reg2));
return SFRAME_XLATE_OK;
}
#define SFRAME_V2_S390X_OFFSET_DECODE_REGNUM(offset) \
((offset) >> 1)
+/* In SFrame V3, change the encoding of register numbers in the SFrame offsets
+ on s390x by keeping the lower 3 bits aside.
+ - LSB=0: Stack offset. The s390x ELF ABI mandates that stack register
+ slots must be 8-byte aligned.
+ - LSB=1: DWARF register number shifted to the left by three.
+ Bits 1 and 2 are currently unused. */
+#define SFRAME_V3_S390X_OFFSET_IS_REGNUM(offset) \
+ ((offset) & 1)
+#define SFRAME_V3_S390X_OFFSET_ENCODE_REGNUM(regnum) \
+ (((regnum) << 3) | 1)
+#define SFRAME_V3_S390X_OFFSET_DECODE_REGNUM(offset) \
+ ((offset) >> 3)
+
#ifdef __cplusplus
}
#endif
return sframe_decoder_get_abi_arch (sfd_ctx) == SFRAME_ABI_S390X_ENDIAN_BIG;
}
+static bool
+sframe_s390x_offset_regnum_p (int32_t offset, uint8_t ver)
+{
+ if (ver == SFRAME_VERSION_2)
+ return SFRAME_V2_S390X_OFFSET_IS_REGNUM (offset);
+ else if (ver == SFRAME_VERSION_3)
+ return SFRAME_V3_S390X_OFFSET_IS_REGNUM (offset);
+ else
+ /* No other version is supported yet. */
+ sframe_assert (false);
+}
+
+static int
+sframe_s390x_offset_decode_regnum (int32_t offset, uint8_t ver)
+{
+ if (ver == SFRAME_VERSION_2)
+ return SFRAME_V2_S390X_OFFSET_DECODE_REGNUM (offset);
+ else if (ver == SFRAME_VERSION_3)
+ return SFRAME_V3_S390X_OFFSET_DECODE_REGNUM (offset);
+ else
+ /* No other version is supported yet. */
+ sframe_assert (false);
+}
+
static void
dump_sframe_header_flags (const sframe_decoder_ctx *sfd_ctx)
{
if (err[1] == 0)
{
if (is_sframe_abi_arch_s390x (sfd_ctx)
- && SFRAME_V2_S390X_OFFSET_IS_REGNUM (fp_offset))
- sprintf (temp, "r%d", SFRAME_V2_S390X_OFFSET_DECODE_REGNUM (fp_offset));
+ && sframe_s390x_offset_regnum_p (fp_offset, ver))
+ sprintf (temp, "r%d",
+ sframe_s390x_offset_decode_regnum (fp_offset, ver));
else
sprintf (temp, "c%+d", fp_offset);
}
{
if (is_sframe_abi_arch_s390x (sfd_ctx)
&& SFRAME_V2_S390X_OFFSET_IS_REGNUM (ra_offset))
- sprintf (temp, "r%d", SFRAME_V2_S390X_OFFSET_DECODE_REGNUM (ra_offset));
+ sprintf (temp, "r%d",
+ sframe_s390x_offset_decode_regnum (ra_offset, ver));
else
sprintf (temp, "c%+d", ra_offset);
}