return default_register_reggroup_p (gdbarch, regnum, group);
}
+/* The "ax_pseudo_register_collect" gdbarch method. */
+
+static int
+s390_ax_pseudo_register_collect (struct gdbarch *gdbarch,
+ struct agent_expr *ax, int regnum)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ if (regnum == tdep->pc_regnum)
+ {
+ ax_reg_mask (ax, S390_PSWA_REGNUM);
+ }
+ else if (regnum == tdep->cc_regnum)
+ {
+ ax_reg_mask (ax, S390_PSWM_REGNUM);
+ }
+ else if (regnum_is_gpr_full (tdep, regnum))
+ {
+ regnum -= tdep->gpr_full_regnum;
+ ax_reg_mask (ax, S390_R0_REGNUM + regnum);
+ ax_reg_mask (ax, S390_R0_UPPER_REGNUM + regnum);
+ }
+ else if (regnum_is_vxr_full (tdep, regnum))
+ {
+ regnum -= tdep->v0_full_regnum;
+ ax_reg_mask (ax, S390_F0_REGNUM + regnum);
+ ax_reg_mask (ax, S390_V0_LOWER_REGNUM + regnum);
+ }
+ else
+ {
+ internal_error (__FILE__, __LINE__, _("invalid regnum"));
+ }
+ return 0;
+}
+
+/* The "ax_pseudo_register_push_stack" gdbarch method. */
+
+static int
+s390_ax_pseudo_register_push_stack (struct gdbarch *gdbarch,
+ struct agent_expr *ax, int regnum)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ if (regnum == tdep->pc_regnum)
+ {
+ ax_reg (ax, S390_PSWA_REGNUM);
+ if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
+ {
+ ax_zero_ext (ax, 31);
+ }
+ }
+ else if (regnum == tdep->cc_regnum)
+ {
+ ax_reg (ax, S390_PSWM_REGNUM);
+ if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
+ ax_const_l (ax, 12);
+ else
+ ax_const_l (ax, 44);
+ ax_simple (ax, aop_rsh_unsigned);
+ ax_zero_ext (ax, 2);
+ }
+ else if (regnum_is_gpr_full (tdep, regnum))
+ {
+ regnum -= tdep->gpr_full_regnum;
+ ax_reg (ax, S390_R0_REGNUM + regnum);
+ ax_reg (ax, S390_R0_UPPER_REGNUM + regnum);
+ ax_const_l (ax, 32);
+ ax_simple (ax, aop_lsh);
+ ax_simple (ax, aop_bit_or);
+ }
+ else if (regnum_is_vxr_full (tdep, regnum))
+ {
+ /* Too large to stuff on the stack. */
+ return 1;
+ }
+ else
+ {
+ internal_error (__FILE__, __LINE__, _("invalid regnum"));
+ }
+ return 0;
+}
+
+/* The "gen_return_address" gdbarch method. Since this is supposed to be
+ just a best-effort method, and we don't really have the means to run
+ the full unwinder here, just collect the link register. */
+
+static void
+s390_gen_return_address (struct gdbarch *gdbarch,
+ struct agent_expr *ax, struct axs_value *value,
+ CORE_ADDR scope)
+{
+ value->type = register_type (gdbarch, S390_R14_REGNUM);
+ value->kind = axs_lvalue_register;
+ value->u.reg = S390_R14_REGNUM;
+}
+
/* A helper for s390_software_single_step, decides if an instruction
is a partial-execution instruction that needs to be executed until
break;
}
+ /* BRC/BRCL -- branch relative on condition. Ignore "branch
+ never", branch to following instruction, and "conditional
+ trap" (BRC +2). Otherwise terminate search. */
+ else if (is_ri (insn, op1_brc, op2_brc, &r1, &i2))
+ {
+ if (r1 != 0 && i2 != 1 && i2 != 2)
+ break;
+ }
+ else if (is_ril (insn, op1_brcl, op2_brcl, &r1, &i2))
+ {
+ if (r1 != 0 && i2 != 3)
+ break;
+ }
+
/* Terminate search when hitting any other branch instruction. */
else if (is_rr (insn, op_basr, &r1, &r2)
|| is_rx (insn, op_bas, &r1, &d2, &x2, &b2)
|| is_rr (insn, op_bcr, &r1, &r2)
|| is_rx (insn, op_bc, &r1, &d2, &x2, &b2)
- || is_ri (insn, op1_brc, op2_brc, &r1, &i2)
- || is_ril (insn, op1_brcl, op2_brcl, &r1, &i2)
|| is_ril (insn, op1_brasl, op2_brasl, &r2, &i2))
break;
set_tdesc_pseudo_register_type (gdbarch, s390_pseudo_register_type);
set_tdesc_pseudo_register_reggroup_p (gdbarch,
s390_pseudo_register_reggroup_p);
+ set_gdbarch_ax_pseudo_register_collect (gdbarch,
+ s390_ax_pseudo_register_collect);
+ set_gdbarch_ax_pseudo_register_push_stack
+ (gdbarch, s390_ax_pseudo_register_push_stack);
+ set_gdbarch_gen_return_address (gdbarch, s390_gen_return_address);
tdesc_use_registers (gdbarch, tdesc, tdesc_data);
set_gdbarch_register_name (gdbarch, s390_register_name);