1
votes

my final goal is to write a code in MIPS in this way

temp = 0;
if (x == y)
   temp = 1
...rest of the program...

I should write it for == , != , <= , >= , < , >

I thought about something like that :

li $t1 0
beq $r1 $r2 Temp1
/**rest of the program...**/

Temp1:
li $t1 1
(1) /** how do I return to rest of the program? **/

I saw in mips BGEZAL command(insetad of beq) that allows me to put in (1) line

jr $ra

but I have not found appropiate command for all cases : bge,bne,neq etc.

my question :

what is the simple way for all cases to make this branch and link?

I mean,branch to label if some condition happen,and store the address of pc+4 in $ra,so I can return my code?

In Addition,I cant create another label to represent the rest of the program(and jump it),I must return somehow in the $ra,because it is translation from java-based-code to mips

thanks.

1
So you want just to set the temp to 0/1, you don't require the branching, right?Ped7g
yes. branch is just result of using bge,beq,bne(and etc..) commandsMatan
I don't see how translation from java-based is preventing you from creating another label for rest of code, if you can create label for "temp1" code??Ped7g

1 Answers

5
votes

For this example

temp = 0;
if (x == y)
   temp = 1
...rest of the program...

It is easier to use the opposite branch:

li    $t1, 0
bne   $r1, $r2, RestOfProgram  ; temp already is 0, so only continue
; here you want temp=1, because x==y, so just set it, and continue
li    $t1, 1
RestOfProgram:
...rest of the program...

So you are doing this:

temp = 0;
if (x != y) goto rest_of_program
temp = 1
rest_of_program:
...rest of the program...

(It's ugly pseudo C, but in ASM this is the more elegant and clean way, as "goto" is modus operandi of ASM, while executing only some instruction conditionally is against the ASM nature of "here I have the pc set, so I will execute it").


But you don't need to branch at all (if your goal is to set some register to 0 or 1 by the condition), for example:

temp = (x < y);
slt    $t1, $r1, $r2    ; or "sltu" for unsigned values

temp = (x > y)
slt    $t1, $r2, $r1    ; or "sltu" for unsigned values

EDIT2 (I did miss the existence of <=, >=, ... by pseudo ins and produced not very good part of answer, edited it now to be more accurate and complete):

There are also pseudo instructions sle/sge/seq/sne for <=, >=, ==, !=.

For my own curiosity, I had to take a look how they are implemented, basically:

sgt: temp = (y < x)   (slt with swapped arguments)
sle: temp = !(y < x)  (slt, xori)
sge: temp = !(x < y)  ("sle" with swapped arguments)
seq: temp = |x - y| < 1  (subu, $at=1, sltu)
sne: temp = 0 < |x - y|  (subu, sltu $zero)

EDIT1: if you insist on slower $ra subroutine, then move whole test into Temp1:

li  $t1, 0
jal Temp1_when_equal
... rest of code ...

Temp1_when_equal:      ; will set $t1 to 1 when $r1 == $r2
bne $r1, $r2, Temp1_keep_0
li  $t1, 1
Temp1_keep_0:
jr  $ra

But it is not clear to me why you can do this, and can not do the proper thing, seems very weird, you are probably having some very weird situation (basically I don't believe you, you are probably missing the way how to do branching in injected code without labels, so you think it's not possible, but it is, as long as you can inject the code like in your question, you can also inject branch with "rest of code" target in the scope of injected short code).

And if you really must do this, then consider moving it all to subroutine, so the main code will be only jal set_t1_when_r1_equals_r2 and both li will be together inside the subroutine. That would be at least a bit maintainable, the above example is quite bad.

But the "set by condition" solution is superior to any branching of course.