Home > Back-end >  GNU ARM assembler giving a seemingly irrelevant register in error message
GNU ARM assembler giving a seemingly irrelevant register in error message

Time:02-16

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.

CodePudding user response:

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.

  • Related