This is the mail archive of the
mailing list for the newlib project.
RE: [PATCH,MIPS 1/3] Re-work setjmp/longjmp to match o32 FPXX and FP64 ABI
- From: Matthew Fortune <Matthew dot Fortune at imgtec dot com>
- To: Steve Ellcey <Steve dot Ellcey at imgtec dot com>, "newlib at sourceware dot org" <newlib at sourceware dot org>
- Date: Wed, 26 Nov 2014 22:47:08 +0000
- Subject: RE: [PATCH,MIPS 1/3] Re-work setjmp/longjmp to match o32 FPXX and FP64 ABI
- Authentication-results: sourceware.org; auth=none
- References: <6D39441BF12EF246A7ABCE6654B0235320F734A0 at LEMAIL01 dot le dot imgtec dot org> <20141126094958 dot GY3810 at calimero dot vinschen dot de> <1417023197 dot 31489 dot 274 dot camel at ubuntu-sellcey>
> > > +#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,