This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC][PATCH] Process record support for ppc


Anthony Green wrote:

>   This patch isn't quite ready for prime-time.  I just wanted to put it
> out there for comment, should there be any.  The current status is that
> none of the gdb.reverse tests FAIL due to unrecognized instructions (on
> powerpc64-unknown-linux-gnu (Fedora)).  There are just some oddities to
> sort out around reverse next, etc.

Thanks for working on this!

>From reviewing the list of recognized instructions, it does seem that
many are still missing.  In particular, none of VMX, VSX, or DFP is
implemented -- but I guess we can live without those for a first
implementation.

However, even many base instructions (many floating-point, but also
several integer) ones are missing; I think it would be good to add
those for completeness.  Most should be able to be handled just like
others that are already implemented.

Here's the list I came up with (comparing against the latest ISA,
and omitting anything VMX, VSX, DFP, privileged, or embedded-only).

A few of those are rare and can probably be omitted for now.


Missing main opcodes:

0x0c addic
0x17 rlwnm[.]
0x1d andis.
0x2b lhau
0x31 lfsu
0x33 lfdu
0x35 stfsu
0x37 stfdu

0x2e lmw  (low-prio)
0x2f stmw  (low-prio)
0x38 lq  (low-prio)
0x39 lfdp  (low-prio)
0x3d stfdp  (low-prio)


Missing subcodes of main opcode 0x1f (load/store):

0x157 lhax Load Halfword Algebraic Indexed
0x097 stwx Store Word Indexed

0x035 ldux Load Doubleword with Update Indexed
0x037 lwzux Load Word and Zero with Update Indexed
0x175 lwaux Load Word Algebraic with Update Indexed
0x137 lhzux Load Halfword and Zero with Update Indexed
0x177 lhaux Load Halfword Algebraic with Update Indexed
0x077 lbzux Load Byte and Zero with Update Indexed
0x1b7 sthux Store Halfword with Update Indexed
0x0b7 stwux Store Word with Update Indexed
0x0f7 stbux Store Byte with Update Indexed

0x214 ldbrx Load Doubleword Byte-Reverse Indexed (low-prio)
0x216 lwbrx Load Word Byte-Reverse Indexed (low-prio)
0x316 lhbrx Load Halfword Byte-Reverse Indexed (low-prio)
0x294 stdbrx Store Doubleword Byte-Reverse Indexed (low-prio)
0x296 stwbrx Store Word Byte-Reverse Indexed (low-prio)
0x396 sthbrx Store Halfword Byte-Reverse Indexed (low-prio)

0x114 lqarx Load Quadword And Reserve Indexed (low-prio)
0x074 lharx Load Halfword And Reserve Indexed (low-prio)
0x034 lbarx Load Byte And Reserve Indexed (low-prio)
0x0b6 stqcx. Store Quadword Conditional Indexed (low-prio)
0x0d6 stdcx. Store Doubleword Conditional Indexed (low-prio)
0x096 stwcx. Store Word Conditional Indexed (low-prio)
0x2d6 sthcx. Store Halfword Conditional Indexed (low-prio)
0x2b6 stbcx. Store Byte Conditional Indexed (low-prio)
[ Can reverse-debugging handle load-reserve/store-conditional at all ???
  The patch below attemps to handle ldarx/lwarx ... ]

0x217 lfsx Load Floating-Point Single Indexed
0x257 lfdx Load Floating-Point Double Indexed
0x297 stfsx Store Floating-Point Single Indexed
0x2d7 stfdx Store Floating-Point Double Indexed
0x237 lfsux Load Floating-Point Single with Update Indexed
0x277 lfdux Load Floating-Point Double with Update Indexed
0x2b7 stfsux Store Floating-Point Single with Update Indexed
0x2f7 stfdux Store Floating-Point Double with Update Indexed
0x357 lfiwax Load Floating-Point as Integer Word Algebraic Indexed
0x377 lfiwzx Load Floating-Point as Integer Word and Zero Indexed
0x3d7 stfiwx Store Floating-Point as Integer Word Indexed

