Question

The is leaving me baffled, and I really can't figure out why I am getting this problem. I am to create a program in c that outputs an unsigned value just before the C flag is set, using assembly to accumulate a variable with addcc, and send back the value to main in c. I believe the code I have for c is correct:

unsigned int func();

int main(void){
    printf("The max value before the C flag is set is: %u\n", func());
}

Now the problem comes in with the assembly...

.global func
func: save %sp, -128, %sp
addcc %g0, 1, %g0
clr %l0

loop:
bcs away
mov %l0, %i0
addcc %i0, 1, %l0
ba loop
nop

away:
ret
restore

What this should be doing is accumulating %l0, when the C flag is set passing the value back to %i0 and returning it. When I run this, I get 0. This doen's make sense to me, as I believe I should be getting a much larger number. Any help would be appreciated.

Was it helpful?

Solution

The problem is that branches on Sparc are delayed -- the next instruction after the branch will be executed before the branch actually executes. So when you have:

bcs away
mov %l0, %i0

when the C flag is set and this branch is taken, the mov will still execute, overwriting the value in %i0 (the value before the last add that set C) with %l0 (the value after the add -- 0).

If you stick a nop in here:

bcs away
nop
mov %l0, %i0

it should give you the value you want.

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