On Thu, 22 May 2014, Richard Sandiford wrote:

> I can't hope to match Maciej's reply on the details, but like he says,
> my understanding was that this:
> 
> > ADD.D $f20, $f10, $f10
> > MOV.D $f18, $f20
> > SWC1 $f20, 0($sp)
> > MTC1 $2, $f20
> > LWC1 $f20, 0($sp)
> > ADD.D $f16, $f18, $f20
> > ($f16 should be 4*$f10)
> 
> really is required to work for -modd-spreg.  Specifically I thought the
> LWC1 would force $f20 to be become "uninterpreted" and then the ADD.D
> would need to (re)interpret the register pair as D-format.

 But as I wrote it has always worked, even with the MIPS I R2010 FPU.  All 
the CP1 transfer instructions are non-arithmetic and operate on FPRs in 
the raw manner (note that MOV.S and MOV.D do not fall in this class).  And 
they actually have to, or otherwise a sequence like this (typical for a 
MIPS I function epilogue):

        lwc1    $f20,0(sp)
                                # <- hw interrupt taken here
        lwc1    $f21,4(sp)
        jr      ra
         addiu  sp,sp,8

would break on a system with a proper OS such as Linux if a hardware 
interrupt exception was taken right after the first LWC1 that would cause 
a context switch and the other process also switched (lazily) the FP 
context.  Once back to this process, the second LWC1 would fault with a 
Coprocessor Unusable exception that would pull the whole FP context back.  
Once that has completed the LWC1 instruction would only replace one half 
of the double value stored in $f20 (note that the FP context switch 
handler may well use LDC1 instructions if supported by hardware; Linux 
does where possible).

 Yes, it happens that we restore even-numbered FPRs first, before their 
odd-numbered counterparts each, but neither the ABI nor hardware mandates 
that, we could as well swap the order and that would have to work too.

  Maciej

Reply via email to