This is the mail archive of the cgen@sources.redhat.com mailing list for the CGEN project.


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

Re: incorrect disassembly on vliw / little endian


Patrick Macdonald writes:
 > Patrick Macdonald wrote:
 > > 
 > > Hello,
 > > 
 > > This is a follow up to my prior note.  This patch fixes the vliw,
 > > little endian problem I'm seeing.  I have a few concerns though:
 > > 
 > > 1. Is it too restrictive?
 > > 2. Can we assume that most reads/writes will be multiples of 8?
 > 
 > Missing an "even" there.  Point 2 should read:
 > 
 >   2. Can we assume that most reads/writes will be even multiples of
 >      8 (except for 8)?  (8/16/32)
 >  
 > > Comments/suggestions?  If not, I'll submit it.

fwiw, this doesn't seem like the right way to go.
[it may certainly be the best expedient way though]

I'm guessing this is the code that's getting you into trouble.
Clearly the `then' branch is the wrong thing to do for your port.

[While Frank can certainly disagree, I kinda like having
the int insns [for sparc, etc.] - one problem is that the support got
extended to ports that has thus far worked, but with recent ports
is now starting to break.]

	  /* Make sure the entire insn is loaded into insn_value, if it
	     can fit.  */
	  if (CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize &&
	      (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
	    {
	      unsigned long full_insn_value;
	      int rc = read_insn (cd, pc, info, buf,
				  CGEN_INSN_BITSIZE (insn) / 8,
				  & ex_info, & full_insn_value);
	      if (rc != 0)
		return rc;
	      length = CGEN_EXTRACT_FN (cd, insn)
		(cd, insn, &ex_info, full_insn_value, &fields, pc);
	    }
	  else
	    length = CGEN_EXTRACT_FN (cd, insn)
	      (cd, insn, &ex_info, insn_value, &fields, pc);

Maybe a better solution lies along getting the `else' branch
working.

 > > binutils ==========
 > > 
 > > RCS file: /cvs/src/src/opcodes/cgen-dis.in,v
 > > retrieving revision 1.5
 > > diff -c -p -r1.5 cgen-dis.in
 > > *** cgen-dis.in 2001/01/09 17:00:21     1.5
 > > --- cgen-dis.in 2001/01/30 20:40:06
 > > *************** print_insn (cd, pc, info, buf, buflen)
 > > *** 278,283 ****
 > > --- 278,296 ----
 > >                                   & ex_info, & full_insn_value);
 > >               if (rc != 0)
 > >                 return rc;
 > > +
 > > +               /* The re-read on a vliw, little endian will transpose the
 > > bytes.
 > > +                  Correct this with a hi byte(s) / lo bytes(s) flip.  Note that
 > > the
 > > +                  content of full_insn_value is not true little endian now. */
 > > +               if (info->endian == BFD_ENDIAN_LITTLE &&
 > > +                   (CGEN_INSN_BITSIZE (insn) / 2) == cd->base_insn_bitsize)
 > > +                {
 > > +                  unsigned long mask = ~(0xffffffff << cd->base_insn_bitsize);
 > > +                  unsigned long hi = (full_insn_value & mask) <<
 > > cd->base_insn_bitsize;
 > > +                  unsigned long lo = full_insn_value >> cd->base_insn_bitsize;
 > > +                  full_insn_value = hi | lo;
 > > +                }
 > > +
 > >               length = CGEN_EXTRACT_FN (cd, insn)
 > >                 (cd, insn, &ex_info, full_insn_value, &fields, pc);
 > >             }
 > > 
 > > Patrick Macdonald wrote:
 > > >
 > > > Hi,
 > > >
 > > > I'm using cgen on a vliw set with the following characteristics:
 > > > 16 bit base instruction, 16/32 bit additional bits based on
 > > > the contents of the base instruction, little endian.
 > > >
 > > > I guess it's best to describe my problem with an example:
 > > >
 > > > Let's say I have a 16 bit instruction (0xdead) and a 16 bit
 > > > variable (0xbeef). The assembler writes this to disk as
 > > > adde efbe, which is correct.
 > > >
 > > > On disassembly in @port@-dis.c, the first 16 bits are read in to
 > > > determine the instruction (0xdead).  It matches with a 32 bit
 > > > instruction and the instruction is re-read as a 32 bit, little
 > > > endian instruction causing the full instruction to become 0xbeefdead
 > > > instead of the correct 0xdeadbeef.
 > > >
 > > > Before I start mangling the code, has anyone else encountered this
 > > > or am I just extremely lucky these days?  Thoughts/hints/directions
 > > > gladly accepted.
 > > >
 > > > I'm leaning towards adding a check of endianess on the re-read and
 > > > flipping the bits if little endian.  Based on the conditions to
 > > > enter the re-read, this would solve the problem for this particular
 > > > port without crippling others.
 > > >
 > > > Patrick

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