This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS470 atomic.s bug

 Team,

This customer has found a bug in the atomic.s library. Please confirm the customer's findings below.

After getting the appropriate documentation, learning the ARM Assembly opcode mnemonics, and hand-assembling my own instructions, I have success.

For your reference, I've now reworked the atomic.s file, and have placed hand-coded assembly instructions directly as emitted bytes into the execution stream (.field values).

The resulting compiler generated code is correct, executes correctly, and decompiles correctly, but steps incorrectly (obviously) in the debugger instruction stream.

At present, this is the only work-around I've been able to implement. But the good thing, is that at least it is working and I can continue development. Please let me know when/how this will be addressed in the compiler/assembler.


Here is the issue I've encountered with the TMS470 Compiler in Code Composer Studio. ( Version: 4.2.4.00033 )

I'm attempting to implement a Byte/Short/Long Atomic Byte Swap function, which I intend to use with the bit-banding capability in the ARM Cortex-M3 processor. To get this to compile, I have tried everything from inline assembly, to separate assembly language files, to aliased registers, to ... now giving up trying to use the STREX instruction.

The atomic.s code I've provided/attached compiles as follows:

11 00000000               .thumb
12 00000000               .sect ".text"
13                   
14                    ;; uint8_t  AtomicSwapByte (uint8_t  nValue, uint8_t  *pData);
15                        .global AtomicSwapByte
16                        .thumbfunc AtomicSwapByte
17                    AtomicSwapByte: .asmfunc
18 00000000 3F4FE8D1      ldrexb      r3, [r1] ; [KEEP 32-BIT INS]
19 00000004 0F42E8C1      strexb      r2, r0, [r1] ; [KEEP 32-BIT INS]
20 00000008 2A01          cmp         r2, #1 ; [ORIG 16-BIT INS]
21 0000000a D0F9          beq         AtomicSwapByte ; [ORIG 16-BIT INS]
22 0000000c 4618          mov         r0, r3 ; [ORIG 16-BIT INS]
23 0000000e 4770          bx          lr ; [ORIG 16-BIT INS]
24                        .endasmfunc
25                   
26                    ;; uint16_t AtomicSwapShort(uint16_t nValue, uint16_t *pData);
27                        .global AtomicSwapShort
28                        .thumbfunc AtomicSwapShort
29                    AtomicSwapShort: .asmfunc
30 00000010 3F5FE8D1      ldrexh      r3, [r1] ; [KEEP 32-BIT INS]
31 00000014 0F42E8C1      strexh      r2, r0, [r1] ; [KEEP 32-BIT INS]
32 00000018 2A01          cmp         r2, #1 ; [ORIG 16-BIT INS]
33 0000001a D0F9          beq         AtomicSwapShort ; [ORIG 16-BIT INS]
34 0000001c 4618          mov         r0, r3 ; [ORIG 16-BIT INS]
35 0000001e 4770          bx          lr ; [ORIG 16-BIT INS]
36                        .endasmfunc
37                   
38                    ;; uint32_t AtomicSwapLong (uint32_t nValue, uint32_t *pData);
39                        .global AtomicSwapLong
40                        .thumbfunc AtomicSwapLong
41                    AtomicSwapLong: .asmfunc
42 00000020 3F00E851      ldrex       r3, [r1] ; [KEEP 32-BIT INS]
43 00000024 0F02E841      strex       r2, r0, [r1] ; [KEEP 32-BIT INS]
44 00000028 2A01          cmp         r2, #1 ; [ORIG 16-BIT INS]
45 0000002a D0F9          beq         AtomicSwapLong ; [ORIG 16-BIT INS]
46 0000002c 4618          mov         r0, r3 ; [ORIG 16-BIT INS]
47 0000002e 4770          bx          lr ; [ORIG 16-BIT INS]
48                        .endasmfunc


When decompiled, or viewed in the debugger, this code becomes:

            AtomicSwapByte:
