bool
s390_support_flex_fde_p (void)
{
- return false;
+ return true;
}
/* Specify the fixed offset to recover RA from CFA.
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,
- const 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_fp_track (cur_fre,
- SFRAME_V2_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 does not track SP explicitly. */
- else if (cfi_insn->u.rr.reg1 == SFRAME_CFA_SP_REG)
- {
- as_warn (_("no SFrame FDE emitted; %s register %u in .cfi_register"),
- sframe_register_name (cfi_insn->u.rr.reg1), cfi_insn->u.rr.reg1);
- return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */
- }
-
- return SFRAME_XLATE_OK;
-}
-
/* Translate DW_CFA_register into SFrame context.
This opcode indicates: Previous value of register1 is register2. This is
sframe_xlate_do_register (struct sframe_xlate_ctx *xlate_ctx,
const struct cfi_insn_data *cfi_insn)
{
- /* Conditionally invoke S390-specific implementation. */
- if (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG)
- return s390_sframe_xlate_do_register (xlate_ctx, cfi_insn);
- else if (sframe_support_flex_fde_p ())
+ if (sframe_support_flex_fde_p ())
{
struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
+++ /dev/null
-#name: SFrame generation on s390x - .cfi_def_cfa_register with non-SP/FP register
-#as: --gsframe
-#warning: non-SP/FP register 10 in \.cfi_def_cfa_register
-#objdump: --sframe=.sframe
-#...
-Contents of the SFrame section .sframe:
-
- Header :
-
- Version: SFRAME_VERSION_3
- Flags: SFRAME_F_FDE_FUNC_START_PCREL
- Num FDEs: 0
- Num FREs: 0
-
-#pass
+++ /dev/null
-#name: SFrame generation on s390x - .cfi_def_cfa with non-SP/FP register
-#as: --gsframe
-#warning: non-SP/FP register 10 in \.cfi_def_cfa
-#objdump: --sframe=.sframe
-#...
-Contents of the SFrame section .sframe:
-
- Header :
-
- Version: SFRAME_VERSION_3
- Flags: SFRAME_F_FDE_FUNC_START_PCREL
- Num FDEs: 0
- Num FREs: 0
-
-#pass
-#name: SFrame generation on s390x - RA and then FP saved in registers
+#name: SFrame generation on s390x - RA and then FP saved in FPR registers
#objdump: --sframe=.sframe
#...
Contents of the SFrame section .sframe:
Function Index :
- func idx \[0\]: pc = 0x0, size = 26 bytes
+ func idx \[0\]: pc = 0x0, size = 26 bytes, attr = "F"
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+0004 +sp\+160 +u +r16\+0 +
+ 0+0008 +sp\+160 +r17\+0 +r16\+0 +
+ 0+0014 +sp\+160 +u +r16\+0 +
0+0018 +sp\+160 +u +u +
#pass
Function Index :
- func idx \[0\]: pc = 0x0, size = 26 bytes
+ func idx \[0\]: pc = 0x0, size = 26 bytes, attr = "F"
STARTPC +CFA +FP +RA +
0+0000 +sp\+160 +u +u +
- 0+0004 +sp\+160 +r17 +U +
- 0+0008 +sp\+160 +r17 +r16 +
- 0+0014 +sp\+160 +r17 +U +
+ 0+0004 +sp\+160 +r17\+0 +U +
+ 0+0008 +sp\+160 +r17\+0 +r16\+0 +
+ 0+0014 +sp\+160 +r17\+0 +U +
0+0018 +sp\+160 +u +u +
#pass
--- /dev/null
+#name: SFrame generation on s390x - .cfi_def_cfa_register with non-SP/FP register
+#as: --gsframe
+#objdump: --sframe=.sframe
+#...
+Contents of the SFrame section .sframe:
+
+ Header :
+
+ Version: SFRAME_VERSION_3
+ Flags: SFRAME_F_FDE_FUNC_START_PCREL
+ Num FDEs: 1
+ Num FREs: 6
+
+ Function Index :
+
+ func idx \[0\]: pc = 0x0, size = 40 bytes, attr = "F"
+ STARTPC +CFA +FP +RA +
+ 0+0000 +sp\+160 +u +u +
+ 0+0006 +sp\+160 +c\-72 +c\-48 +
+ 0+000c +sp\+320 +c\-72 +c\-48 +
+ 0+0010 +r10\+320 +c\-72 +c\-48 +
+ 0+001c +sp\+160 +u +u +
+ 0+001e +r10\+320 +c\-72 +c\-48 +
+#pass
--- /dev/null
+#name: SFrame generation on s390x - .cfi_def_cfa with non-SP/FP register
+#as: --gsframe
+#objdump: --sframe=.sframe
+#...
+Contents of the SFrame section .sframe:
+
+ Header :
+
+ Version: SFRAME_VERSION_3
+ Flags: SFRAME_F_FDE_FUNC_START_PCREL
+ Num FDEs: 1
+ Num FREs: 6
+
+ Function Index :
+
+ func idx \[0\]: pc = 0x0, size = 40 bytes, attr = "F"
+ STARTPC +CFA +FP +RA +
+ 0+0000 +sp\+160 +u +u +
+ 0+0006 +sp\+160 +c\-72 +c\-48 +
+ 0+000c +sp\+320 +c\-72 +c\-48 +
+ 0+0010 +r10\+320 +c\-72 +c\-48 +
+ 0+001c +sp\+160 +u +u +
+ 0+001e +r10\+320 +c\-72 +c\-48 +
+#pass
run_dump_test "cfi-sframe-s390x-1"
run_dump_test "cfi-sframe-s390x-2"
run_dump_test "cfi-sframe-s390x-3"
- run_dump_test "cfi-sframe-s390x-err-1"
- run_dump_test "cfi-sframe-s390x-err-2"
run_dump_test "cfi-sframe-s390x-err-3"
run_dump_test "cfi-sframe-s390x-err-4"
run_dump_test "cfi-sframe-s390x-fpra-offset-1"
run_dump_test "cfi-sframe-s390x-fpra-register-2"
run_dump_test "cfi-sframe-s390x-ra-undefined-1"
run_dump_test "cfi-sframe-s390x-pr33756"
+ run_dump_test "cfi-sframe-s390x-non-spfp-cfa-1"
+ run_dump_test "cfi-sframe-s390x-non-spfp-cfa-2"
}
offset2 (intrepreted as FP = CFA + offset2)
fi
fi
- Note that in s390x, if a FP/RA offset2/offset3 value has the least-
- significant bit set it represents a DWARF register number shifted to the
- left by 1 to restore the FP/RA value from.
+ Note that in s390x, if a FP/RA is to be restored from a register, flex FDEs
+ are used in SFrame V3. In SFrame V2, default FDEs were used: the
+ least-significant bit of the offset was set to indicate that the encoded
+ value is a DWARF register number shifted to the left by 1.
*/
/* Used when SFRAME_FRE_TYPE_ADDR1 is specified as FRE type. */
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 false;
+ 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
+ /* 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);
}
else if (err[2] == 0)
{
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));
+ && sframe_s390x_offset_regnum_p (ra_offset, ver))
+ sprintf (temp, "r%d",
+ sframe_s390x_offset_decode_regnum (ra_offset, ver));
else
sprintf (temp, "c%+d", ra_offset);
}