* [RFA] rs6000-tdep.c: more e500 support
@ 2002-08-22 11:02 Elena Zannoni
2002-08-22 12:11 ` Kevin Buettner
0 siblings, 1 reply; 8+ messages in thread
From: Elena Zannoni @ 2002-08-22 11:02 UTC (permalink / raw)
To: gdb-patches
Almost done. The only remaining patch is the push_arguments changes.
This patch takes care of skip_prologue, get_saved_regs, and handling
of return values.
Note how I used the new form of extract_return_value, the
non-deprecated one. Hope it's the right usage.
Elena
2002-08-22 Elena Zannoni <ezannoni@redhat.com>
* rs6000-tdep.c (struct rs6000_framedata): Add saved_ev and
ev_offset fields.
(skip_prologue): Add support for BookE/e500 instructions.
(e500_extract_return_value): New function.
(frame_get_saved_regs): Add support for saving ev registers and
pseudo gpr's.
(e500_store_return_value): New function.
(rs6000_gdbarch_init): Move up default intializations of
deprecated_extract_return_value and store_return_value. Overwrite
init of store_return_value with e500 specific version.
Set extract_return_value for e500.
Index: rs6000-tdep.c
===================================================================
RCS file: /cvs/uberbaum/gdb/rs6000-tdep.c,v
retrieving revision 1.76
diff -u -p -r1.76 rs6000-tdep.c
--- rs6000-tdep.c 21 Aug 2002 22:56:02 -0000 1.76
+++ rs6000-tdep.c 22 Aug 2002 17:50:23 -0000
@@ -67,12 +67,14 @@ struct rs6000_framedata
int saved_gpr; /* smallest # of saved gpr */
int saved_fpr; /* smallest # of saved fpr */
int saved_vr; /* smallest # of saved vr */
+ int saved_ev; /* smallest # of saved ev */
int alloca_reg; /* alloca register number (frame ptr) */
char frameless; /* true if frameless functions. */
char nosavedpc; /* true if pc not saved. */
int gpr_offset; /* offset of saved gprs from prev sp */
int fpr_offset; /* offset of saved fprs from prev sp */
int vr_offset; /* offset of saved vrs from prev sp */
+ int ev_offset; /* offset of saved evs from prev sp */
int lr_offset; /* offset of saved lr */
int cr_offset; /* offset of saved cr */
int vrsave_offset; /* offset of saved vrsave register */
@@ -359,11 +361,13 @@ rs6000_software_single_step (enum target
- saved_gpr is the number of the first saved gpr.
- saved_fpr is the number of the first saved fpr.
- saved_vr is the number of the first saved vr.
+ - saved_ev is the number of the first saved ev.
- alloca_reg is the number of the register used for alloca() handling.
Otherwise -1.
- gpr_offset is the offset of the first saved gpr from the previous frame.
- fpr_offset is the offset of the first saved fpr from the previous frame.
- vr_offset is the offset of the first saved vr from the previous frame.
+ - ev_offset is the offset of the first saved ev from the previous frame.
- lr_offset is the offset of the saved lr
- cr_offset is the offset of the saved cr
- vrsave_offset is the offset of the saved vrsave register
@@ -441,6 +445,8 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l
int lr_reg = -1;
int cr_reg = -1;
int vr_reg = -1;
+ int ev_reg = -1;
+ long ev_offset = 0;
int vrsave_reg = -1;
int reg;
int framep = 0;
@@ -467,6 +473,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l
fdata->saved_gpr = -1;
fdata->saved_fpr = -1;
fdata->saved_vr = -1;
+ fdata->saved_ev = -1;
fdata->alloca_reg = -1;
fdata->frameless = 1;
fdata->nosavedpc = 1;
@@ -533,7 +540,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l
}
else if ((op & 0xffff0000) == 0x60000000)
{
- /* nop */
+ /* nop */
/* Allow nops in the prologue, but do not consider them to
be part of the prologue unless followed by other prologue
instructions. */
@@ -647,7 +654,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l
else if ((op & 0xfc0007fe) == 0x7c000378 && /* mr(.) Rx,Ry */
(((op >> 21) & 31) >= 3) && /* R3 >= Ry >= R10 */
(((op >> 21) & 31) <= 10) &&
- (((op >> 16) & 31) >= fdata->saved_gpr)) /* Rx: local var reg */
+ ((long) ((op >> 16) & 31) >= fdata->saved_gpr)) /* Rx: local var reg */
{
continue;
@@ -728,7 +735,9 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l
in a pair of insns to save the vector registers on the
stack. */
/* 001110 00000 00000 iiii iiii iiii iiii */
- else if ((op & 0xffff0000) == 0x38000000) /* li r0, SIMM */
+ /* 001110 01110 00000 iiii iiii iiii iiii */
+ else if ((op & 0xffff0000) == 0x38000000 /* li r0, SIMM */
+ || (op & 0xffff0000) == 0x39c00000) /* li r14, SIMM */
{
li_found_pc = pc;
vr_saved_offset = SIGNED_SHORT (op);
@@ -754,6 +763,100 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l
}
}
/* End AltiVec related instructions. */
+
+ /* Start BookE related instructions. */
+ /* Store gen register S at (r31+uimm).
+ Any register less than r13 is volatile, so we don't care. */
+ /* 000100 sssss 11111 iiiii 01100100001 */
+ else if ((op & 0xfc1f07ff) == 0x101f0321) /* evstdd Rs,uimm(R31) */
+ {
+ if ((op & 0x03e00000) >= 0x01a00000) /* Rs >= r13 */
+ {
+ unsigned int imm;
+ ev_reg = GET_SRC_REG (op);
+ imm = (op >> 11) & 0x1f;
+ ev_offset = imm * 8;
+ /* If this is the first vector reg to be saved, or if
+ it has a lower number than others previously seen,
+ reupdate the frame info. */
+ if (fdata->saved_ev == -1 || fdata->saved_ev > ev_reg)
+ {
+ fdata->saved_ev = ev_reg;
+ fdata->ev_offset = ev_offset + offset;
+ }
+ }
+ continue;
+ }
+ /* Store gen register rS at (r1+rB). */
+ /* 000100 sssss 00001 bbbbb 01100100000 */
+ else if ((op & 0xffe007ff) == 0x13e00320) /* evstddx RS,R1,Rb */
+ {
+ if (pc == (li_found_pc + 4))
+ {
+ ev_reg = GET_SRC_REG (op);
+ /* If this is the first vector reg to be saved, or if
+ it has a lower number than others previously seen,
+ reupdate the frame info. */
+ /* We know the contents of rB from the previous instruction. */
+ if (fdata->saved_ev == -1 || fdata->saved_ev > ev_reg)
+ {
+ fdata->saved_ev = ev_reg;
+ fdata->ev_offset = vr_saved_offset + offset;
+ }
+ vr_saved_offset = -1;
+ ev_reg = -1;
+ li_found_pc = 0;
+ }
+ continue;
+ }
+ /* Store gen register r31 at (rA+uimm). */
+ /* 000100 11111 aaaaa iiiii 01100100001 */
+ else if ((op & 0xffe007ff) == 0x13e00321) /* evstdd R31,Ra,UIMM */
+ {
+ /* Wwe know that the source register is 31 already, but
+ it can't hurt to compute it. */
+ ev_reg = GET_SRC_REG (op);
+ ev_offset = ((op >> 11) & 0x1f) * 8;
+ /* If this is the first vector reg to be saved, or if
+ it has a lower number than others previously seen,
+ reupdate the frame info. */
+ if (fdata->saved_ev == -1 || fdata->saved_ev > ev_reg)
+ {
+ fdata->saved_ev = ev_reg;
+ fdata->ev_offset = ev_offset + offset;
+ }
+
+ continue;
+ }
+ /* Store gen register S at (r31+r0).
+ Store param on stack when offset from SP bigger than 4 bytes. */
+ /* 000100 sssss 11111 00000 01100100000 */
+ else if ((op & 0xfc1fffff) == 0x101f0320) /* evstddx Rs,R31,R0 */
+ {
+ if (pc == (li_found_pc + 4))
+ {
+ if ((op & 0x03e00000) >= 0x01a00000)
+ {
+ ev_reg = GET_SRC_REG (op);
+ /* If this is the first vector reg to be saved, or if
+ it has a lower number than others previously seen,
+ reupdate the frame info. */
+ /* We know the contents of r0 from the previous
+ instruction. */
+ if (fdata->saved_ev == -1 || fdata->saved_ev > ev_reg)
+ {
+ fdata->saved_ev = ev_reg;
+ fdata->ev_offset = vr_saved_offset + offset;
+ }
+ ev_reg = -1;
+ }
+ vr_saved_offset = -1;
+ li_found_pc = 0;
+ continue;
+ }
+ }
+ /* End BookE related instructions. */
+
else
{
/* Not a recognized prologue instruction.
@@ -1141,6 +1244,62 @@ ppc_push_return_address (CORE_ADDR pc, C
/* Extract a function return value of type TYPE from raw register array
REGBUF, and copy that return value into VALBUF in virtual format. */
+static void
+e500_extract_return_value (struct type *valtype, struct regcache *regbuf, char *valbuf)
+{
+ int offset = 0;
+ int vallen = TYPE_LENGTH (valtype);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+
+ if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY
+ && vallen == 8
+ && TYPE_VECTOR (valtype))
+ {
+ regcache_raw_read (regbuf, tdep->ppc_ev0_regnum + 3, valbuf);
+ }
+ else
+ {
+ /* Return value is copied starting from r3. Note that r3 for us
+ is a pseudo register. */
+ int offset = 0;
+ int return_regnum = tdep->ppc_gp0_regnum + 3;
+ int reg_size = REGISTER_RAW_SIZE (return_regnum);
+ int reg_part_size;
+ char *val_buffer;
+ int copied = 0;
+ int i = 0;
+
+ /* Compute where we will start storing the value from. */
+ if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+ {
+ if (vallen <= reg_size)
+ offset = reg_size - vallen;
+ else
+ offset = reg_size + (reg_size - vallen);
+ }
+
+ /* How big does the local buffer need to be? */
+ if (vallen <= reg_size)
+ val_buffer = alloca (reg_size);
+ else
+ val_buffer = alloca (vallen);
+
+ /* Read all we need into our private buffer. We copy it in
+ chunks that are as long as one register, never shorter, even
+ if the value is smaller than the register. */
+ while (copied < vallen)
+ {
+ reg_part_size = REGISTER_RAW_SIZE (return_regnum + i);
+ /* It is a pseudo/cooked register. */
+ regcache_cooked_read (regbuf, return_regnum + i,
+ val_buffer + copied);
+ copied += reg_part_size;
+ i++;
+ }
+ /* Put the stuff in the return buffer. */
+ memcpy (valbuf, val_buffer + offset, vallen);
+ }
+}
static void
rs6000_extract_return_value (struct type *valtype, char *regbuf, char *valbuf)
@@ -1394,9 +1553,11 @@ frame_get_saved_regs (struct frame_info
if (fdatap->saved_fpr == 0
&& fdatap->saved_gpr == 0
&& fdatap->saved_vr == 0
+ && fdatap->saved_ev == 0
&& fdatap->lr_offset == 0
&& fdatap->cr_offset == 0
- && fdatap->vr_offset == 0)
+ && fdatap->vr_offset == 0
+ && fdatap->ev_offset == 0)
frame_addr = 0;
else
/* NOTE: cagney/2002-04-14: The ->frame points to the inner-most
@@ -1450,6 +1611,23 @@ frame_get_saved_regs (struct frame_info
}
}
+ /* if != -1, fdatap->saved_ev is the smallest number of saved_ev.
+ All vr's from saved_ev to ev31 are saved. ????? */
+ if (tdep->ppc_ev0_regnum != -1 && tdep->ppc_ev31_regnum != -1)
+ {
+ if (fdatap->saved_ev >= 0)
+ {
+ int i;
+ CORE_ADDR ev_addr = frame_addr + fdatap->ev_offset;
+ for (i = fdatap->saved_ev; i < 32; i++)
+ {
+ fi->saved_regs[tdep->ppc_ev0_regnum + i] = ev_addr;
+ fi->saved_regs[tdep->ppc_gp0_regnum + i] = ev_addr + 4;
+ ev_addr += REGISTER_RAW_SIZE (tdep->ppc_ev0_regnum);
+ }
+ }
+ }
+
/* If != 0, fdatap->cr_offset is the offset from the frame that holds
the CR. */
if (fdatap->cr_offset != 0)
@@ -1801,6 +1979,27 @@ rs6000_store_struct_return (CORE_ADDR ad
/* Write into appropriate registers a function return value
of type TYPE, given in virtual format. */
+static void
+e500_store_return_value (struct type *type, char *valbuf)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+
+ /* Everything is returned in GPR3 and up. */
+ int copied = 0;
+ int i = 0;
+ int len = TYPE_LENGTH (type);
+ while (copied < len)
+ {
+ int regnum = gdbarch_tdep (current_gdbarch)->ppc_gp0_regnum + 3 + i;
+ int reg_size = REGISTER_RAW_SIZE (regnum);
+ char *reg_val_buf = alloca (reg_size);
+
+ memcpy (reg_val_buf, valbuf + copied, reg_size);
+ copied += reg_size;
+ write_register_gen (regnum, reg_val_buf);
+ i++;
+ }
+}
static void
rs6000_store_return_value (struct type *type, char *valbuf)
@@ -2553,6 +2752,9 @@ rs6000_gdbarch_init (struct gdbarch_info
set_gdbarch_pc_regnum (gdbarch, 64);
set_gdbarch_sp_regnum (gdbarch, 1);
set_gdbarch_fp_regnum (gdbarch, 1);
+ set_gdbarch_deprecated_extract_return_value (gdbarch,
+ rs6000_extract_return_value);
+ set_gdbarch_store_return_value (gdbarch, rs6000_store_return_value);
if (v->arch == bfd_arch_powerpc)
switch (v->mach)
@@ -2586,6 +2788,8 @@ rs6000_gdbarch_init (struct gdbarch_info
set_gdbarch_dwarf2_reg_to_regnum (gdbarch, e500_dwarf2_reg_to_regnum);
set_gdbarch_pseudo_register_read (gdbarch, e500_pseudo_register_read);
set_gdbarch_pseudo_register_write (gdbarch, e500_pseudo_register_write);
+ set_gdbarch_extract_return_value (gdbarch, e500_extract_return_value);
+ set_gdbarch_store_return_value (gdbarch, e500_store_return_value);
break;
default:
tdep->ppc_vr0_regnum = -1;
@@ -2667,9 +2871,6 @@ rs6000_gdbarch_init (struct gdbarch_info
set_gdbarch_register_convert_to_virtual (gdbarch, rs6000_register_convert_to_virtual);
set_gdbarch_register_convert_to_raw (gdbarch, rs6000_register_convert_to_raw);
set_gdbarch_stab_reg_to_regnum (gdbarch, rs6000_stab_reg_to_regnum);
-
- set_gdbarch_deprecated_extract_return_value (gdbarch, rs6000_extract_return_value);
-
/* Note: kevinb/2002-04-12: I'm not convinced that rs6000_push_arguments()
is correct for the SysV ABI when the wordsize is 8, but I'm also
fairly certain that ppc_sysv_abi_push_arguments() will give even
@@ -2683,7 +2884,6 @@ rs6000_gdbarch_init (struct gdbarch_info
set_gdbarch_push_arguments (gdbarch, rs6000_push_arguments);
set_gdbarch_store_struct_return (gdbarch, rs6000_store_struct_return);
- set_gdbarch_store_return_value (gdbarch, rs6000_store_return_value);
set_gdbarch_deprecated_extract_struct_value_address (gdbarch, rs6000_extract_struct_value_address);
set_gdbarch_pop_frame (gdbarch, rs6000_pop_frame);
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [RFA] rs6000-tdep.c: more e500 support 2002-08-22 11:02 [RFA] rs6000-tdep.c: more e500 support Elena Zannoni @ 2002-08-22 12:11 ` Kevin Buettner 2002-08-22 13:10 ` Elena Zannoni 0 siblings, 1 reply; 8+ messages in thread From: Kevin Buettner @ 2002-08-22 12:11 UTC (permalink / raw) To: Elena Zannoni, gdb-patches On Aug 22, 1:50pm, Elena Zannoni wrote: > @@ -647,7 +654,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l > else if ((op & 0xfc0007fe) == 0x7c000378 && /* mr(.) Rx,Ry */ > (((op >> 21) & 31) >= 3) && /* R3 >= Ry >= R10 */ > (((op >> 21) & 31) <= 10) && > - (((op >> 16) & 31) >= fdata->saved_gpr)) /* Rx: local var reg */ > + ((long) ((op >> 16) & 31) >= fdata->saved_gpr)) /* Rx: local var reg */ > { > continue; > Why is the cast needed above? > @@ -754,6 +763,100 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l > } > } > /* End AltiVec related instructions. */ > + > + /* Start BookE related instructions. */ > + /* Store gen register S at (r31+uimm). > + Any register less than r13 is volatile, so we don't care. */ > + /* 000100 sssss 11111 iiiii 01100100001 */ > + else if ((op & 0xfc1f07ff) == 0x101f0321) /* evstdd Rs,uimm(R31) */ Hmm... it looks like BookE is using 6 for its primary opcode (which are the most significant 6 bits). I wonder if this could cause conflicts with other cores which also extend the base PPC instruction set. A quick Google search reveals: http://sources.redhat.com/ml/binutils/2001-10/msg00186.html So apparently there can be conflicts. It's not clear to me if there are conflicts for the instructions that we care about, but I wonder if it might not be better to add a conjunct which restricts these tests to the BookE architecture. (Maybe it'd be a good idea to squirrel away the v->arch and v->mach values from rs6000_gdbarch_init() into the gdbarch_tdep struct. I guess you could also check to see if tdep->ppc_ev0_regnum is not -1.) Kevin ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFA] rs6000-tdep.c: more e500 support 2002-08-22 12:11 ` Kevin Buettner @ 2002-08-22 13:10 ` Elena Zannoni 2002-08-22 13:35 ` Andrew Cagney 2002-08-22 13:41 ` Kevin Buettner 0 siblings, 2 replies; 8+ messages in thread From: Elena Zannoni @ 2002-08-22 13:10 UTC (permalink / raw) To: Kevin Buettner; +Cc: Elena Zannoni, gdb-patches Kevin Buettner writes: > On Aug 22, 1:50pm, Elena Zannoni wrote: > > > @@ -647,7 +654,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l > > else if ((op & 0xfc0007fe) == 0x7c000378 && /* mr(.) Rx,Ry */ > > (((op >> 21) & 31) >= 3) && /* R3 >= Ry >= R10 */ > > (((op >> 21) & 31) <= 10) && > > - (((op >> 16) & 31) >= fdata->saved_gpr)) /* Rx: local var reg */ > > + ((long) ((op >> 16) & 31) >= fdata->saved_gpr)) /* Rx: local var reg */ > > { > > continue; > > > > Why is the cast needed above? Signed & unsigend comparisons, when saved_gpr is -1: op is unsigned long, while saved_gpr is an int I was running into this: (gdb) p (unsigned long) 0 > (int) -1 $3 = 0 the cast makes it work. I could have changed the type of op, but I was afraid I would break a bunch of other things. (gdb) p (long) 0 > (int) -1 $4 = 1 > > > @@ -754,6 +763,100 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l > > } > > } > > /* End AltiVec related instructions. */ > > + > > + /* Start BookE related instructions. */ > > + /* Store gen register S at (r31+uimm). > > + Any register less than r13 is volatile, so we don't care. */ > > + /* 000100 sssss 11111 iiiii 01100100001 */ > > + else if ((op & 0xfc1f07ff) == 0x101f0321) /* evstdd Rs,uimm(R31) */ > > Hmm... it looks like BookE is using 6 for its primary opcode (which are > the most significant 6 bits). I wonder if this could cause conflicts > with other cores which also extend the base PPC instruction set. > > A quick Google search reveals: > > http://sources.redhat.com/ml/binutils/2001-10/msg00186.html > > So apparently there can be conflicts. It's not clear to me if there > are conflicts for the instructions that we care about, but I wonder > if it might not be better to add a conjunct which restricts these tests > to the BookE architecture. (Maybe it'd be a good idea to squirrel > away the v->arch and v->mach values from rs6000_gdbarch_init() into > the gdbarch_tdep struct. I guess you could also check to see if > tdep->ppc_ev0_regnum is not -1.) > Yes, conflicts also with Altivec instructions. I would prefer to save the architecture & machine pair, rather than check the registers. Elena > Kevin ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFA] rs6000-tdep.c: more e500 support 2002-08-22 13:10 ` Elena Zannoni @ 2002-08-22 13:35 ` Andrew Cagney 2002-08-22 13:41 ` Kevin Buettner 1 sibling, 0 replies; 8+ messages in thread From: Andrew Cagney @ 2002-08-22 13:35 UTC (permalink / raw) To: Elena Zannoni; +Cc: Kevin Buettner, gdb-patches > > Hmm... it looks like BookE is using 6 for its primary opcode (which are > > the most significant 6 bits). I wonder if this could cause conflicts > > with other cores which also extend the base PPC instruction set. > > > > A quick Google search reveals: > > > > http://sources.redhat.com/ml/binutils/2001-10/msg00186.html > > > > So apparently there can be conflicts. It's not clear to me if there > > are conflicts for the instructions that we care about, but I wonder > > if it might not be better to add a conjunct which restricts these tests > > to the BookE architecture. (Maybe it'd be a good idea to squirrel > > away the v->arch and v->mach values from rs6000_gdbarch_init() into > > the gdbarch_tdep struct. I guess you could also check to see if > > tdep->ppc_ev0_regnum is not -1.) > > > > Yes, conflicts also with Altivec instructions. I would prefer to save > the architecture & machine pair, rather than check the registers. Try: const struct bfd_arch_info *gdbarch_bfd_arch_info (gdbarch) Andrew ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFA] rs6000-tdep.c: more e500 support 2002-08-22 13:10 ` Elena Zannoni 2002-08-22 13:35 ` Andrew Cagney @ 2002-08-22 13:41 ` Kevin Buettner 2002-08-22 15:01 ` Elena Zannoni 1 sibling, 1 reply; 8+ messages in thread From: Kevin Buettner @ 2002-08-22 13:41 UTC (permalink / raw) To: Elena Zannoni, Kevin Buettner; +Cc: gdb-patches On Aug 22, 4:02pm, Elena Zannoni wrote: > Kevin Buettner writes: > > On Aug 22, 1:50pm, Elena Zannoni wrote: > > > > > @@ -647,7 +654,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l > > > else if ((op & 0xfc0007fe) == 0x7c000378 && /* mr(.) Rx,Ry */ > > > (((op >> 21) & 31) >= 3) && /* R3 >= Ry >= R10 */ > > > (((op >> 21) & 31) <= 10) && > > > - (((op >> 16) & 31) >= fdata->saved_gpr)) /* Rx: local var reg */ > > > + ((long) ((op >> 16) & 31) >= fdata->saved_gpr)) /* Rx: local var reg */ > > > { > > > continue; > > > > > > > Why is the cast needed above? > > Signed & unsigend comparisons, when saved_gpr is -1: > op is unsigned long, while saved_gpr is an int > > I was running into this: > (gdb) p (unsigned long) 0 > (int) -1 > $3 = 0 > > the cast makes it work. I could have changed the type of op, but I was > afraid I would break a bunch of other things. > > (gdb) p (long) 0 > (int) -1 > $4 = 1 Okay, thanks for the explanation. > > > @@ -754,6 +763,100 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l > > > } > > > } > > > /* End AltiVec related instructions. */ > > > + > > > + /* Start BookE related instructions. */ > > > + /* Store gen register S at (r31+uimm). > > > + Any register less than r13 is volatile, so we don't care. */ > > > + /* 000100 sssss 11111 iiiii 01100100001 */ > > > + else if ((op & 0xfc1f07ff) == 0x101f0321) /* evstdd Rs,uimm(R31) */ > > > > Hmm... it looks like BookE is using 6 for its primary opcode (which are > > the most significant 6 bits). I wonder if this could cause conflicts > > with other cores which also extend the base PPC instruction set. > > > > A quick Google search reveals: > > > > http://sources.redhat.com/ml/binutils/2001-10/msg00186.html > > > > So apparently there can be conflicts. It's not clear to me if there > > are conflicts for the instructions that we care about, but I wonder > > if it might not be better to add a conjunct which restricts these tests > > to the BookE architecture. (Maybe it'd be a good idea to squirrel > > away the v->arch and v->mach values from rs6000_gdbarch_init() into > > the gdbarch_tdep struct. I guess you could also check to see if > > tdep->ppc_ev0_regnum is not -1.) > > > > Yes, conflicts also with Altivec instructions. I would prefer to save > the architecture & machine pair, rather than check the registers. I would prefer that also. Kevin ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFA] rs6000-tdep.c: more e500 support 2002-08-22 13:41 ` Kevin Buettner @ 2002-08-22 15:01 ` Elena Zannoni 2002-08-22 15:07 ` Kevin Buettner 0 siblings, 1 reply; 8+ messages in thread From: Elena Zannoni @ 2002-08-22 15:01 UTC (permalink / raw) To: Kevin Buettner; +Cc: Elena Zannoni, gdb-patches Kevin Buettner writes: > On Aug 22, 4:02pm, Elena Zannoni wrote: > > > Kevin Buettner writes: > > > On Aug 22, 1:50pm, Elena Zannoni wrote: > > > > > > > @@ -647,7 +654,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l > > > > else if ((op & 0xfc0007fe) == 0x7c000378 && /* mr(.) Rx,Ry */ > > > > (((op >> 21) & 31) >= 3) && /* R3 >= Ry >= R10 */ > > > > (((op >> 21) & 31) <= 10) && > > > > - (((op >> 16) & 31) >= fdata->saved_gpr)) /* Rx: local var reg */ > > > > + ((long) ((op >> 16) & 31) >= fdata->saved_gpr)) /* Rx: local var reg */ > > > > { > > > > continue; > > > > > > > > > > Why is the cast needed above? > > > > Signed & unsigend comparisons, when saved_gpr is -1: > > op is unsigned long, while saved_gpr is an int > > > > I was running into this: > > (gdb) p (unsigned long) 0 > (int) -1 > > $3 = 0 > > > > the cast makes it work. I could have changed the type of op, but I was > > afraid I would break a bunch of other things. > > > > (gdb) p (long) 0 > (int) -1 > > $4 = 1 > > Okay, thanks for the explanation. > > > > > @@ -754,6 +763,100 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l > > > > } > > > > } > > > > /* End AltiVec related instructions. */ > > > > + > > > > + /* Start BookE related instructions. */ > > > > + /* Store gen register S at (r31+uimm). > > > > + Any register less than r13 is volatile, so we don't care. */ > > > > + /* 000100 sssss 11111 iiiii 01100100001 */ > > > > + else if ((op & 0xfc1f07ff) == 0x101f0321) /* evstdd Rs,uimm(R31) */ > > > > > > Hmm... it looks like BookE is using 6 for its primary opcode (which are > > > the most significant 6 bits). I wonder if this could cause conflicts > > > with other cores which also extend the base PPC instruction set. > > > > > > A quick Google search reveals: > > > > > > http://sources.redhat.com/ml/binutils/2001-10/msg00186.html > > > > > > So apparently there can be conflicts. It's not clear to me if there > > > are conflicts for the instructions that we care about, but I wonder > > > if it might not be better to add a conjunct which restricts these tests > > > to the BookE architecture. (Maybe it'd be a good idea to squirrel > > > away the v->arch and v->mach values from rs6000_gdbarch_init() into > > > the gdbarch_tdep struct. I guess you could also check to see if > > > tdep->ppc_ev0_regnum is not -1.) > > > > > > > Yes, conflicts also with Altivec instructions. I would prefer to save > > the architecture & machine pair, rather than check the registers. > > I would prefer that also. > > Kevin I ended up using Andrew's suggestion. How's this? Index: rs6000-tdep.c =================================================================== RCS file: /cvs/uberbaum/gdb/rs6000-tdep.c,v retrieving revision 1.76 diff -u -p -r1.76 rs6000-tdep.c --- rs6000-tdep.c 21 Aug 2002 22:56:02 -0000 1.76 +++ rs6000-tdep.c 22 Aug 2002 21:54:12 -0000 @@ -67,12 +67,14 @@ struct rs6000_framedata int saved_gpr; /* smallest # of saved gpr */ int saved_fpr; /* smallest # of saved fpr */ int saved_vr; /* smallest # of saved vr */ + int saved_ev; /* smallest # of saved ev */ int alloca_reg; /* alloca register number (frame ptr) */ char frameless; /* true if frameless functions. */ char nosavedpc; /* true if pc not saved. */ int gpr_offset; /* offset of saved gprs from prev sp */ int fpr_offset; /* offset of saved fprs from prev sp */ int vr_offset; /* offset of saved vrs from prev sp */ + int ev_offset; /* offset of saved evs from prev sp */ int lr_offset; /* offset of saved lr */ int cr_offset; /* offset of saved cr */ int vrsave_offset; /* offset of saved vrsave register */ @@ -359,11 +361,13 @@ rs6000_software_single_step (enum target - saved_gpr is the number of the first saved gpr. - saved_fpr is the number of the first saved fpr. - saved_vr is the number of the first saved vr. + - saved_ev is the number of the first saved ev. - alloca_reg is the number of the register used for alloca() handling. Otherwise -1. - gpr_offset is the offset of the first saved gpr from the previous frame. - fpr_offset is the offset of the first saved fpr from the previous frame. - vr_offset is the offset of the first saved vr from the previous frame. + - ev_offset is the offset of the first saved ev from the previous frame. - lr_offset is the offset of the saved lr - cr_offset is the offset of the saved cr - vrsave_offset is the offset of the saved vrsave register @@ -441,13 +445,16 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l int lr_reg = -1; int cr_reg = -1; int vr_reg = -1; + int ev_reg = -1; + long ev_offset = 0; int vrsave_reg = -1; int reg; int framep = 0; int minimal_toc_loaded = 0; int prev_insn_was_prologue_insn = 1; int num_skip_non_prologue_insns = 0; - + const struct bfd_arch_info *arch_info = gdbarch_bfd_arch_info (current_gdbarch); + /* Attempt to find the end of the prologue when no limit is specified. Note that refine_prologue_limit() has been written so that it may be used to "refine" the limits of non-zero PC values too, but this @@ -467,6 +474,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l fdata->saved_gpr = -1; fdata->saved_fpr = -1; fdata->saved_vr = -1; + fdata->saved_ev = -1; fdata->alloca_reg = -1; fdata->frameless = 1; fdata->nosavedpc = 1; @@ -533,7 +541,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l } else if ((op & 0xffff0000) == 0x60000000) { - /* nop */ + /* nop */ /* Allow nops in the prologue, but do not consider them to be part of the prologue unless followed by other prologue instructions. */ @@ -647,7 +655,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l else if ((op & 0xfc0007fe) == 0x7c000378 && /* mr(.) Rx,Ry */ (((op >> 21) & 31) >= 3) && /* R3 >= Ry >= R10 */ (((op >> 21) & 31) <= 10) && - (((op >> 16) & 31) >= fdata->saved_gpr)) /* Rx: local var reg */ + ((long) ((op >> 16) & 31) >= fdata->saved_gpr)) /* Rx: local var reg */ { continue; @@ -728,7 +736,9 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l in a pair of insns to save the vector registers on the stack. */ /* 001110 00000 00000 iiii iiii iiii iiii */ - else if ((op & 0xffff0000) == 0x38000000) /* li r0, SIMM */ + /* 001110 01110 00000 iiii iiii iiii iiii */ + else if ((op & 0xffff0000) == 0x38000000 /* li r0, SIMM */ + || (op & 0xffff0000) == 0x39c00000) /* li r14, SIMM */ { li_found_pc = pc; vr_saved_offset = SIGNED_SHORT (op); @@ -754,6 +764,104 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l } } /* End AltiVec related instructions. */ + + /* Start BookE related instructions. */ + /* Store gen register S at (r31+uimm). + Any register less than r13 is volatile, so we don't care. */ + /* 000100 sssss 11111 iiiii 01100100001 */ + else if (arch_info->mach == bfd_mach_ppc_e500 + && (op & 0xfc1f07ff) == 0x101f0321) /* evstdd Rs,uimm(R31) */ + { + if ((op & 0x03e00000) >= 0x01a00000) /* Rs >= r13 */ + { + unsigned int imm; + ev_reg = GET_SRC_REG (op); + imm = (op >> 11) & 0x1f; + ev_offset = imm * 8; + /* If this is the first vector reg to be saved, or if + it has a lower number than others previously seen, + reupdate the frame info. */ + if (fdata->saved_ev == -1 || fdata->saved_ev > ev_reg) + { + fdata->saved_ev = ev_reg; + fdata->ev_offset = ev_offset + offset; + } + } + continue; + } + /* Store gen register rS at (r1+rB). */ + /* 000100 sssss 00001 bbbbb 01100100000 */ + else if (arch_info->mach == bfd_mach_ppc_e500 + && (op & 0xffe007ff) == 0x13e00320) /* evstddx RS,R1,Rb */ + { + if (pc == (li_found_pc + 4)) + { + ev_reg = GET_SRC_REG (op); + /* If this is the first vector reg to be saved, or if + it has a lower number than others previously seen, + reupdate the frame info. */ + /* We know the contents of rB from the previous instruction. */ + if (fdata->saved_ev == -1 || fdata->saved_ev > ev_reg) + { + fdata->saved_ev = ev_reg; + fdata->ev_offset = vr_saved_offset + offset; + } + vr_saved_offset = -1; + ev_reg = -1; + li_found_pc = 0; + } + continue; + } + /* Store gen register r31 at (rA+uimm). */ + /* 000100 11111 aaaaa iiiii 01100100001 */ + else if (arch_info->mach == bfd_mach_ppc_e500 + && (op & 0xffe007ff) == 0x13e00321) /* evstdd R31,Ra,UIMM */ + { + /* Wwe know that the source register is 31 already, but + it can't hurt to compute it. */ + ev_reg = GET_SRC_REG (op); + ev_offset = ((op >> 11) & 0x1f) * 8; + /* If this is the first vector reg to be saved, or if + it has a lower number than others previously seen, + reupdate the frame info. */ + if (fdata->saved_ev == -1 || fdata->saved_ev > ev_reg) + { + fdata->saved_ev = ev_reg; + fdata->ev_offset = ev_offset + offset; + } + + continue; + } + /* Store gen register S at (r31+r0). + Store param on stack when offset from SP bigger than 4 bytes. */ + /* 000100 sssss 11111 00000 01100100000 */ + else if (arch_info->mach == bfd_mach_ppc_e500 + && (op & 0xfc1fffff) == 0x101f0320) /* evstddx Rs,R31,R0 */ + { + if (pc == (li_found_pc + 4)) + { + if ((op & 0x03e00000) >= 0x01a00000) + { + ev_reg = GET_SRC_REG (op); + /* If this is the first vector reg to be saved, or if + it has a lower number than others previously seen, + reupdate the frame info. */ + /* We know the contents of r0 from the previous + instruction. */ + if (fdata->saved_ev == -1 || fdata->saved_ev > ev_reg) + { + fdata->saved_ev = ev_reg; + fdata->ev_offset = vr_saved_offset + offset; + } + ev_reg = -1; + } + vr_saved_offset = -1; + li_found_pc = 0; + continue; + } + } + /* End BookE related instructions. */ + else { /* Not a recognized prologue instruction. @@ -1141,6 +1249,62 @@ ppc_push_return_address (CORE_ADDR pc, C /* Extract a function return value of type TYPE from raw register array REGBUF, and copy that return value into VALBUF in virtual format. */ +static void +e500_extract_return_value (struct type *valtype, struct regcache *regbuf, char *valbuf) +{ + int offset = 0; + int vallen = TYPE_LENGTH (valtype); + struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + + if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY + && vallen == 8 + && TYPE_VECTOR (valtype)) + { + regcache_raw_read (regbuf, tdep->ppc_ev0_regnum + 3, valbuf); + } + else + { + /* Return value is copied starting from r3. Note that r3 for us + is a pseudo register. */ + int offset = 0; + int return_regnum = tdep->ppc_gp0_regnum + 3; + int reg_size = REGISTER_RAW_SIZE (return_regnum); + int reg_part_size; + char *val_buffer; + int copied = 0; + int i = 0; + + /* Compute where we will start storing the value from. */ + if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) + { + if (vallen <= reg_size) + offset = reg_size - vallen; + else + offset = reg_size + (reg_size - vallen); + } + + /* How big does the local buffer need to be? */ + if (vallen <= reg_size) + val_buffer = alloca (reg_size); + else + val_buffer = alloca (vallen); + + /* Read all we need into our private buffer. We copy it in + chunks that are as long as one register, never shorter, even + if the value is smaller than the register. */ + while (copied < vallen) + { + reg_part_size = REGISTER_RAW_SIZE (return_regnum + i); + /* It is a pseudo/cooked register. */ + regcache_cooked_read (regbuf, return_regnum + i, + val_buffer + copied); + copied += reg_part_size; + i++; + } + /* Put the stuff in the return buffer. */ + memcpy (valbuf, val_buffer + offset, vallen); + } +} static void rs6000_extract_return_value (struct type *valtype, char *regbuf, char *valbuf) @@ -1394,9 +1558,11 @@ frame_get_saved_regs (struct frame_info if (fdatap->saved_fpr == 0 && fdatap->saved_gpr == 0 && fdatap->saved_vr == 0 + && fdatap->saved_ev == 0 && fdatap->lr_offset == 0 && fdatap->cr_offset == 0 - && fdatap->vr_offset == 0) + && fdatap->vr_offset == 0 + && fdatap->ev_offset == 0) frame_addr = 0; else /* NOTE: cagney/2002-04-14: The ->frame points to the inner-most @@ -1450,6 +1616,23 @@ frame_get_saved_regs (struct frame_info } } + /* if != -1, fdatap->saved_ev is the smallest number of saved_ev. + All vr's from saved_ev to ev31 are saved. ????? */ + if (tdep->ppc_ev0_regnum != -1 && tdep->ppc_ev31_regnum != -1) + { + if (fdatap->saved_ev >= 0) + { + int i; + CORE_ADDR ev_addr = frame_addr + fdatap->ev_offset; + for (i = fdatap->saved_ev; i < 32; i++) + { + fi->saved_regs[tdep->ppc_ev0_regnum + i] = ev_addr; + fi->saved_regs[tdep->ppc_gp0_regnum + i] = ev_addr + 4; + ev_addr += REGISTER_RAW_SIZE (tdep->ppc_ev0_regnum); + } + } + } + /* If != 0, fdatap->cr_offset is the offset from the frame that holds the CR. */ if (fdatap->cr_offset != 0) @@ -1801,6 +1984,27 @@ rs6000_store_struct_return (CORE_ADDR ad /* Write into appropriate registers a function return value of type TYPE, given in virtual format. */ +static void +e500_store_return_value (struct type *type, char *valbuf) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + + /* Everything is returned in GPR3 and up. */ + int copied = 0; + int i = 0; + int len = TYPE_LENGTH (type); + while (copied < len) + { + int regnum = gdbarch_tdep (current_gdbarch)->ppc_gp0_regnum + 3 + i; + int reg_size = REGISTER_RAW_SIZE (regnum); + char *reg_val_buf = alloca (reg_size); + + memcpy (reg_val_buf, valbuf + copied, reg_size); + copied += reg_size; + write_register_gen (regnum, reg_val_buf); + i++; + } +} static void rs6000_store_return_value (struct type *type, char *valbuf) @@ -2553,6 +2757,9 @@ rs6000_gdbarch_init (struct gdbarch_info set_gdbarch_pc_regnum (gdbarch, 64); set_gdbarch_sp_regnum (gdbarch, 1); set_gdbarch_fp_regnum (gdbarch, 1); + set_gdbarch_deprecated_extract_return_value (gdbarch, + rs6000_extract_return_value); + set_gdbarch_store_return_value (gdbarch, rs6000_store_return_value); if (v->arch == bfd_arch_powerpc) switch (v->mach) @@ -2586,6 +2793,8 @@ rs6000_gdbarch_init (struct gdbarch_info set_gdbarch_dwarf2_reg_to_regnum (gdbarch, e500_dwarf2_reg_to_regnum); set_gdbarch_pseudo_register_read (gdbarch, e500_pseudo_register_read); set_gdbarch_pseudo_register_write (gdbarch, e500_pseudo_register_write); + set_gdbarch_extract_return_value (gdbarch, e500_extract_return_value); + set_gdbarch_store_return_value (gdbarch, e500_store_return_value); break; default: tdep->ppc_vr0_regnum = -1; @@ -2667,9 +2876,6 @@ rs6000_gdbarch_init (struct gdbarch_info set_gdbarch_register_convert_to_virtual (gdbarch, rs6000_register_convert_to_virtual); set_gdbarch_register_convert_to_raw (gdbarch, rs6000_register_convert_to_raw); set_gdbarch_stab_reg_to_regnum (gdbarch, rs6000_stab_reg_to_regnum); - - set_gdbarch_deprecated_extract_return_value (gdbarch, rs6000_extract_return_value); - /* Note: kevinb/2002-04-12: I'm not convinced that rs6000_push_arguments() is correct for the SysV ABI when the wordsize is 8, but I'm also fairly certain that ppc_sysv_abi_push_arguments() will give even @@ -2683,7 +2889,6 @@ rs6000_gdbarch_init (struct gdbarch_info set_gdbarch_push_arguments (gdbarch, rs6000_push_arguments); set_gdbarch_store_struct_return (gdbarch, rs6000_store_struct_return); - set_gdbarch_store_return_value (gdbarch, rs6000_store_return_value); set_gdbarch_deprecated_extract_struct_value_address (gdbarch, rs6000_extract_struct_value_address); set_gdbarch_pop_frame (gdbarch, rs6000_pop_frame); ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFA] rs6000-tdep.c: more e500 support 2002-08-22 15:01 ` Elena Zannoni @ 2002-08-22 15:07 ` Kevin Buettner 2002-08-22 15:31 ` Elena Zannoni 0 siblings, 1 reply; 8+ messages in thread From: Kevin Buettner @ 2002-08-22 15:07 UTC (permalink / raw) To: Elena Zannoni, Kevin Buettner; +Cc: gdb-patches On Aug 22, 5:54pm, Elena Zannoni wrote: > How's this? > > Index: rs6000-tdep.c > =================================================================== > RCS file: /cvs/uberbaum/gdb/rs6000-tdep.c,v > retrieving revision 1.76 > diff -u -p -r1.76 rs6000-tdep.c > --- rs6000-tdep.c 21 Aug 2002 22:56:02 -0000 1.76 > +++ rs6000-tdep.c 22 Aug 2002 21:54:12 -0000 Yes, fine. Thanks, Kevin ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFA] rs6000-tdep.c: more e500 support 2002-08-22 15:07 ` Kevin Buettner @ 2002-08-22 15:31 ` Elena Zannoni 0 siblings, 0 replies; 8+ messages in thread From: Elena Zannoni @ 2002-08-22 15:31 UTC (permalink / raw) To: Kevin Buettner; +Cc: Elena Zannoni, gdb-patches Kevin Buettner writes: > On Aug 22, 5:54pm, Elena Zannoni wrote: > > > How's this? > > > > Index: rs6000-tdep.c > > =================================================================== > > RCS file: /cvs/uberbaum/gdb/rs6000-tdep.c,v > > retrieving revision 1.76 > > diff -u -p -r1.76 rs6000-tdep.c > > --- rs6000-tdep.c 21 Aug 2002 22:56:02 -0000 1.76 > > +++ rs6000-tdep.c 22 Aug 2002 21:54:12 -0000 > > Yes, fine. > > Thanks, > > Kevin Thanks. Committed. Elena ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2002-08-22 22:28 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2002-08-22 11:02 [RFA] rs6000-tdep.c: more e500 support Elena Zannoni 2002-08-22 12:11 ` Kevin Buettner 2002-08-22 13:10 ` Elena Zannoni 2002-08-22 13:35 ` Andrew Cagney 2002-08-22 13:41 ` Kevin Buettner 2002-08-22 15:01 ` Elena Zannoni 2002-08-22 15:07 ` Kevin Buettner 2002-08-22 15:31 ` Elena Zannoni
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox