+/* Find the next pc for a sigreturn or rt_sigreturn syscall. In
+ addition, set IS_THUMB depending on whether we will return to ARM
+ or Thumb code.
+ See arm-linux.h for stack layout details. */
+static CORE_ADDR
+arm_sigreturn_next_pc (struct regcache *regcache, int svc_number,
+ int *is_thumb)
+{
+ unsigned long sp;
+ unsigned long sp_data;
+ /* Offset of PC register. */
+ int pc_offset = 0;
+ CORE_ADDR next_pc = 0;
+ uint32_t cpsr;
+
+ gdb_assert (svc_number == __NR_sigreturn || svc_number == __NR_rt_sigreturn);
+
+ collect_register_by_name (regcache, "sp", &sp);
+ (*the_target->read_memory) (sp, (unsigned char *) &sp_data, 4);
+
+ pc_offset = arm_linux_sigreturn_next_pc_offset
+ (sp, sp_data, svc_number, __NR_sigreturn == svc_number ? 1 : 0);
+
+ (*the_target->read_memory) (sp + pc_offset, (unsigned char *) &next_pc, 4);
+
+ /* Set IS_THUMB according the CPSR saved on the stack. */
+ (*the_target->read_memory) (sp + pc_offset + 4, (unsigned char *) &cpsr, 4);
+ *is_thumb = ((cpsr & CPSR_T) != 0);
+
+ return next_pc;
+}
+
+/* When PC is at a syscall instruction, return the PC of the next
+ instruction to be executed. */
+static CORE_ADDR
+get_next_pcs_syscall_next_pc (struct arm_get_next_pcs *self)
+{
+ CORE_ADDR next_pc = 0;
+ CORE_ADDR pc = regcache_read_pc (self->regcache);
+ int is_thumb = arm_is_thumb_mode ();
+ ULONGEST svc_number = 0;
+ struct regcache *regcache = self->regcache;
+
+ if (is_thumb)
+ {
+ collect_register (regcache, 7, &svc_number);
+ next_pc = pc + 2;
+ }
+ else
+ {
+ unsigned long this_instr;
+ unsigned long svc_operand;
+
+ target_read_memory (pc, (unsigned char *) &this_instr, 4);
+ svc_operand = (0x00ffffff & this_instr);
+
+ if (svc_operand) /* OABI. */
+ {
+ svc_number = svc_operand - 0x900000;
+ }
+ else /* EABI. */
+ {
+ collect_register (regcache, 7, &svc_number);
+ }
+
+ next_pc = pc + 4;
+ }
+
+ /* This is a sigreturn or sigreturn_rt syscall. */
+ if (svc_number == __NR_sigreturn || svc_number == __NR_rt_sigreturn)
+ {
+ /* SIGRETURN or RT_SIGRETURN may affect the arm thumb mode, so
+ update IS_THUMB. */
+ next_pc = arm_sigreturn_next_pc (regcache, svc_number, &is_thumb);
+ }
+
+ /* Addresses for calling Thumb functions have the bit 0 set. */
+ if (is_thumb)
+ next_pc = MAKE_THUMB_ADDR (next_pc);
+
+ return next_pc;
+}