Search code examples
assemblyfloating-pointcomparisonmipsspim

MIPS - is there a way to transfer the value of the flag in coprocessor 1 to integer registers of coprocessor 0?


I'm making a compiler for a school project and I am using MIPS assembly as my target code. But that's not important. I know that operations involving floating-point numbers are done in coprocessor 1 and that result of comparison instructions like c.eq.d and c.le.d are in the flag that can be tested through bc1t and bc1f. Is there a way that the MIPS can transfer the value of the flag to coprocessor 0's registers (e.g. $a0) without using the branching instruction of bc1t and bc1f. If this is impossible, how can I create anonymous labels in SPIM? It seems like SPIM doesn't support this feature. (Pls correct me if i'm wrong.)


Solution

  • You could use MOVF (or MOVT) to put a value in a GPR based on a single FP condition code:

    MOVF rd, rs, cc
    
    To test an FP condition code then conditionally move a GPR
    
    If the floating point condition code specified by CC is zero, then the contents of GPR rs are placed into GPR rd.
    

    Or, if you want all the condition codes at once you could use CFC1:

    CFC1 rt, fs
    
    Copy the 32-bit word from FP (coprocessor 1) control register fs into GPR rt.
    
    if fs = 0 then
        temp <- FIR
    elseif fs = 25 then
        temp <- 0^24 || FCSR31..25 || FCSR23
    elseif fs = 26 then
        temp <- 0^14 || FCSR17..12 || 0^5 || FCSR6..2 || 0^2
    elseif fs = 28 then
        temp <- 0^20 || FCSR11.7 || 0^4 || FCSR24 || FCSR1..0
    elseif fs = 31 then
        temp <- FCSR
    else
        temp <- UNPREDICTABLE
    endif
    GPR[rt] <- temp
    

    The bits you want are 23 and 25..31, so either $f25 or $f31 should be appropriate to use as fs.