0x00008C60:   E8D13F4F LDREXB.W        R3, [R1]
0x00008C64:   E8C10F42 STREXB.W        R2, R0, [R1]
0x00008C68:   2A01     CMP             R2, #0x1
0x00008C6A:   D0F9     BEQ             AtomicSwapByte
0x00008C6C:   4618     MOV             R0, R3
0x00008C6E:   4770     BX              R14
            AtomicSwapShort:
0x00008C70:   E8D13F5F LDREXH.W        R3, [R1]
0x00008C74:   E8C10F42 STREXB.W        R2, R0, [R1]
0x00008C78:   2A01     CMP             R2, #0x1
0x00008C7A:   D0F9     BEQ             AtomicSwapShort
0x00008C7C:   4618     MOV             R0, R3
0x00008C7E:   4770     BX              R14
            AtomicSwapLong:
0x00008C80:   E8513F00 LDREX.W         R3, [R1, #0]
0x00008C84:   E8410F02 STREX.W         PC, R0, [R1, #8]
0x00008C88:   2A01     CMP             R2, #0x1
0x00008C8A:   D0F9     BEQ             AtomicSwapLong
0x00008C8C:   4618     MOV             R0, R3
0x00008C8E:   4770     BX              R14

I've encountered the following two issues with the assembler output produced:

1). The STREXH opcode in AtomicSwapShort is incorrectly replaced with a STREXB opcode.
2). The STREX opcode in AtomicSwapLong is incorrectly replaced with a PC relative result location, with an #8 byte offset specified.

Modified atomic.s file

;;*****************************************************************************

;; Title: Disruptive Limited - Inception

;; Author: Robert P. Beyer

;; iSolutions (NZ) Limited

;; Contract: Objective Concepts LLC / Disruptive Limited

;; Date: May 10, 2011

;; Software: Code Composer Studio

;; Hardware: Luminary Micro LM3S5R36, Apple Authentication Co-processor

;;*****************************************************************************

.thumb

.sect ".text"

;; uint8_t AtomicSwapByte (uint8_t nValue, uint8_t *pData);

.global AtomicSwapByte

.thumbfunc AtomicSwapByte

.clink

AtomicSwapByte: .asmfunc

ldrexb r3, [r1]

;; strexb r2, r0, [r1]

.field 0x0F42E8C1

cmp r2, #1

beq AtomicSwapByte

mov r0, r3

bx lr

.endasmfunc

;; uint16_t AtomicSwapShort(uint16_t nValue, uint16_t *pData);

.global AtomicSwapShort

.thumbfunc AtomicSwapShort

.clink

AtomicSwapShort: .asmfunc

ldrexh r3, [r1]

;; strexh r2, r0, [r1]

.field 0x0F52E8C1

cmp r2, #1

beq AtomicSwapShort

mov r0, r3

bx lr

.endasmfunc

;; uint32_t AtomicSwapLong (uint32_t nValue, uint32_t *pData);

.global AtomicSwapLong

.thumbfunc AtomicSwapLong

.clink

AtomicSwapLong: .asmfunc

ldrex r3, [r1]

;; strex r2, r0, [r1]

.field 0x0200E841

cmp r2, #1

beq AtomicSwapLong

mov r0, r3

bx lr

.endasmfunc

;;*****************************************************************************

;;

;; End of the file

;;

;;*****************************************************************************

.end

;; E8410200 strex r2, r0, [r1]

;; E8C10F52 strexh r2, r0, [r1]

;; E8C10F42 strexb r2, r0, [r1]

  • Carlo Marsano said:
    1). The STREXH opcode in AtomicSwapShort is incorrectly replaced with a STREXB opcode.
    2). The STREX opcode in AtomicSwapLong is incorrectly replaced with a PC relative result location, with an #8 byte offset specified.

    These look to be bugs in the compiler. I have filed bug # SDSCM00042007 to track these issues. Please feel free to track the status of the bug using the SDOWP link in my signature. I will also move this post to the compiler forum so the folks there can post any updates on the bug when available.

  • The fix for this bug was already in the works. It will be available in the 4.9.2 release of the compiler.