Reputation:
I have:
CODE
beq $s3, 1, option1
beq $s3, 0, option2
MORE CODE
option1:
code
jr $ra????
option2:
code
jr $ra
I am trying to test s3 if it is a 0 or a 1 and run a different block of code (outputting a string) then continue with the rest of the code starting from immediately after the second beq
If I do it with jr $ra in each statement, I get an infinite loop. If I do it without those, it runs both statements then skips the rest of the code block im in and continues to the next function..
How can I make a branch statement that will bring me back to it when it is done?
Upvotes: 3
Views: 21391
Reputation: 18825
I think what you actually need here, is regular jump instruction which jumps to instruction after the original switch-case:
CODE
beq $s3, 1, option1
beq $s3, 0, option2
return_here:
MORE CODE
option1:
code
j return_here
option2:
code
j return_here
This will jump to option1
or option2
and when finished it will jump to return_here
label. The jr $ra
instruction returns from a subroutine which means that the code would have to be invoked with jal
instruction (storing the current instruction pointer to $ra
and jumping to address).
Upvotes: 4
Reputation: 366
To use use the jump-return (jr) instruction, you must first make a jump using the jump-and-link instruction (jal). This instruction saves the program counter located in the $ra register before jumping to another part of the code. This way, the CPU knows which part of the code to return to when jr is called.
Standard branching instructions (like beq) does not save the program counter, so the CPU doesn't know what part of the code to return to when you call jr unexpectedly. This is why your code goes into a loop when you call jr.
Alternatively, you can also avoid linked jumping all together:
CODE
beq $s3, 1, option1
option1_ret:
beq $s3, 0, option2
option2_ret:
MORE CODE
option1:
code
j option1_ret
option2:
code
j option2_ret
Upvotes: 8