0x317 lfdpx Load Floating-Point Double Pair Indexed  (low-prio)
0x397 stfdpx Store Floating-Point Double Pair Indexed  (low-prio)


Missing subcodes of main opcode 0x1f (arithmetic):

0x00a addc[.] Add Carrying
0x0ca addze[.] Add to Zero Extended
0x0ea addme[.] Add to Minus One Extended
0x008 subfc[.] Subtract From Carrying
0x0c8 subfze[.] Subtract From Zero Extended
0x0e8 subfme[.] Subtract From Minus One Extended
0x00b mulhwu[.] Multiply High Word Unsigned
0x049 mulhd[.] Multiply High Doubleword
0x04b mulhw[.] Multiply High Word
0x189 divdeu[.] Divide Doubleword Extended Unsigned
0x18b divweu[.] Divide Word Extended Unsigned
0x1a9 divde[.] Divide Doubleword Extended
0x1ab divwe[.] Divide Word Extended
0x1cb divwu[.] Divide Word Unsigned
0x1e9 divd[.] Divide Doubleword
0x1eb divw[.] Divide Word

Missing subcodes of main opcode 0x1f (arithmetic / overflow variants):  (low-prio)

0x30a addo[.] Add & record OV
0x20a addco[.] Add Carrying & record OV
0x28a addeo[.] Add Extended & record OV & record OV
0x2ca addzeo[.] Add to Zero Extended & record OV
0x2ea addmeo[.] Add to Minus One Extended & record OV
0x208 subfco[.] Subtract From Carrying & record OV
0x228 subfo[.] Subtract From & record OV
0x288 subfeo[.] Subtract From Extended & record OV
0x2c8 subfzeo[.] Subtract From Zero Extended & record OV
0x2e8 subfmeo[.] Subtract From Minus One Extended & record OV
0x268 nego[.] Negate & record OV
0x2e9 mulldo[.] Multiply Low Doubleword & record OV
0x2eb mullwo[.] Multiply Low Word & record OV
0x389 divdeuo[.] Divide Doubleword Extended Unsigned & record OV
0x38b divweuo[.] Divide Word Extended Unsigned & record OV
0x3a9 divdeo[.] Divide Doubleword Extended & record OV
0x3ab divweo[.] Divide Word Extended & record OV
0x3c9 divduo[.] Divide Doubleword Unsigned & record OV
0x3cb divwuo[.] Divide Word Unsigned & record OV
0x3e9 divdo[.] Divide Doubleword & record OV
0x3eb divwo[.] Divide Word & record OV

Missing subcodes of main opcode 0x1f (misc):

0x1fc cmpb Compare Byte
0x3ba extsb[.] Extend Sign Byte
0x1dc nand[.] NAND
0x01b sld[.] Shift Left Doubleword
0x31a srad[.] Shift Right Algebraic Doubleword
0x218 srw[.] Shift Right Word
0x21b srd[.] Shift Right Doubleword

0x00f isel Integer Select
0x07a popcntb Population Count Byte-wise
0x17a popcntw Population Count Words
0x1fa popcntd Population Count Doubleword
0x09a prtyw Parity Word
0x0ba prtyd Parity Doubleword
0x0fc bpermd Bit Permute Doubleword

0x0f6 dcbtst Data Cache Block Touch for Store
0x3d6 icbi Instruction Cache Block Invalidate
0x356 eieio Enforce In-order Execution of I/O
0x03e wait Wait for Interrupt


Missing subcodes of main opcode 0x3b (floating-point):

0x012 fdivs[.] Floating Divide Single
0x014 fsubs[.] Floating Subtract Single
0x015 fadds[.] Floating Add Single
0x016 fsqrts[.] Floating Square Root Single
0x018 fres[.] Floating Reciprocal Estimate Single
0x019 fmuls[.] Floating Multiply Single
0x01a frsqrtes[.] Floating Reciprocal Square Root Estimate Single
0x01c fmsubs[.] Floating Multiply-Subtract Single
0x01d fmadds[.] Floating Multiply-Add Single
0x01e fnmsubs[.] Floating Negative Multiply-Subtract Single
0x01f fnmadds[.] Floating Negative Multiply-Add Single
0x34e fcfids[.] Floating Convert From Integer Doubleword Single
0x3ce fcfidus[.] Floating Convert From Integer Doubleword Unsigned Single

