This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Inline Assembly: Assembling ARM/Thumb-16 ADDS or ADD with status update


On Wed, Jun 22, 2011 at 7:41 PM, Jeffrey Walton <noloader@gmail.com> wrote:
> On Tue, Jun 21, 2011 at 4:50 AM, Andrew Haley <aph@redhat.com> wrote:
>> On 21/06/11 06:21, Jeffrey Walton wrote:
>>> Hi All,
>>>
>>> ARMv6, -mthumb, and Apple's AS (1.38, probably modified).
>>>
>>> I've got a routine to add two unsigned ints and then check the carry
>>> flag in the CPSR. To perform the add, I use the Thumb-16 ADD
>>> instruction (ADDS is not available).
>>>
>>> __asm__ volatile
>>> (
>>> ?"ldr ?r4, %[xa] ?;" ?// R4 = a
>>> ?"ldr ?r5, %[xb] ?;" ?// R5 = b
>>> ?"add ?r6, r4, r5 ?;" ?// R6 = R4 + R5, set status
>>> ?"bcc ?1f ? ? ?;" ?// jump if carry is clear
>>> ?"mov ?r5, #0 ? ?;" ?// set overflow
>>> ?"str ?r5, %[xc] ?;" ?// write it to memory
>>> ?"1: ? ? ? ?;" ?// jump label
>>> ?"str ?r6, %[xr] ?;" ?// result = R6
>>> ?: [xr] "=m" (result), [xc] "=m" (no_carry)
>>> ?: [xa] "m" (a), [xb] "m" (b)
>>> ?: "r4", "r5", "r6"
>>> ?);
>>>
>>> According to ?'ARM® Developer Suite, v1.2', Section 2.2.8, page 2-9,
>>> the status flags are set with ADD under Thumb-16:
>>>
>>> ? ?The conditional branch instruction is the only Thumb
>>> ? ?instruction that can be executed conditionally on the
>>> ? ?value of the ALU status flags in the CPSR. All data
>>> ? ?processing instructions update these flags, except
>>> ? ?when one or more high registers are specified as
>>> ? ?operands to the MOV or ADD instructions. In these
>>> ? ?cases the flags cannot be updated.
>>>
>>> Unfortunately, the status flags are not being updated.
>>
>> Yes they are, as you'll see when you step through.
>>
>> This is a logic failure: your asm declares that it writes no_carry, but
>> it only does so if carry is set. ?Your asm must also write to no_carry
>> when carry is clear. ?Then your asm will work.
> Thanks Andrew. My bad - what you did not see was the C language
> prologue which initialized no_carry.
>
> I believe the problem is the ADD on Thumb-16 does not set the flags
> (despite the ARM manual cited - perhaps it applies to Thumb-2). When I
> followed the ADD with a CMN, the flags were set.
Finished with the knob turning, and wanted to post results in case
someone else stumbles across this.

According to the Thumb-16 Quick Reference Guide [1], the ADDS
instruction should be available. This appears to be a bug in the
assembler (ie, rejecting a valid sentence of the language). Unless of
course, spurious rejections are OK and expected....

To work around AS's unwillingness to assemble certain mnemonics, one
can emit the bytes via a directive. For example, in the following code
the `.short 0x1809` is actually `ADDS R1, R1, R0`.

Jeff

int add_u32(u32t a, u32t b, u32t* r)
{
    volatile int no_carry;
    volatile u32t result;
	
    __asm__ volatile
    (
        // Per the ARM ABI, A and B are in R0 and R1.

        "mov    r3, #1    ;"	// R3 = no_carry = TRUE
	
        // "adds    r1, r1, r0  ;" // Nope - assembler error
        ".short 0x1809    ;"    // Same as ADDS R1, R1, R0
        "bcc    1f			;"
        "mov	r3, #0		;"	// R3 = no_carry = FALSE
	
        "1:				;"
        "str    r1, %[xr]	;"	// result = R1
        "str    r3, %[xc]	;"	// no_carry = R3
	
	 : [xr] "=m" (result), [xc] "=m" (no_carry)
	 :
	 : "r1", "r3"
    );

    if(r)
        *r = result;

    return no_carry;
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]