On Wed, Jun 22, 2011 at 7:41 PM, Jeffrey Walton <noloader@xxxxxxxxx> wrote: > On Tue, Jun 21, 2011 at 4:50 AM, Andrew Haley <aph@xxxxxxxxxx> 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; }