Missing subcodes of main opcode 0x3f (floating-point):

0x000 fcmpu Floating Compare Unordered
0x008 fcpsgn[.] Floating Copy Sign
0x00c frsp[.] Floating Round to Single-Precision
0x00e fctiw[.] Floating Convert To Integer Word
0x00f fctiwz[.] Floating Convert To Integer Word with round to Zero
0x012 fdiv[.] Floating Divide
0x014 fsub[.] Floating Subtract
0x015 fadd[.] Floating Add
0x016 fsqrt[.] Floating Square Root
0x017 fsel[.] Floating Select
0x018 fre[.] Floating Reciprocal Estimate
0x019 fmul[.] Floating Multiply
0x01a frsqrte[.] Floating Reciprocal Square Root Estimate
0x01c fmsub[.] Floating Multiply-Subtract
0x01d fmadd[.] Floating Multiply-Add
0x01e fnmsub[.] Floating Negative Multiply-Subtract
0x01f fnmadd[.] Floating Negative Multiply-Add
0x020 fcmpo Floating Compare Ordered
0x026 mtfsb1[.] Move To FPSCR Bit 1
0x028 fneg[.] Floating Negate
0x040 mcrfs Move To Condition Register from FPSCR
0x046 mtfsb0[.] Move To FPSCR Bit 0
0x080 ftdiv Floating Test for software Divide
0x086 mtfsfi[.] Move To FPSCR Field Immediate
0x088 fnabs[.] Floating Negative Absolute Value
0x08e fctiwu[.] Floating Convert To Integer Word Unsigned
0x08f fctiwuz[.] Floating Convert To Integer Word Unsigned with round toward Zero
0x0a0 ftsqrt Floating Test for software Square Root
0x108 fabs[.] Floating Absolute Value
0x188 frin[.] Floating Round To Integer Nearest
0x1a8 friz[.] Floating Round To Integer toward Zero
0x1c8 frip[.] Floating Round To Integer Plus
0x1e8 frim[.] Floating Round To Integer Minus
0x247 mffs[.] Move From FPSCR
0x2c7 mtfsf[.] Move To FPSCR Fields
0x32e fctid[.] Floating Convert To Integer Doubleword
0x32f fctidz[.] Floating Convert To Integer Doubleword with round toward Zero
0x34e fcfid[.] Floating Convert From Integer Doubleword
0x3ae fctidu[.] Floating Convert To Integer Doubleword Unsigned
0x3af fctiduz[.] Floating Convert To Integer Doubleword Unsigned with round toward Zero
0x3ce fcfidu[.] Floating Convert From Integer Doubleword Unsigned


A few other comments on the patch itself:


> +  /* Support reverse debugging.  */
> +  set_gdbarch_process_record (gdbarch, rs6000_process_record);

Will this actually work anywhere but on Linux targets?  Maybe better
to only install there.

i386 also uses set_gdbarch_process_record_signal; do we need that too?


