Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GNU ARM assembler giving a seemingly irrelevant register in error message

Goal

I'm building a mutex primitive using gcc inline assembly for a CortexM7 target using the LDREX and STREX instructions, following the Barrier Litmus Tests and Cookbook document from ARM.

Code

static inline void testAcquireLock(unsigned int *lock) {
  unsigned int tempStore1 = 0;
  unsigned int tempStore2 = 0;

  __asm__ volatile(
      "Loop%=:                         \n\t" // "%=" generates unique #
      "LDREX %[ts1], %[lock]           \n\t" // exclusive read lock
      "CMP %[ts1], #0                  \n\t" // check if 0
      "ITT EQ                          \n\t" // block for below conds.
      "STREXEQ %[ts1], %[ts2], %[lock] \n\t" // attempt to ex. store new value
      "CMPEQ %[ts1], #0                \n\t" // test if store suceeded
      "BNE Loop%=                      \n\t" // retry if not
      "DMB                             \n\t" // mem barrier for subsequent reads
      : [lock] "+l"(*lock), [ts1] "=l"(tempStore1), [ts2] "=l"(tempStore2)
      : // inputs
      : "memory");
}

Error Message

The only error shown is below. The assembler is referencing R15, which doesn't seem to be used in the generated assembly? Line 191 in the error message corresponds to the first LDREX instruction seen above.

[build] /tmp/ccEU4dXd.s: Assembler messages:
[build] /tmp/ccEU4dXd.s:191: Error: r15 not allowed here -- `ldrex r1,r3'
[build] /tmp/ccEU4dXd.s:194: Error: r15 not allowed here -- `strexeq r1,r2,r3'

Build/Compiler Options

The project is configured with CMake using the following compiler settings:

target_compile_options(testing
PRIVATE
    -mcpu=cortex-m7
    -mfpu=fpv5-d16
    -mfloat-abi=hard
    -mthumb
    -Wall
    -fdata-sections
    -ffunction-sections
)

Compile command that caused the error:

[build] /usr/bin/arm-none-eabi-gcc -DSTM32F777xx -DUSE_HAL_DRIVER -I<removed>  -g   -mcpu=cortex-m7 -mfpu=fpv5-d16 -mfloat-abi=hard -mthumb -Wall -fdata-sections -ffunction-sections -std=gnu11 -o <removed>.c.obj   -c <removed>.c

Research / What I've Tried

  1. After reading I realize there's two (instruction sets? syntax parsers?) for armv7, and the processor can be in one of two modes for these (ARM and THUMB). But I don't fully understand this, and how it affects the parsing of handwritten assembly.

  2. I suspected, because the processor is in thumb mode (-mthumb), it has something to do with my inline alias constraints? Per documentation I tried switching between "+l", "+r", "+h" but it doesn't seem to change anything.

  3. I tried using hardcoded registers "r3, r4, r5" instead of the inline aliases but that gave the same error.

like image 718
Tegan Avatar asked Oct 29 '25 07:10

Tegan


1 Answers

Per @jester's help, I realized I had the wrong constraint on the GCC-inline variable alias for the lock. It should have been "+m", specifying a memory address instead of a register.

I was also de-referencing the address of the lock when I should have been leaving it as a pointer.

I changed [lock] "+l"(*lock) to [lock] "+m"(lock) and it now builds.

like image 127
Tegan Avatar answered Oct 30 '25 23:10

Tegan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!