Question

I came across the instruction jalr $t1, $t2 instruction, which supposedly sets $t1 to the return address and jumps to $t2. However, there seems to be some ambiguity as to which operation happens first. For instance, the following works differently in MARS and SPIM:

.text
main:
    la $t0, func
    jalr $t0, $t0
    # ...
    li $v0, 10
    syscall        # Exit program

func:
    # ...
    jr $t0

In MARS, $t0 is first set to pc + 4 (return address) and then jumps to $t0, so that the code under func is never run. However, SPIM seems to do the oppsite: jump first and then set the value of $t0 to (the previous) pc + 4; thus func is called and runs as usual.

My question is therefore, which simulator implements correct behavior in this case?

Was it helpful?

Solution

From Imagination Technologies' The MIPS32® Instruction Set v5.03 with emphasis added for clarity (registration required for download of the whole document)

Format: JALR rs (rd = 31 implied)  
        JALR rd, rs

Restrictions:

Register specifiers rs and rd must not be equal, because such an instruction does not have the same effect when reexecuted. The result of executing such an instruction is UNPREDICTABLE. This restriction permits an exception handler to resume execution by re-executing the branch when an exception occurs in the branch delay slot. ))

In other words, they're strangely enough both correct.

OTHER TIPS

The MIPS instruction spec says:

Operation:
    I:  temp ← GPR[rs]
        GPR[rd] ← PC + 8
    I+1:if Config1CA = 0 then
            PC ← temp
        else
            PC ← temp<sub>GPRLEN-1..1</sub> || 0
            ISAMode ← temp<sub>0</sub>
        endif

So it would seem that SPIM is correct and MARS is wrong.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top