> +static int
> +rs6000_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
> +		       CORE_ADDR addr)
> +{
> +  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
> +  uint32_t op;
> +
> +  if (record_debug > 1)
> +    fprintf_unfiltered (gdb_stdlog, "Process record: rs6000_process_record "
> +			            "addr = 0x%s\n",
> +			paddress (target_gdbarch (), addr));

Why use target_gdbarch here?  We've got a gdbarch ...

> +  op = rs6000_fetch_instruction (gdbarch, addr);
> +
> +  switch (PPC_OP (op))
> +    {
> +    case 0x7:  /* mulli */
> +    case 0xe:  /* addi */
> +    case 0xf:  /* addis */
> +    case 0x20: /* lwz */
> +    case 0x2a: /* lha */

Maybe move lwz/lha below to the lhz etc. group

> +      {
> +	int reg = (op >> 21) & ((1<<5)-1);
> +
> +	if (record_full_arch_list_add_reg (regcache, reg))
> +	  return -1;
> +      }
> +      break;
> +
> +    case 0x8:  /* subfic */
> +      { 
> +	int reg = (op >> 21) & ((1<<5)-1);
> +
> +	if (record_full_arch_list_add_reg (regcache, PPC_XER_REGNUM))
> +	  return -1;
> +	if (record_full_arch_list_add_reg (regcache, reg))
> +	  return -1;
> +      }
> +      break;
> +
> +    case 0xa: /* cmpli */
> +    case 0xb: /* cmpi */
> +      if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM))
> +	return -1;
> +      break;
> +
> +    case 0xd: /* addic. */
> +      { 
> +	int reg = (op >> 21) & ((1<<5)-1);
> +
> +	if (record_full_arch_list_add_reg (regcache, PPC_XER_REGNUM))
> +	  return -1;
> +	if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM))
> +	  return -1;
> +	if (record_full_arch_list_add_reg (regcache, reg))
> +	  return -1;
> +      }
> +      break;
> +
> +    case 0x10: /* bc */
> +      if (record_full_arch_list_add_reg (regcache, PPC_LR_REGNUM))
> +	return -1;
> +      if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM))

This should be PPC_CTR_REGNUM, not PPC_CR_REGNUM, right?

Here and elsewhere, I'm not sure if it would be worthwile to track
modifications to registers more precisely, i.e. specifically check
for the Rc bit before marking CR as modified; specifically check
whether this instruction actually modifies CTR and/or LR; etc.

> +	return -1;
> +      break;
> +
> +    case 0x11: /* sc */
> +      if (record_full_arch_list_add_reg (regcache, PPC_MSR_REGNUM))
> +	return -1;
> +      /* Also SRR0 and SRR1, but not implementing supervisory instructions here */

Well, it seems this would have to handle the effects of the actual syscall,
using a OS-specific callback (like on Intel).  At some point, that should
then probably call into record_linux_system_call -- need to verify whether
that is actually correct for PowerPC.

> +      break;
> +
> +    case 0x12: /* b */
> +      {
> +	if (record_full_arch_list_add_reg (regcache, PPC_LR_REGNUM))
> +	  return -1;
> +      }

Braces unnecessary here.

> +      break;
> +
> +    case 0x13:
> +      {
> +	switch ((op >> 1) & ((1<<10)-1))
> +	  {
> +	  case 0x0: /* mcrf */
> +	    if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM))
> +	      return -1;
> +	    break;
> +	    
> +	  case 0x10: /* bclr */

Might also handle bctar[l] with the same implementation.

> +	    if (record_full_arch_list_add_reg (regcache, PPC_LR_REGNUM))
> +	      return -1;
> +	    if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM))

Again CTR, not CR.

> +	      return -1;
> +	    break;
> +
> +	  case 0xc1: /* crxor */

Should handle likewise: crandc, crnand, crand, creqv, crorc, cror.

> +	    if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM))
> +	      return -1;
> +	    break;
> +
> +	  case 0x96: /* isync */
> +	    break;
> +
> +	  case 0x210: /* bcctr */
> +	    if (record_full_arch_list_add_reg (regcache, PPC_LR_REGNUM))
> +	      return -1;
> +	    break;
> +
> +	  default:
> +	    printf_unfiltered (_("Process record: unrecognized instruction "
> +				 "0x13 opcode 0x%x at addr 0x%s.\n"), 
> +			       ((op >> 1) & ((1<<10)-1)),
> +			       paddress (target_gdbarch (), addr));
> +	    return -1;
> +	  }
> +      }
> +      break;
> +	
> +    case 0x14: /* rlwimi */
> +    case 0x15: /* rlwinm */
> +    case 0x1c: /* andi. */
> +    case 0x1e: /* rldicl, rldicr */

Now this opcode also covers rldic[.], rldimi[.], rldcl[.], rldcr[.] ...
Fortunately, the implementation seems correct for all of them, but it
should still be indicated in the comment.

