[patch/RFA] multiarch INSTRUCTION_NULLIFIED

Randolph Chung
2004-11-18T00:02:23Z

Currently only hppa uses this define, but possibly this will be useful
for other architectures which has conditionally nullified instructions
(ia64?) as well. This gets us one step closer to full multiarch
support..

Tested on hppa-linux with no regressions.

ok?
randolph

2004-11-17 Randolph Chung <tausq@debian.org>

* gdbarch.sh (instruction_nullified): New method.
* gdbarch.c: Regenerate.
* gdbarch.h: Regenerate.
* hppa-tdep.c (hppa_instruction_nullified): Remove prototype and make
static. Rewrite to work directly off the passed regcache.
(hppa_gdbarch_init): Set instruction_nullified method.
* infrun.c (INSTRUCTION_NULLIFIED): Delete.
(handle_inferior_event): Replace INSTRUCTION_NULLIFIED with calls to
new gdbarch method.
* config/pa/tm-hppa.h (INSTRUCTION_NULLIFIED): Delete definition.

Index: gdbarch.sh
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.sh,v
retrieving revision 1.350
diff -u -p -r1.350 gdbarch.sh
--- gdbarch.sh 31 Oct 2004 21:21:41 -0000 1.350
+++ gdbarch.sh 17 Nov 2004 23:37:57 -0000
@@ -614,6 +614,13 @@ F:=:void:software_single_step:enum targe
# Return non-zero if the processor is executing a delay slot and a
# further single-step is needed before the instruction finishes.
M::int:single_step_through_delay:struct frame_info *frame:frame
+# On some systems, the PC may be left pointing at an instruction that won't
+# actually be executed. This is usually indicated by a bit in the PSW. If
+# we find ourselves in such a state, then we step the target beyond the
+# nullified instruction before returning control to the user so as to avoid
+# confusion. Return non-zero if the processor is about to execute a
+# nullified instruction.
+M::int:instruction_nullified:struct regcache *regcache:regcache
# FIXME: cagney/2003-08-28: Need to find a better way of selecting the
# disassembler. Perhaps objdump can handle it?
f:TARGET_PRINT_INSN:int:print_insn:bfd_vma vma, struct disassemble_info *info:vma, info::0:
Index: gdbarch.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.c,v
retrieving revision 1.314
diff -u -p -r1.314 gdbarch.c
--- gdbarch.c 31 Oct 2004 21:21:41 -0000 1.314
+++ gdbarch.c 17 Nov 2004 23:37:57 -0000
@@ -212,6 +212,7 @@ struct gdbarch
gdbarch_smash_text_address_ftype *smash_text_address;
gdbarch_software_single_step_ftype *software_single_step;
gdbarch_single_step_through_delay_ftype *single_step_through_delay;
+ gdbarch_instruction_nullified_ftype *instruction_nullified;
gdbarch_print_insn_ftype *print_insn;
gdbarch_skip_trampoline_code_ftype *skip_trampoline_code;
gdbarch_skip_solib_resolver_ftype *skip_solib_resolver;
@@ -338,6 +339,7 @@ struct gdbarch startup_gdbarch =
0, /* smash_text_address */
0, /* software_single_step */
0, /* single_step_through_delay */
+ 0, /* instruction_nullified */
0, /* print_insn */
0, /* skip_trampoline_code */
generic_skip_solib_resolver, /* skip_solib_resolver */
@@ -591,6 +593,7 @@ verify_gdbarch (struct gdbarch *current_
/* Skip verify of smash_text_address, invalid_p == 0 */
/* Skip verify of software_single_step, has predicate */
/* Skip verify of single_step_through_delay, has predicate */
+ /* Skip verify of instruction_nullified, has predicate */
if (current_gdbarch->print_insn == 0)
fprintf_unfiltered (log, "\n\tprint_insn");
/* Skip verify of skip_trampoline_code, invalid_p == 0 */
@@ -1195,6 +1198,12 @@ gdbarch_dump (struct gdbarch *current_gd
fprintf_unfiltered (file,
"gdbarch_dump: inner_than = <0x%lx>\n",
(long) current_gdbarch->inner_than);
+ fprintf_unfiltered (file,
+ "gdbarch_dump: gdbarch_instruction_nullified_p() = %d\n",
+ gdbarch_instruction_nullified_p (current_gdbarch));
+ fprintf_unfiltered (file,
+ "gdbarch_dump: instruction_nullified = <0x%lx>\n",
+ (long) current_gdbarch->instruction_nullified);
#ifdef TARGET_INT_BIT
fprintf_unfiltered (file,
"gdbarch_dump: TARGET_INT_BIT # %s\n",
@@ -3366,6 +3375,30 @@ set_gdbarch_single_step_through_delay (s
}

int
+gdbarch_instruction_nullified_p (struct gdbarch *gdbarch)
+{
+ gdb_assert (gdbarch != NULL);
+ return gdbarch->instruction_nullified != NULL;
+}
+
+int
+gdbarch_instruction_nullified (struct gdbarch *gdbarch, struct regcache *regcache)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->instruction_nullified != NULL);
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_instruction_nullified called\n");
+ return gdbarch->instruction_nullified (gdbarch, regcache);
+}
+
+void
+set_gdbarch_instruction_nullified (struct gdbarch *gdbarch,
+ gdbarch_instruction_nullified_ftype instruction_nullified)
+{
+ gdbarch->instruction_nullified = instruction_nullified;
+}
+
+int
gdbarch_print_insn (struct gdbarch *gdbarch, bfd_vma vma, struct disassemble_info *info)
{
gdb_assert (gdbarch != NULL);
Index: gdbarch.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.h,v
retrieving revision 1.275
diff -u -p -r1.275 gdbarch.h
--- gdbarch.h 31 Oct 2004 21:21:41 -0000 1.275
+++ gdbarch.h 17 Nov 2004 23:37:57 -0000
@@ -1227,6 +1227,19 @@ typedef int (gdbarch_single_step_through
extern int gdbarch_single_step_through_delay (struct gdbarch *gdbarch, struct frame_info *frame);
extern void set_gdbarch_single_step_through_delay (struct gdbarch *gdbarch, gdbarch_single_step_through_delay_ftype *single_step_through_delay);

+/* On some systems, the PC may be left pointing at an instruction that won't
+ actually be executed. This is usually indicated by a bit in the PSW. If
+ we find ourselves in such a state, then we step the target beyond the
+ nullified instruction before returning control to the user so as to avoid
+ confusion. Return non-zero if the processor is about to execute a
+ nullified instruction. */
+
+extern int gdbarch_instruction_nullified_p (struct gdbarch *gdbarch);
+
+typedef int (gdbarch_instruction_nullified_ftype) (struct gdbarch *gdbarch, struct regcache *regcache);
+extern int gdbarch_instruction_nullified (struct gdbarch *gdbarch, struct regcache *regcache);
+extern void set_gdbarch_instruction_nullified (struct gdbarch *gdbarch, gdbarch_instruction_nullified_ftype *instruction_nullified);
+
/* FIXME: cagney/2003-08-28: Need to find a better way of selecting the
disassembler. Perhaps objdump can handle it? */

Index: hppa-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/hppa-tdep.c,v
retrieving revision 1.181
diff -u -p -r1.181 hppa-tdep.c
--- hppa-tdep.c 13 Nov 2004 02:15:32 -0000 1.181
+++ hppa-tdep.c 17 Nov 2004 23:37:57 -0000
@@ -71,7 +71,6 @@ const struct objfile_data *hppa_objfile_
/* FIXME: brobecker 2002-11-07: We will likely be able to make the
following functions static, once we hppa is partially multiarched. */
int hppa_pc_requires_run_before_use (CORE_ADDR pc);
-int hppa_instruction_nullified (void);

/* Handle 32/64-bit struct return conventions. */

@@ -2292,14 +2291,19 @@ hppa_pc_requires_run_before_use (CORE_AD
return (!target_has_stack && (pc & 0xFF000000));
}

-int
-hppa_instruction_nullified (void)
+static int
+hppa_instruction_nullified (struct gdbarch *gdbarch,
+ struct regcache *regcache)
{
- /* brobecker 2002/11/07: Couldn't we use a ULONGEST here? It would
- avoid the type cast. I'm leaving it as is for now as I'm doing
- semi-mechanical multiarching-related changes. */
- const int ipsw = (int) read_register (HPPA_IPSW_REGNUM);
- const int flags = (int) read_register (HPPA_FLAGS_REGNUM);
+ ULONGEST tmp, ipsw, flags;
+
+ regcache_cooked_read (regcache, HPPA_IPSW_REGNUM, &tmp);
+ ipsw = extract_unsigned_integer (&tmp, register_size (current_gdbarch,
+ HPPA_IPSW_REGNUM));
+
+ regcache_cooked_read (regcache, HPPA_FLAGS_REGNUM, &tmp);
+ flags = extract_unsigned_integer (&tmp, register_size (current_gdbarch,
+ HPPA_FLAGS_REGNUM));

return ((ipsw & 0x00200000) && !(flags & 0x2));
}
@@ -2570,6 +2574,7 @@ hppa_gdbarch_init (struct gdbarch_info i

set_gdbarch_breakpoint_from_pc (gdbarch, hppa_breakpoint_from_pc);
set_gdbarch_pseudo_register_read (gdbarch, hppa_pseudo_register_read);
+ set_gdbarch_instruction_nullified (gdbarch, hppa_instruction_nullified);

/* Frame unwind methods. */
set_gdbarch_unwind_dummy_id (gdbarch, hppa_unwind_dummy_id);
Index: infrun.c
===================================================================
RCS file: /cvs/src/src/gdb/infrun.c,v
retrieving revision 1.182
diff -u -p -r1.182 infrun.c
--- infrun.c 8 Nov 2004 17:25:23 -0000 1.182
+++ infrun.c 17 Nov 2004 23:37:57 -0000
@@ -163,15 +163,6 @@ static int debug_infrun = 0;
#define SOLIB_IN_DYNAMIC_LINKER(pid,pc) 0
#endif

-/* On some systems, the PC may be left pointing at an instruction that won't
- actually be executed. This is usually indicated by a bit in the PSW. If
- we find ourselves in such a state, then we step the target beyond the
- nullified instruction before returning control to the user so as to avoid
- confusion. */
-
-#ifndef INSTRUCTION_NULLIFIED
-#define INSTRUCTION_NULLIFIED 0
-#endif

/* We can't step off a permanent breakpoint in the ordinary way, because we
can't remove it. Instead, we have to advance the PC to the next
@@ -1744,11 +1735,11 @@ handle_inferior_event (struct execution_
it so that the user won't be confused when GDB appears to be ready
to execute it. */

- /* if (INSTRUCTION_NULLIFIED && currently_stepping (ecs)) */
- if (INSTRUCTION_NULLIFIED)
+ if (gdbarch_instruction_nullified_p (current_gdbarch)
+ && gdbarch_instruction_nullified (current_gdbarch, current_regcache))
{
if (debug_infrun)
- printf_unfiltered ("infrun: INSTRUCTION_NULLIFIED\n");
+ printf_unfiltered ("infrun: nullified instruction\n");
registers_changed ();
target_resume (ecs->ptid, 1, TARGET_SIGNAL_0);

Index: config/pa/tm-hppa.h
===================================================================
RCS file: /cvs/src/src/gdb/config/pa/tm-hppa.h,v
retrieving revision 1.77
diff -u -p -r1.77 tm-hppa.h
--- config/pa/tm-hppa.h 13 Nov 2004 02:27:04 -0000 1.77
+++ config/pa/tm-hppa.h 17 Nov 2004 23:37:57 -0000
@@ -28,9 +28,3 @@

extern int hppa_pc_requires_run_before_use (CORE_ADDR pc);
#define DEPRECATED_PC_REQUIRES_RUN_BEFORE_USE(pc) hppa_pc_requires_run_before_use (pc)
-
-/* PA specific macro to see if the current instruction is nullified. */
-#ifndef INSTRUCTION_NULLIFIED
-extern int hppa_instruction_nullified (void);
-#define INSTRUCTION_NULLIFIED hppa_instruction_nullified ()
-#endif
--
Randolph Chung
Debian GNU/Linux Developer, hppa/ia64 ports