diff options
-rw-r--r-- | gas/gen-sframe.c | 35 | ||||
-rw-r--r-- | gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-1.d | 22 | ||||
-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.d | 4 | ||||
-rw-r--r-- | gas/testsuite/gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-2.d | 15 | ||||
-rw-r--r-- | gas/testsuite/gas/cfi-sframe/cfi-sframe.exp | 2 | ||||
-rw-r--r-- | libsframe/sframe-dump.c | 22 |
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"); |