> +      {
> +	int reg = (op >> 16) & ((1<<5)-1);
> +
> +	if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM))
> +	  return -1;
> +	if (record_full_arch_list_add_reg (regcache, reg))
> +	  return -1;
> +      }
> +      break;
> +
> +    case 0x18: /* ori */
> +    case 0x19: /* oris */
> +    case 0x1a: /* xori */
> +    case 0x1b: /* xoris */
> +      {
> +	int reg = (op >> 16) & ((1<<5)-1);
> +
> +	if (record_full_arch_list_add_reg (regcache, reg))
> +	  return -1;
> +	break;
> +      }
> +
> +    case 0x1f:
> +      {
> +	int reg;
> +	switch ((op >> 1) & ((1<<10)-1))
> +	  {
> +	  case 0x0:  /* cmp */
> +	  case 0x20: /* cmpl */
> +	    if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM))
> +	      return -1;
> +	    break;
> +	    
> +	  case 0x9: /* mulhdu */
> +	    if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM))
> +	      return -1;
> +	    reg = (op >> 21) & ((1<<5)-1);
> +	    if (record_full_arch_list_add_reg (regcache, reg))
> +	      return -1;
> +	    break;
> +
> +	  case 0x13:  /* mfcr */

This also includes mfocrf (implementation is fine, but should be called
out in the comment).

> +	  case 0x14:  /* lwarx */
> +	  case 0x15:  /* ldx */
> +	  case 0x17:  /* lwzx */
> +	  case 0x54:  /* ldarx */
> +	  case 0x57:  /* lbzx */
> +	  case 0x117: /* lhzx */
> +	  case 0x155: /* lwax */
> +	    reg = (op >> 21) & ((1<<5)-1);
> +	    if (record_full_arch_list_add_reg (regcache, reg))
> +	      return -1;
> +	    break;
> +
> +	  case 0x90: /* mtcrf */

And this also includes mtocrf (implementation is again fine).

> +	    if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM))
> +	      return -1;
> +	    break;
> +
> +	  case 0x28:  /* subf */
> +	  case 0x68:  /* neg */
> +	  case 0x88:  /* subfe */
> +	  case 0x8a:  /* adde */
> +	  case 0xe9:  /* mulld */
> +	  case 0xeb:  /* mullw */
> +	  case 0x10a: /* add */
> +	  case 0x1c9: /* divdu */
> +	    if (record_full_arch_list_add_reg (regcache, PPC_XER_REGNUM))
> +	      return -1;
> +	    if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM))
> +	      return -1;
> +	    reg = (op >> 21) & ((1<<5)-1);
> +	    if (record_full_arch_list_add_reg (regcache, reg))
> +	      return -1;
> +	    break;
> +
> +	  case 0x36:  /* dcbst */
> +	  case 0x56:  /* dcbf */
> +	  case 0x116: /* dcbt */
> +	  case 0x256: /* sync */
> +	  case 0x3f6: /* sync */

Hmm, that last one is actually dcbz ...

> +	    break;
> +
> +	  case 0x318: /* sraw */
> +	  case 0x33a: /* sradi */

And this is actually srawi.

> +	  case 0x33b: /* sradi */
> +	    if (record_full_arch_list_add_reg (regcache, PPC_XER_REGNUM))
> +	      return -1;
> +	    /* fall through... */
> +	  case 0x8:   /* rldcl */

But this is subfc, and it is handled incorrectly here!

> +	  case 0x18:  /* slw */
> +	  case 0x1a:  /* cntlzw */
> +	  case 0x1c:  /* and */
> +	  case 0x3a:  /* cntlzd */
> +	  case 0x3c:  /* andc */
> +	  case 0x7c:  /* nor */
> +	  case 0x11c: /* eqv */
> +	  case 0x13c: /* xor */
> +	  case 0x1bc: /* or */
> +	  case 0x19c: /* orc */
> +	  case 0x21b: /* srd */
> +	  case 0x39a: /* extsh */
> +	  case 0x3da: /* extsw */
> +	    if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM))
> +	      return -1;
> +	    /* fall through... */
> +	  case 0x153: /* mfspr */

