[Avrora] Question on binary subtraction
Urs Hunkeler
urs.hunkeler at epfl.ch
Tue Jan 18 07:57:20 PST 2011
Hi,
I'm stuck again, and this time I have the exact location of the problem,
but I don't understand what's going wrong. Maybe someone can help me here?
The C code of the problematic part looks like this (from
TransformAlarmC.nc in TinyOS 2.x):
if (remaining > MAX_DELAY)
The problem is that the body of the if-statement is executed even though
at this point the variable "remaining" is 0, and the constant MAX_DELAY
is 1024.
The corresponding assembly code (as obtained with the msp430-objdump
tool) looks like this:
42ce: 0c 48 mov r8, r12 ;
42d0: 0d 49 mov r9, r13 ;
42d2: 3c 80 01 04 sub #1025, r12 ;#0x0401
42d6: 0d 73 sbc r13 ;
42d8: 17 28 jnc $+48 ;abs 0x4308
So this means subtract 1025 (to have "greater" instead of "greater or
equal") from "remaining" (which is 32-bits and stored in registers r8
and r9). If the carry bit is not set, then do not execute the body of
the if-statement (or, if the carry bit is set, then execute the body of
the if-statement).
Since this is a subtraction with a negative result, I would expect the
carry-bit to be set, but then the assembly code doesn't make sense. So
maybe I misunderstand how the carry bit works?
In any case, the Avrora MSP430 interpreter (the part of the MSP430 code
that has been available for a while on SF and probably has been written
by Ben) performs the subtraction with the following outcome (as I would
have expected):
Sub: 0 - 1025 - 0 = -1025, C = true, N = true, Z = false, V = false
Sub: 0 - 0 - 1 = -1, C = true, N = true, Z = false, V = false
And it then obviously executes the body of the if-statement, which
results in the TinyOS timer code malfunctioning. This code works on real
hardware. What is wrong here?
The subtraction code in the MPS430InstInterpreter class is the following
(not written by me):
public int performSubtractionW(int r1, int r2, int carry) {
int result = r2 - r1 - carry;
boolean Rd15 = bit_get(r1, 15);
boolean Rr15 = bit_get(r2, 15);
boolean R15 = bit_get(result, 15);
C = !Rd15 && Rr15 || Rr15 && R15 || R15 && !Rd15;
N = R15;
Z = low(result) == 0 && high(result) == 0;
V = Rd15 && !Rr15 && !R15 || !Rd15 && Rr15 && R15;
return result;
}
Thanks for any help, comments or suggestions!
Cheers,
Urs
More information about the Avrora
mailing list