diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c index 70affc914c2..36a70d8642c 100644 --- a/gdb/s390-tdep.c +++ b/gdb/s390-tdep.c @@ -855,6 +855,11 @@ s390_analyze_prologue (struct gdbarch *gdbarch, || is_rre (insn64, op_lgr, &r1, &r2)) data->gpr[r1] = data->gpr[r2]; + /* LDGR r1, r2 --- load from register to floating-point register + (64-bit version). */ + else if (is_rre (insn64, op_ldgr, &r1, &r2)) + data->fpr[r1] = data->gpr[r2]; + /* L r1, d2(x2, b2) --- load. */ /* LY r1, d2(x2, b2) --- load (long-displacement version). */ /* LG r1, d2(x2, b2) --- load (64-bit version). */ @@ -2542,6 +2547,40 @@ s390_prologue_frame_unwind_cache (const frame_info_ptr &this_frame, && data.fpr_slot[i] != 0) info->saved_regs[S390_F0_REGNUM + i].set_addr (cfa - data.fpr_slot[i]); + /* Handle this type of prologue: + ldgr %f2,%r11 + ldgr %f0,%r15 + where call-clobbered floating point registers are used as register save + slots. */ + for (i = 0; i < S390_NUM_FPRS; i++) + { + int fpr = S390_F0_REGNUM + i; + + /* Check that fpr is a call-clobbered register. */ + if (s390_register_call_saved (gdbarch, fpr)) + continue; + + /* Check that fpr contains the value of a register at function + entry. */ + if (data.fpr[i].kind != pvk_register) + continue; + + int entry_val_reg = data.fpr[i].reg; + + /* Check that entry_val_reg is a call-saved register. */ + if (!s390_register_call_saved (gdbarch, entry_val_reg)) + continue; + + /* In the prologue, we've copied: + - the value of a call-saved register (entry_val_reg) at function + entry, to + - a call-clobbered floating point register (fpr). + + Heuristic: assume that makes the floating point register a register + save slot, leaving the value constant throughout the function. */ + info->saved_regs[entry_val_reg].set_realreg (fpr); + } + /* Function return will set PC to %r14. */ info->saved_regs[S390_PSWA_REGNUM] = info->saved_regs[S390_RETADDR_REGNUM]; diff --git a/gdb/s390-tdep.h b/gdb/s390-tdep.h index bfcb8f17c56..d8f5fd5e185 100644 --- a/gdb/s390-tdep.h +++ b/gdb/s390-tdep.h @@ -82,6 +82,7 @@ enum op1_lgfi = 0xc0, op2_lgfi = 0x01, op_lr = 0x18, op_lgr = 0xb904, + op_ldgr = 0xb3c1, op_l = 0x58, op1_ly = 0xe3, op2_ly = 0x58, op1_lg = 0xe3, op2_lg = 0x04,