This also seems to be handled incorrectly; the target register is in bits 6..10
for mfspr, as opposed for the others in this group.

> +	    reg = (op >> 16) & ((1<<5)-1);
> +	    if (record_full_arch_list_add_reg (regcache, reg))
> +	      return -1;
> +	    break;
> +
> +	  case 0x95: /* stdx */
> +	    {
> +	      CORE_ADDR rAa, rBa;
> +	      int regS = (op >> 21) & ((1<<5)-1);

regS is never used here (and in cases below).

> +	      int regA = (op >> 16) & ((1<<5)-1);
> +	      int regB = (op >> 11) & ((1<<5)-1);
> +
> +	      if (regA)
> +		regcache_raw_read_unsigned (regcache, regA, &rAa);
> +	      else
> +		rAa = 0;
> +	      regcache_raw_read_unsigned (regcache, regB, &rBa);
> +	
> +	      if (record_full_arch_list_add_mem (rAa + rBa, 8))
> +		return -1;
> +	    }
> +	    break;
> +
> +	  case 0xb5: /* stdux */
> +	    {
> +	      CORE_ADDR rAa, rBa;
> +	      int regS = (op >> 21) & ((1<<5)-1);
> +	      int regA = (op >> 16) & ((1<<5)-1);
> +	      int regB = (op >> 11) & ((1<<5)-1);
> +
> +	      if (record_full_arch_list_add_reg (regcache, regA))
> +		return -1;
> +
> +	      regcache_raw_read_unsigned (regcache, regA, &rAa);
> +	      regcache_raw_read_unsigned (regcache, regB, &rBa);
> +	
> +	      if (record_full_arch_list_add_mem (rAa + rBa, 8))
> +		return -1;
> +	    }
> +	    break;
> +
> +	  case 0xd7: /* stbx */
> +	    {
> +	      CORE_ADDR rAa, rBa;
> +	      int regS = (op >> 21) & ((1<<5)-1);
> +	      int regA = (op >> 16) & ((1<<5)-1);
> +	      int regB = (op >> 11) & ((1<<5)-1);
> +
> +	      if (regA)
> +		regcache_raw_read_unsigned (regcache, regA, &rAa);
> +	      else
> +		rAa = 0;
> +	      regcache_raw_read_unsigned (regcache, regB, &rBa);
> +	
> +	      if (record_full_arch_list_add_mem (rAa + rBa, 1))
> +		return -1;
> +	    }
> +	    break;
> +
> +	  case 0x197: /* sthx */
> +	    {
> +	      CORE_ADDR rAa, rBa;
> +	      int regS = (op >> 21) & ((1<<5)-1);
> +	      int regA = (op >> 16) & ((1<<5)-1);
> +	      int regB = (op >> 11) & ((1<<5)-1);
> +
> +	      if (regA)
> +		regcache_raw_read_unsigned (regcache, regA, &rAa);
> +	      else
> +		rAa = 0;
> +	      regcache_raw_read_unsigned (regcache, regB, &rBa);
> +	
> +	      if (record_full_arch_list_add_mem (rAa + rBa, 2))
> +		return -1;
> +	    }
> +	    break;
> +
> +	  case 0x1d3: /* mtspr */
> +	    reg = (op >> 11) & ((1<<10)-1);
> +	    switch (reg)
> +	      {
> +	      case 0x100: /* lr */
> +		if (record_full_arch_list_add_reg (regcache, PPC_LR_REGNUM))
> +		  return -1;
> +		break;
> +
> +	      case 0x120: /* ctr */
> +		if (record_full_arch_list_add_reg (regcache, PPC_CTR_REGNUM))
> +		  return -1;
> +		break;
> +
> +	      default:
> +		printf_unfiltered (_("Process record: unrecognized mtspr SPR 0x%x"
> +				     " at addr 0x%s.\n"), 
> +				   reg, paddress (target_gdbarch (), addr));
> +		return -1;
> +	      }
> +	    break;
> +
> +	  case 0x338: /* srawi */

