[PATCH,MIPS 1/3] Re-work setjmp/longjmp to match o32 FPXX and FP64 ABI
Wed Nov 26 22:47:00 GMT 2014
> > > +#elif __mips_fpr == 0 || __mips_fpr == 64
> > > +#define FPR_LAYOUT \
> > > + and $8, $4, 4; \
> > > + bne $8, $0, 1f; \
> > > + GPR_OFFSET ($31, 22); \
> > > + addiu $4, $4, -4; \
> > > +1: \
> > > + FPR_OFFSET ($f20, 0); \
> > > + FPR_OFFSET ($f22, 2); \
> > > + FPR_OFFSET ($f24, 4); \
> > > + FPR_OFFSET ($f26, 6); \
> > > + FPR_OFFSET ($f28, 8); \
> > > + FPR_OFFSET ($f30, 10);
> The only thing I was not sure of with patch 1 is the saving of $31. I
> understand the need for the stack to be 8 byte aligned but I am not sure
> why we need to save $31 here and in GPR_LAYOUT. Can we just align the
> stack without saving $31? I am also not sure how 22 was arrived at as
> the offset.
The setjmp/longjmp routines don't know what memory they have been provided
with they merely have a buffer. In MIPS case the buffer is only 4-byte
aligned and we cannot increase alignment without breaking compatibility
with all pre-existing objects built against newlib.
What this means is that we can't just shunt up the base of the buffer and
use some more space at the end as it will be out of range.
Instead we have to create an aligned space within the jmpbuf for the
double precision registers and shuffle the store of whichever register that
this displaces. Since $31 is saved last it is the one that is overwritten
if we have to realign the base of the FPR area down by 4 bytes.
The purpose of writing to GPOFF index 22 is to write to the last 4-byte slot
in the buffer. It comes out from:
#define GPOFF(INDEX) (INDEX * BYTES_PER_WORD)
#define FPOFF(INDEX) ((INDEX + NUM_GPRS_SAVED) * BYTES_PER_WORD)
NUM_GPRS_SAVED is 11 so the first FP register is in 11*BYTES_PER_WORD and there
are 12 FPRs so the last half of the last one is in 22*BYTES_PER_WORD. Therefore
using 22 with GPR_OFFSET gets the same slot. I do think this is hideously
obfuscated but I'm not sure if anything else would make sense either.
I don't know if it would help (for example) to have a macro like GPR_OFFSET
but that uses FPOFF.
#define GPR_FPOFFSET(REG, INDEX) STORE_GPR REG,FPOFF(INDEX)($4)
This could then be used as GPR_FPOFFSET(11) instead of GPR_OFFSET(22) though
it is perhaps just as confusing.
Any suggestions and/or does it make more sense now?
Thanks for the review,
More information about the Newlib