1

I'm trying to convert the following line to SPARC assembly (using negative logic):

if (i < a || i > b) {...}

But I've stuck on how to convert "or" to bitwise or in SPARC. And I couldn't find helpful documentations to convert this. Can someone help? Thank you.

(suppose i is in $l0, a is in $l1, and b is in $l2 )

EDIT:

Here is what I have tried:

    cmp %l0, %l1 ! compare i with a
    bge end_if ! negative logic test to end if statement
    nop
    cmp %l0, %l2 ! compare i with b
    ble end_if ! negative logic test to end if statement
    nop
if:
    /*do something*/
end_if:
    /*statements*/

The more specific question is that how to use a "or" between two cmp instructions? This is getting very confusing to me when using negative logic.

Margaret Bloom
  • 41,768
  • 5
  • 78
  • 124
turf
  • 183
  • 2
  • 2
  • 16
  • What have you tried? Do you want to use [short-circuit evaluation](https://en.wikipedia.org/wiki/Short-circuit_evaluation)? And in the end, no matter what, it's just a question about comparing, testing and conditional jumping. – Some programmer dude Jan 26 '17 at 08:02
  • I suggest you "negate" the original condition first, and then build your assembly code from that. – Some programmer dude Jan 26 '17 at 08:54

2 Answers2

2

your code:

cmp %l0, %l1 ! compare i with a
bge end_if ! negative logic test to end if statement
nop
cmp %l0, %l2 ! compare i with b
ble end_if ! negative logic test to end if statement
nop
if:
    /*do something*/
end_if:
    /*statements*/

is an AND. both sub-conditions must be fulfilled, to reach the "do something" code. (a bit of boolean logic perhaps helps explaining: !(a ^ b) = !a v !b note: the combining operation changes! )

for an OR, you have to use a different logic:

test condition1
jump_if_true doit
test condition2
jmp_if_true doit         ; *1) this branch and
jmp dont_doit            ; this jmp can be optimized

do_it:
   /* do if-part */
   jmp endif
dont_do_it
   /* do else-part */
endif:

now you could be optimized the last 2 jumps to just one

test condition1
jump_if_true doit
test condition2
jmp_if_not_true dont_doit         ; inverted to remove the 2nd jump

doit:
   /* do if-part */
   jmp endif
dont_doit
   /* do else-part */
endif:
Tommylee2k
  • 2,683
  • 1
  • 9
  • 22
1

You can easily check that if (cond1 || cond2) { ... } is equivalent to

if (cond1) goto if_code
if (cond2) goto if_code

goto other_code

if_code:

   ...

other_code:

and that if (cond1 && cond2) { ... } is equivalent to

if ( ! cond1) goto other_code
if ( ! cond2) goto other_code

if_code:

   ...


other_code:

Your implementation matches the second pattern with cond1 := i < a and cond2 := i > b (beware of the negation).
So it is equivalent of if (i < a && i > b){ ... }.

The point is that in a disjunction cond1 || cond2 if cond1 is false it doesn't mean the disjunction is false, the other condition can be true.
The absorption law of the disjunction and conjunction operators is reflected on the implementation in terms of jumps.

In my code I left the short-circuit aspect of the evaluation unspecified. The conditions can be both evaluated ahead of time (no short-circuit) or only if needed (short-circuit).

Margaret Bloom
  • 41,768
  • 5
  • 78
  • 124