Well, this is not srawi, this code seems unassigned ...
However, srawi is actually correctly handled above, so this code seems
unnecessary.

> +	    if (record_full_arch_list_add_reg (regcache, PPC_XER_REGNUM))
> +	      return -1;
> +	    if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM))
> +	      return -1;
> +	    reg = (op >> 16) & ((1<<5)-1);
> +	    if (record_full_arch_list_add_reg (regcache, reg))
> +	      return -1;
> +	    break;
> +
> +	  default:
> +	    printf_unfiltered (_("Process record: unrecognized instruction 0x1F opcode 0x%x"
> +				 " at addr 0x%s.\n"), 
> +			       ((op >> 1) & ((1<<10)-1)), paddress (target_gdbarch (), addr));
> +	    return -1;
> +	  }
> +	break;
> +      }
> +
> +    case 0x21: /* lwzu */
> +    case 0x23: /* lbzu */
> +    case 0x29: /* lhzu */
> +      {
> +	int regT = (op >> 21) & ((1<<5)-1);
> +	int regA = (op >> 16) & ((1<<5)-1);
> +
> +	if (record_full_arch_list_add_reg (regcache, regA))
> +	  return -1;
> +	if (record_full_arch_list_add_reg (regcache, regT))
> +	  return -1;
> +      }      
> +      break;
> +
> +    case 0x22: /* lbz */
> +    case 0x28: /* lhz */
> +    case 0x3a: /* ld */

OK, this is wrong for 0x3a.  The low two bits are a sub-opcode here,
and this opcode covers not just ld, but also lwa (for which the
implementation would be correct), and ldu (for which it is wrong).

> +      {
> +	int regT = (op >> 21) & ((1<<5)-1);
> +
> +	if (record_full_arch_list_add_reg (regcache, regT))
> +	  return -1;
> +      }      
> +      break;
> +
> +    case 0x24: /* stw */
> +    case 0x34: /* stfs */
> +      {
> +	CORE_ADDR addr;
> +	int regS = (op >> 21) & ((1<<5)-1);

regS again unused here (and below).

> +	int regA = (op >> 16) & ((1<<5)-1);
> +	int32_t offset = (((int32_t)op & 0xFFFF) << 16) >> 16;
> +
> +	if (regA == 0)
> +	  addr = 0;
> +	else
> +	  regcache_raw_read_unsigned (regcache, regA, &addr);
> +	
> +	if (record_full_arch_list_add_mem (addr + offset, 4))
> +	  return -1;
> +      }
> +      break;
> +
> +    case 0x25: /* stwu */
> +      {
> +	CORE_ADDR addr;
> +	int regS = (op >> 21) & ((1<<5)-1);
> +	int regA = (op >> 16) & ((1<<5)-1);
> +	int32_t offset = (((int32_t)op & 0xFFFF) << 16) >> 16;
> +
> +	if (record_full_arch_list_add_reg (regcache, regA))
> +	  return -1;
> +
> +	regcache_raw_read_unsigned (regcache, regA, &addr);
> +	
> +	if (record_full_arch_list_add_mem (addr + offset, 4))
> +	  return -1;
> +      }
> +      break;
> +
> +    case 0x26: /* stb */
> +      {
> +	CORE_ADDR addr;
> +	int regS = (op >> 21) & ((1<<5)-1);
> +	int regA = (op >> 16) & ((1<<5)-1);
> +	int32_t offset = (((int32_t)op & 0xFFFF) << 16) >> 16;
> +
> +	if (regA == 0)
> +	  addr = 0;
> +	else
> +	  regcache_raw_read_unsigned (regcache, regA, &addr);
> +	
> +	if (record_full_arch_list_add_mem (addr + offset, 1))
> +	  return -1;
> +      }
> +      break;
> +
> +    case 0x27: /* stbu */
> +      {
> +	CORE_ADDR addr;
> +	int regS = (op >> 21) & ((1<<5)-1);
> +	int regA = (op >> 16) & ((1<<5)-1);
> +	int32_t offset = (((int32_t)op & 0xFFFF) << 16) >> 16;
> +
> +	if (record_full_arch_list_add_reg (regcache, regA))
> +	  return -1;
> +
> +	regcache_raw_read_unsigned (regcache, regA, &addr);
> +	
> +	if (record_full_arch_list_add_mem (addr + offset, 1))
> +	  return -1;
> +      }
> +      break;
> +
> +    case 0x2c: /* sth */
> +      {
> +	CORE_ADDR addr;
> +	int regS = (op >> 21) & ((1<<5)-1);
> +	int regA = (op >> 16) & ((1<<5)-1);
> +	int32_t offset = (((int32_t)op & 0xFFFF) << 16) >> 16;
> +
> +	if (regA == 0)
> +	  addr = 0;
> +	else
> +	  regcache_raw_read_unsigned (regcache, regA, &addr);
> +	
> +	if (record_full_arch_list_add_mem (addr + offset, 2))
> +	  return -1;
> +      }
> +      break;
> +
> +    case 0x2d: /* sthu */
> +      {
> +	CORE_ADDR addr;
> +	int regS = (op >> 21) & ((1<<5)-1);
> +	int regA = (op >> 16) & ((1<<5)-1);
> +	int32_t offset = (((int32_t)op & 0xFFFF) << 16) >> 16;
> +
> +	if (record_full_arch_list_add_reg (regcache, regA))
> +	  return -1;
> +
> +	regcache_raw_read_unsigned (regcache, regA, &addr);
> +	
> +	if (record_full_arch_list_add_mem (addr + offset, 2))
> +	  return -1;
> +      }
> +      break;
> +
> +    case 0x30: /* lfs */
> +    case 0x32: /* lfd */
> +      {
> +	int regT = (op >> 21) & ((1<<5)-1);
> +
> +	if (record_full_arch_list_add_reg (regcache, PPC_F0_REGNUM + regT))
> +	  return -1;
> +      }      
> +      break;
> +
> +    case 0x36: /* stfd */
> +    case 0x3e: /* std */

