* [rfa:i386] Add mmx registers
@ 2002-08-10 16:58 Andrew Cagney
2002-08-12 11:10 ` Mark Kettenis
0 siblings, 1 reply; 9+ messages in thread
From: Andrew Cagney @ 2002-08-10 16:58 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 419 bytes --]
Hello,
This adds mmx registers to the i386.
Several notes:
It depends on an earlier patch I submitted that eliminates
register_byte() and register_raw_size() from the i386.
It probably works better if the ``info vector'' command is added.
If someone has a bit of code for testing this, I'm most interested. I
think its correct :-)
Assuming I've got it right ..., yes, it is that easy :-)
comments? ok?
Andrew
[-- Attachment #2: diffs --]
[-- Type: text/plain, Size: 4078 bytes --]
2002-08-10 Andrew Cagney <cagney@redhat.com>
* i386-tdep.h (i386_register_byte, i386_register_raw_size): Delete
declarations.
* i386-tdep.c (i386_register_name): Handle mmx registers.
(is_mmx_regnum): New function.
(i386_mmx_names): New array.
(nr_mmx_regs): New variable.
(i386_pseudo_register_read): New function.
(i386_pseudo_register_write): New function.
(mmx_regnum_to_fp_regnum): New function. Code from Fernando Nasser.
diff --exclude *CVS* --exclude *#* --exclude *~* --exclude *%* --exclude *.orig --exclude *.rej --exclude *diffs --exclude new-* --exclude old-* --exclude *-new --exclude *-old -u /home/cagney/2002-08-09-p4-cleanup/src/gdb/i386-tdep.c ./i386-tdep.c
--- /home/cagney/2002-08-09-p4-cleanup/src/gdb/i386-tdep.c Fri Aug 9 20:44:31 2002
+++ ./i386-tdep.c Sat Aug 10 02:02:14 2002
@@ -56,6 +56,23 @@
"mxcsr"
};
+/* MMX registers. */
+
+static char *i386_mmx_names[] =
+{
+ "mm0", "mm1", "mm2", "mm3",
+ "mm4", "mm5", "mm6", "mm7"
+};
+static const int nr_mmx_regs = (sizeof (i386_mmx_names)
+ / sizeof (i386_mmx_names[0]));
+#define MM0_REGNUM (NUM_REGS)
+
+static int
+is_mmx_regnum (int reg)
+{
+ return (reg >= MM0_REGNUM && reg < MM0_REGNUM + nr_mmx_regs);
+}
+
/* Return the name of register REG. */
const char *
@@ -63,9 +80,10 @@
{
if (reg < 0)
return NULL;
+ if (is_mmx_regnum (reg))
+ return i386_mmx_names[reg - MM0_REGNUM];
if (reg >= sizeof (i386_register_names) / sizeof (*i386_register_names))
return NULL;
-
return i386_register_names[reg];
}
@@ -1079,9 +1097,60 @@
if (IS_SSE_REGNUM (regnum))
return builtin_type_vec128i;
+ if (is_mmx_regnum (regnum))
+ return builtin_type_vec64i;
+
return builtin_type_int;
}
+/* Map a cooked register onto a raw register or memory. For the i386,
+ the MMX registers need to be mapped onto floating point registers. */
+
+static int
+mmx_regnum_to_fp_regnum (struct regcache *regcache, int regnum)
+{
+ int mmxi = regnum - MM0_REGNUM;
+ int fstat = regcache_raw_read_as_address (regcache, FSTAT_REGNUM);
+ int tos = (fstat >> 11) & 0x7;
+ int fpi = (mmxi + tos) % 8;
+ return FP0_REGNUM + fpi;
+}
+
+static void
+i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+ int regnum, void *buf)
+{
+ if (is_mmx_regnum (regnum))
+ {
+ char *mmx_buf = alloca (MAX_REGISTER_RAW_SIZE);
+ int fpnum = mmx_regnum_to_fp_regnum (regcache, regnum);
+ regcache_raw_read (regcache, fpnum, mmx_buf);
+ /* Extract (always little endian). */
+ memcpy (buf, mmx_buf, REGISTER_RAW_SIZE (regnum));
+ }
+ else
+ regcache_raw_read (regcache, regnum, buf);
+}
+
+static void
+i386_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
+ int regnum, const void *buf)
+{
+ if (is_mmx_regnum (regnum))
+ {
+ char *mmx_buf = alloca (MAX_REGISTER_RAW_SIZE);
+ int fpnum = mmx_regnum_to_fp_regnum (regcache, regnum);
+ /* Read ... */
+ regcache_raw_read (regcache, fpnum, mmx_buf);
+ /* ... Modify ... (always little endian). */
+ memcpy (mmx_buf, buf, REGISTER_RAW_SIZE (regnum));
+ /* ... Write. */
+ regcache_raw_write (regcache, fpnum, mmx_buf);
+ }
+ else
+ regcache_raw_write (regcache, regnum, buf);
+}
+
/* Return true iff register REGNUM's virtual format is different from
its raw format. Note that this definition assumes that the host
supports IEEE 32-bit floats, since it doesn't say that SSE
@@ -1474,6 +1543,11 @@
set_gdbarch_saved_pc_after_call (gdbarch, i386_saved_pc_after_call);
set_gdbarch_frame_num_args (gdbarch, i386_frame_num_args);
set_gdbarch_pc_in_sigtramp (gdbarch, i386_pc_in_sigtramp);
+
+ /* Wire in the MMX registers. */
+ set_gdbarch_num_pseudo_regs (gdbarch, nr_mmx_regs);
+ set_gdbarch_pseudo_register_read (gdbarch, i386_pseudo_register_read);
+ set_gdbarch_pseudo_register_write (gdbarch, i386_pseudo_register_write);
/* Hook in ABI-specific overrides, if they have been registered. */
gdbarch_init_osabi (info, gdbarch, osabi);
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [rfa:i386] Add mmx registers 2002-08-10 16:58 [rfa:i386] Add mmx registers Andrew Cagney @ 2002-08-12 11:10 ` Mark Kettenis 2002-08-12 12:00 ` Andrew Cagney 0 siblings, 1 reply; 9+ messages in thread From: Mark Kettenis @ 2002-08-12 11:10 UTC (permalink / raw) To: Andrew Cagney; +Cc: gdb-patches Andrew Cagney <ac131313@ges.redhat.com> writes: > Hello, > > This adds mmx registers to the i386. Great, a few nits though :-( * Please rename is_mmx_regnum() to mmx_regnum_p(). * Please rename nr_mmx_regs to mmx_num_regs. * Why do you use regcache_raw_read_as_address() in mmx_regnum_to_fp_regnum? Looks misleading to me... Mark ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [rfa:i386] Add mmx registers 2002-08-12 11:10 ` Mark Kettenis @ 2002-08-12 12:00 ` Andrew Cagney 2002-08-13 7:35 ` Andrew Cagney 0 siblings, 1 reply; 9+ messages in thread From: Andrew Cagney @ 2002-08-12 12:00 UTC (permalink / raw) To: Mark Kettenis; +Cc: gdb-patches > Andrew Cagney <ac131313@ges.redhat.com> writes: > > >> Hello, >> >> This adds mmx registers to the i386. > > > Great, a few nits though :-( > > * Please rename is_mmx_regnum() to mmx_regnum_p(). > > * Please rename nr_mmx_regs to mmx_num_regs. > > * Why do you use regcache_raw_read_as_address() in > mmx_regnum_to_fp_regnum? Looks misleading to me... (because I happen to know what the function does :-) I'll rename the function to ..._as_longest(). I'll fix the others. thanks, Andrew ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [rfa:i386] Add mmx registers 2002-08-12 12:00 ` Andrew Cagney @ 2002-08-13 7:35 ` Andrew Cagney 2002-08-13 14:39 ` Mark Kettenis 0 siblings, 1 reply; 9+ messages in thread From: Andrew Cagney @ 2002-08-13 7:35 UTC (permalink / raw) To: Andrew Cagney; +Cc: Mark Kettenis, gdb-patches [-- Attachment #1: Type: text/plain, Size: 659 bytes --] > Andrew Cagney <ac131313@ges.redhat.com> writes: > > > Hello, > > This adds mmx registers to the i386. > > > Great, a few nits though :-( > > * Please rename is_mmx_regnum() to mmx_regnum_p(). > > * Please rename nr_mmx_regs to mmx_num_regs. > > * Why do you use regcache_raw_read_as_address() in > mmx_regnum_to_fp_regnum? Looks misleading to me... > > (because I happen to know what the function does :-) > I'll rename the function to ..._as_longest(). > > I'll fix the others. Done, this is what I committed. It also includes raw versions of the ..._unsigned() functions since the mmx code needs to access the raw register cache. Andrew [-- Attachment #2: diffs --] [-- Type: text/plain, Size: 6097 bytes --] 2002-08-13 Andrew Cagney <cagney@redhat.com> * i386-tdep.c (i386_register_name): Handle mmx registers. (mmx_regnum_p): New function. (i386_mmx_names): New array. (mmx_num_regs): New variable. (i386_pseudo_register_read): New function. (i386_pseudo_register_write): New function. (mmx_regnum_to_fp_regnum): New function. Code from Fernando Nasser. * regcache.c (regcache_raw_read_unsigned): New function. (regcache_raw_read_signed): New function. * regcache.h (regcache_raw_read_unsigned): Declare. (regcache_raw_read_signed): Declare. Index: i386-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/i386-tdep.c,v retrieving revision 1.75 diff -u -r1.75 i386-tdep.c --- i386-tdep.c 13 Aug 2002 13:58:50 -0000 1.75 +++ i386-tdep.c 13 Aug 2002 14:31:01 -0000 @@ -56,6 +56,23 @@ "mxcsr" }; +/* MMX registers. */ + +static char *i386_mmx_names[] = +{ + "mm0", "mm1", "mm2", "mm3", + "mm4", "mm5", "mm6", "mm7" +}; +static const int mmx_num_regs = (sizeof (i386_mmx_names) + / sizeof (i386_mmx_names[0])); +#define MM0_REGNUM (NUM_REGS) + +static int +mmx_regnum_p (int reg) +{ + return (reg >= MM0_REGNUM && reg < MM0_REGNUM + mmx_num_regs); +} + /* Return the name of register REG. */ const char * @@ -63,6 +80,8 @@ { if (reg < 0) return NULL; + if (mmx_regnum_p (reg)) + return i386_mmx_names[reg - MM0_REGNUM]; if (reg >= sizeof (i386_register_names) / sizeof (*i386_register_names)) return NULL; @@ -1090,9 +1109,64 @@ if (IS_SSE_REGNUM (regnum)) return builtin_type_vec128i; + if (mmx_regnum_p (regnum)) + return builtin_type_vec64i; + return builtin_type_int; } +/* Map a cooked register onto a raw register or memory. For the i386, + the MMX registers need to be mapped onto floating point registers. */ + +static int +mmx_regnum_to_fp_regnum (struct regcache *regcache, int regnum) +{ + int mmxi; + ULONGEST fstat; + int tos; + int fpi; + mmxi = regnum - MM0_REGNUM; + regcache_raw_read_unsigned (regcache, FSTAT_REGNUM, &fstat); + tos = (fstat >> 11) & 0x7; + fpi = (mmxi + tos) % 8; + return (FP0_REGNUM + fpi); +} + +static void +i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, + int regnum, void *buf) +{ + if (mmx_regnum_p (regnum)) + { + char *mmx_buf = alloca (MAX_REGISTER_RAW_SIZE); + int fpnum = mmx_regnum_to_fp_regnum (regcache, regnum); + regcache_raw_read (regcache, fpnum, mmx_buf); + /* Extract (always little endian). */ + memcpy (buf, mmx_buf, REGISTER_RAW_SIZE (regnum)); + } + else + regcache_raw_read (regcache, regnum, buf); +} + +static void +i386_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, + int regnum, const void *buf) +{ + if (mmx_regnum_p (regnum)) + { + char *mmx_buf = alloca (MAX_REGISTER_RAW_SIZE); + int fpnum = mmx_regnum_to_fp_regnum (regcache, regnum); + /* Read ... */ + regcache_raw_read (regcache, fpnum, mmx_buf); + /* ... Modify ... (always little endian). */ + memcpy (mmx_buf, buf, REGISTER_RAW_SIZE (regnum)); + /* ... Write. */ + regcache_raw_write (regcache, fpnum, mmx_buf); + } + else + regcache_raw_write (regcache, regnum, buf); +} + /* Return true iff register REGNUM's virtual format is different from its raw format. Note that this definition assumes that the host supports IEEE 32-bit floats, since it doesn't say that SSE @@ -1485,6 +1559,11 @@ set_gdbarch_saved_pc_after_call (gdbarch, i386_saved_pc_after_call); set_gdbarch_frame_num_args (gdbarch, i386_frame_num_args); set_gdbarch_pc_in_sigtramp (gdbarch, i386_pc_in_sigtramp); + + /* Wire in the MMX registers. */ + set_gdbarch_num_pseudo_regs (gdbarch, mmx_num_regs); + set_gdbarch_pseudo_register_read (gdbarch, i386_pseudo_register_read); + set_gdbarch_pseudo_register_write (gdbarch, i386_pseudo_register_write); /* Hook in ABI-specific overrides, if they have been registered. */ gdbarch_init_osabi (info, gdbarch, osabi); Index: regcache.c =================================================================== RCS file: /cvs/src/src/gdb/regcache.c,v retrieving revision 1.51 diff -u -r1.51 regcache.c --- regcache.c 13 Aug 2002 13:58:50 -0000 1.51 +++ regcache.c 13 Aug 2002 14:31:02 -0000 @@ -661,6 +661,31 @@ } void +regcache_raw_read_signed (struct regcache *regcache, int regnum, LONGEST *val) +{ + char *buf; + gdb_assert (regcache != NULL); + gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers); + buf = alloca (regcache->descr->sizeof_register[regnum]); + regcache_raw_read (regcache, regnum, buf); + (*val) = extract_signed_integer (buf, + regcache->descr->sizeof_register[regnum]); +} + +void +regcache_raw_read_unsigned (struct regcache *regcache, int regnum, + ULONGEST *val) +{ + char *buf; + gdb_assert (regcache != NULL); + gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers); + buf = alloca (regcache->descr->sizeof_register[regnum]); + regcache_raw_read (regcache, regnum, buf); + (*val) = extract_unsigned_integer (buf, + regcache->descr->sizeof_register[regnum]); +} + +void read_register_gen (int regnum, char *buf) { gdb_assert (current_regcache != NULL); Index: regcache.h =================================================================== RCS file: /cvs/src/src/gdb/regcache.h,v retrieving revision 1.13 diff -u -r1.13 regcache.h --- regcache.h 13 Aug 2002 13:58:50 -0000 1.13 +++ regcache.h 13 Aug 2002 14:31:02 -0000 @@ -38,6 +38,10 @@ void regcache_raw_read (struct regcache *regcache, int rawnum, void *buf); void regcache_raw_write (struct regcache *regcache, int rawnum, const void *buf); +extern void regcache_raw_read_signed (struct regcache *regcache, + int regnum, LONGEST *val); +extern void regcache_raw_read_unsigned (struct regcache *regcache, + int regnum, ULONGEST *val); int regcache_valid_p (struct regcache *regcache, int regnum); /* Transfer a cooked register [0..NUM_REGS+NUM_PSEUDO_REGS). */ ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [rfa:i386] Add mmx registers 2002-08-13 7:35 ` Andrew Cagney @ 2002-08-13 14:39 ` Mark Kettenis 2002-08-13 14:55 ` Andrew Cagney 0 siblings, 1 reply; 9+ messages in thread From: Mark Kettenis @ 2002-08-13 14:39 UTC (permalink / raw) To: ac131313; +Cc: gdb-patches Date: Tue, 13 Aug 2002 10:35:37 -0400 From: Andrew Cagney <ac131313@ges.redhat.com> > Hello, > > This adds mmx registers to the i386. > Done, this is what I committed. Ouch! This patch uncovers a problem in the new regcache code and segfaults on my FreeBSD 4.6-STABLE system. The problem is that: + set_gdbarch_pseudo_register_read (gdbarch, i386_pseudo_register_read); + set_gdbarch_pseudo_register_write (gdbarch, i386_pseudo_register_write); changes the i386 target's register cache from "legacy" to "new". This means that there isn't room for the pseudo registers in register_valid_p, yet registers_changed() tries to frob the entries for the pseudo registers. I don't see an obvious way to fix this. Any bright ideas Andrew? Mark ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [rfa:i386] Add mmx registers 2002-08-13 14:39 ` Mark Kettenis @ 2002-08-13 14:55 ` Andrew Cagney 2002-08-13 15:03 ` Andrew Cagney 2002-08-13 15:10 ` Mark Kettenis 0 siblings, 2 replies; 9+ messages in thread From: Andrew Cagney @ 2002-08-13 14:55 UTC (permalink / raw) To: Mark Kettenis; +Cc: gdb-patches > Date: Tue, 13 Aug 2002 10:35:37 -0400 > From: Andrew Cagney <ac131313@ges.redhat.com> > > > Hello, > > > > This adds mmx registers to the i386. > > > > Done, this is what I committed. > > Ouch! This patch uncovers a problem in the new regcache code and > segfaults on my FreeBSD 4.6-STABLE system. The problem is that: My Red Hat GNU/Linux tests didn't bat an eyelid :-( > + set_gdbarch_pseudo_register_read (gdbarch, i386_pseudo_register_read); > + set_gdbarch_pseudo_register_write (gdbarch, i386_pseudo_register_write); > > changes the i386 target's register cache from "legacy" to "new". This > means that there isn't room for the pseudo registers in > register_valid_p, yet registers_changed() tries to frob the entries > for the pseudo registers. > > I don't see an obvious way to fix this. Any bright ideas Andrew? Hmm, yes. It should be clearing: [0 .. current_regcache->descr->nr_raw_registers) Andrew ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [rfa:i386] Add mmx registers 2002-08-13 14:55 ` Andrew Cagney @ 2002-08-13 15:03 ` Andrew Cagney 2002-08-13 15:10 ` Mark Kettenis 1 sibling, 0 replies; 9+ messages in thread From: Andrew Cagney @ 2002-08-13 15:03 UTC (permalink / raw) To: Andrew Cagney; +Cc: Mark Kettenis, gdb-patches > Date: Tue, 13 Aug 2002 10:35:37 -0400 > From: Andrew Cagney <ac131313@ges.redhat.com> > > > Hello, > > > This adds mmx registers to the i386. > > > Done, this is what I committed. > > Ouch! This patch uncovers a problem in the new regcache code and > segfaults on my FreeBSD 4.6-STABLE system. The problem is that: > > My Red Hat GNU/Linux tests didn't bat an eyelid :-( > > + set_gdbarch_pseudo_register_read (gdbarch, i386_pseudo_register_read); > + set_gdbarch_pseudo_register_write (gdbarch, i386_pseudo_register_write); > > changes the i386 target's register cache from "legacy" to "new". This > means that there isn't room for the pseudo registers in > register_valid_p, yet registers_changed() tries to frob the entries > for the pseudo registers. > > I don't see an obvious way to fix this. Any bright ideas Andrew? > > Hmm, yes. It should be clearing: > [0 .. current_regcache->descr->nr_raw_registers) PS: The code should also still allocate nr_cooked_registers worth of register_valid_p. That way, erant code won't crash things. I'll fix both in a tick. Andrew ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [rfa:i386] Add mmx registers 2002-08-13 14:55 ` Andrew Cagney 2002-08-13 15:03 ` Andrew Cagney @ 2002-08-13 15:10 ` Mark Kettenis 2002-08-13 15:21 ` Andrew Cagney 1 sibling, 1 reply; 9+ messages in thread From: Mark Kettenis @ 2002-08-13 15:10 UTC (permalink / raw) To: ac131313; +Cc: gdb-patches Date: Tue, 13 Aug 2002 17:55:33 -0400 From: Andrew Cagney <ac131313@ges.redhat.com> > + set_gdbarch_pseudo_register_read (gdbarch, i386_pseudo_register_read); > + set_gdbarch_pseudo_register_write (gdbarch, i386_pseudo_register_write); > > changes the i386 target's register cache from "legacy" to "new". This > means that there isn't room for the pseudo registers in > register_valid_p, yet registers_changed() tries to frob the entries > for the pseudo registers. > > I don't see an obvious way to fix this. Any bright ideas Andrew? Hmm, yes. It should be clearing: [0 .. current_regcache->descr->nr_raw_registers) Clearing the pseudo registers isn't necessary on targets that still use the legacy stuff? Mark ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [rfa:i386] Add mmx registers 2002-08-13 15:10 ` Mark Kettenis @ 2002-08-13 15:21 ` Andrew Cagney 0 siblings, 0 replies; 9+ messages in thread From: Andrew Cagney @ 2002-08-13 15:21 UTC (permalink / raw) To: Mark Kettenis; +Cc: gdb-patches > Date: Tue, 13 Aug 2002 17:55:33 -0400 > From: Andrew Cagney <ac131313@ges.redhat.com> > > > + set_gdbarch_pseudo_register_read (gdbarch, i386_pseudo_register_read); > > + set_gdbarch_pseudo_register_write (gdbarch, i386_pseudo_register_write); > > > > changes the i386 target's register cache from "legacy" to "new". This > > means that there isn't room for the pseudo registers in > > register_valid_p, yet registers_changed() tries to frob the entries > > for the pseudo registers. > > > > I don't see an obvious way to fix this. Any bright ideas Andrew? > > Hmm, yes. It should be clearing: > [0 .. current_regcache->descr->nr_raw_registers) > > Clearing the pseudo registers isn't necessary on targets that still > use the legacy stuff? Shh! nr_raw_registers == number of raw registers in the register cache == NUM_REGS + NUM_PSEUDO_REGS on legacy targets. Just don't tell anyone M'kay ;-) /* FIXME: cagney/2002-05-11: Shouldn't be including pseudo-registers in the register buffer. Unfortunatly some architectures do. */ descr->nr_cooked_registers = NUM_REGS + NUM_PSEUDO_REGS; descr->nr_raw_registers = descr->nr_cooked_registers; descr->sizeof_raw_register_valid_p = descr->nr_cooked_registers; Andrew ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2002-08-13 22:21 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2002-08-10 16:58 [rfa:i386] Add mmx registers Andrew Cagney 2002-08-12 11:10 ` Mark Kettenis 2002-08-12 12:00 ` Andrew Cagney 2002-08-13 7:35 ` Andrew Cagney 2002-08-13 14:39 ` Mark Kettenis 2002-08-13 14:55 ` Andrew Cagney 2002-08-13 15:03 ` Andrew Cagney 2002-08-13 15:10 ` Mark Kettenis 2002-08-13 15:21 ` Andrew Cagney
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox