user
user

Reputation: 47

C ternary conditional operator to MIPS assembly with one side loaded from memory

C statement

A= A? C[0] : B;

Is is correct to write in assembly instruction this way? Assuming $t1=A, $t2=B, $s1=base address of Array C:

         beq   $t1, $0,  ELSE
         lw    $t1, 0($s1)
ELSE:    add   $t1, $t2, $0

Upvotes: 0

Views: 682

Answers (3)

Peter Cordes
Peter Cordes

Reputation: 365277

You can avoid an unconditional j. Instead of structuring this as an if/else, always do the A=B (because copying a register is cheaper than jumping) and then optionally do the load.

On a MIPS with branch-delay slots, the delay slot actually helps us:

# $t1=A, $t2=B, $s1=base
    beq   $t1, $zero,  noload
    move  $t1, $t2                  # branch delay: runs always

    lw    $t1, 0($s1)
noload:
    # A= A? C[0] : B;

On a MIPS without branch-delay slots (like MARS or SPIM in their default config):

# MIPS without branch-delay slots
# $t1=A, $t2=B, $s1=base
    move  $t3, $t1              # tmp=A
    move  $t1, $t2              # A=B
    beq   $t3, $zero,  noload   # test the original A

    lw    $t1, 0($s1)
noload:
    # $t1 =   A= A ? C[0] : B;

If we can clobber B and rearrange registers, we can save an insn without a branch-delay:

# MIPS without branch-delay slots
# $t1=A, $t2=B, $s1=base
    beq   $t1, $zero,  noload

    lw    $t2, 0($s1)
noload:
    # $t2 = A.   B is "dead": we no longer have it in a register

A move $t3, $t2 before the BEQ could save B in another register before this sequence. Ending up with your variables in different registers can save instructions, but makes it harder to keep track of things. In a loop, you can get away with this if you're unrolling the loop because the 2nd copy of the code can re-shuffle to get registers back the way they need to be for the top of the loop.

move x, y is a pseudo-instruction for or x, y, $zero or ori x, y, 0. Or addu x, y, $zero. Implement it however you like or let your assembler do it for you.

Upvotes: 0

احمد انور
احمد انور

Reputation: 1

Write a MIPS segment for the C statement

x=5;  y=7; 

Land(x,y,z)   //  z=x &y    as procedure call

if (z>x) y=x+1

Upvotes: -1

MikeCAT
MikeCAT

Reputation: 75062

No, it doesn't seem correct because add $t1, $t2, $0 will be executed even if $t1 != $0.

I hope that this works (not tested):

         beq   $t1, $0,  ELSE
         sll $0, $0, 0 # NOP : avoid the instruction after branch being executed
         lw    $t1, 0($s1)
         j END
         sll $0, $0, 0 # NOP : avoid the instruction after branch being executed
ELSE:    add   $t1, $t2, $0
END:

This code assumes that the elements of C are 4-byte long each.

Upvotes: 3

Related Questions