Again, for 0x3e the low two bits are a sub-opcode; this covers std, stdu,
and stq.  Note that when computing the address, the low bits must be
masked out.

> +      {
> +	CORE_ADDR addr;
> +	int regS = (op >> 21) & ((1<<5)-1);
> +	int regA = (op >> 16) & ((1<<5)-1);
> +	int32_t offset = (((int32_t)op & 0xFFFF) << 16) >> 16;
> +
> +	if (regA == 0)
> +	  addr = 0;
> +	else
> +	  regcache_raw_read_unsigned (regcache, regA, &addr);
> +	
> +	if (record_full_arch_list_add_mem (addr + offset, 8))
> +	  return -1;
> +      }
> +      break;
> +
> +    case 0x3f:
> +      {
> +	int reg;
> +
> +	switch ((op >> 1) & ((1<<10)-1))
> +	  {
> +	  case 0x48: /* fmr */
> +	    {
> +	      int regT = (op >> 21) & ((1<<5)-1);
> +	      if (record_full_arch_list_add_reg (regcache, PPC_F0_REGNUM + regT))
> +		return -1;
> +	    }
> +	    break;
> +
> +	  default:
> +	    printf_unfiltered (_("Process record: unrecognized instruction 0x3F opcode 0x%x"
> +				 " at addr 0x%s.\n"), 
> +			       ((op >> 1) & ((1<<10)-1)), paddress (target_gdbarch (), addr));
> +	    return -1;
> +	  }
> +      }
> +      break;
> +
> +    default:
> +      printf_unfiltered (_("Process record: unrecognized instruction opcode 0x%x"
> +			   " at addr 0x%s.\n"), 
> +			 PPC_OP (op), paddress (target_gdbarch (), addr));
> +      return -1;
> +    }
> +
> +  if (record_full_arch_list_add_reg (regcache, PPC_PC_REGNUM))
> +    return -1;
> +  if (record_full_arch_list_add_end ())
> +    return -1;
> +
> +  return 0;
> +}


Bye,
Ulrich


-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]