[kaffe] mipsel JIT3
Kevin D. Kissell
kevink at mips.com
Fri Mar 5 14:14:01 PST 2004
> Right now these are my suspicions/ideas:
> * The register managment code (spills/allocs/restores) appears to
> have changed to the point where it is incompatible with the way
> the MIPS backend presents its registers. Specifically, it looks
> like the register code likes to assume that the `regno' field is
> an index into the reginfo array, which isn't true for MIPS (it
> numbers its int registers from 0 to 31, then its float registers
> from 0 to 31 again).
It looks to me as if the MIPS numbering is done that way so that
the synthesis of instructions can be done using regno, since MIPS
FPRs and GPRs are in seperate banks and both addressed
from 0 to 31.
> *Maybe* the register functions need to be a little smarter, by
> first choosing any register whose regno field matches the ideal
> number, then choosing the best register out of that set that fits
> the other criteria best.
> (This is all crash-course hacking I'm doing, so I might be
> totally mistaken).
The "rreg_ideal" functions did more-or-less that, if I recall (it's been
about a year since I did the same crash course your're doing now).
> * If I renumber the float registers from 32 to 63, the spill
> problem doesn't happen, but I get a bus error when the `call'
> instruction is reached. This happens because the constant pool
> code tries to restore register gp from fp, and it looks like fp
> gets clobbered before this can happen.
The code generation in jit3-mips.def is going to generate all sorts
of broken code if you allow those values to go above 31, I think.
There is no masking of the shifted values as the instruction words
are being created.
You are very likely correct that the use of regno as an index
is causing major problems, but I if you're going to renumber the
floats, you need to tweak the instruction generation code. The
minimalist hack would be to tweak some or all of the 9 macros
at the top of jit3-mips.def to take advantage of the fact that
33 % 32 = 1, i.e.
#define insn_RRR(op, rd, rs, rt) \
LOUT = 0x00000000 | ((rs) << 21) | \
((rt) << 16) | ((rd) << 11) | (op)
#define insn_RRR(op,rd,rs,rt) \
LOUT = 0x00000000 | (((rs) & 0x1f) <<21) \
(((rt)&0x1f)<<16) | (((rd)&0x1f)<<11) op
> * If I disable the JIT constant pool, I get a segmentation
> fault. This happens because load_constant_int writes the
> return value of Float.isNaN(I)Z into register a0 (aka i4), and
> back in Float.toString  this register is used to reload itself
> (i.e. `lw a0,24(a0)'). This fails because that register now
> contains the result of a boolean method (1 or 0).
> So, it looks like there are some missing restores. These
> registers are spilled when they are used, but aren't restored.
That's the syndrome that I was seeing that ORing Reserved
into the descriptors for the argument registers seemed to help.
That's fixing the symptom rather than the cause, though. It solves
the problem by making sure that the argument registers won't
be allocated for anything else, which would be wasteful as hell
on a more register-poor architecture. The more correct fix would
be to do the right thing (if only I knew exacltly what that was!)
when arguments are being set up in registers, so that the registers
are flagged as being valid even though the values weren't generated
by the JIT. You might think that that's exaclty what's being done
in places like the definition of push_double and push_float, when
rreg_ideal_int() is being invoked on the argument registers,
but empirically that wasn't the case when I looked into this last year.
More information about the kaffe