This is the mail archive of the
cgen@sources.redhat.com
mailing list for the CGEN project.
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