Thumb2 load/store multiple with fewer than 2 registers in mask may have unpredictable results

gvaleur1 wrote on Friday, May 19, 2017:

Hi, i am getting the following Warning when i am using freeRTOS CM4 port

[asarm] (warning #2118) Thumb2 load/store multiple with fewer than 2 registers in mask may have unpredictable results

My setup is:
FreeRTOS V9.0.0
GCC CM4F port
Compiler GreenHills ARM ‘6,1,6,1’

The problem seems to be in the “xPortPendSVHandler”
Specificly the lines
" stmdb sp!, {r3} \n"
and
" ldmia sp!, {r3} \n"

This also seems wrong to me with a load/store multiple with only one parameter.
Is this something i should be concerned about or that should be fixed?

Best regards
Gustav Valeur

rtel wrote on Friday, May 19, 2017:

This is not something I have come across before, but have not used the
Greenhills compiler. I will need to investigate more - if you find more
information then please post again here. If another register is added
to the list then the stack will be misaligned when vTaskSwitchContext is
called - so if you add more add another 2, not another 1.

rtel wrote on Friday, May 19, 2017:

The manual does not indicate there is an issue with having a single
register. Quoting from the manual:

“Is a list of one or more registers to be loaded or stored, enclosed in
braces. It can contain register ranges. It must be comma separated if it
contains more than one register or register range”

and

“Restrictions
In these instructions:
Rn must not be PC
reglist must not contain SP
in any STM instruction, reglist must not contain PC
in any LDM instruction, reglist must not contain PC if it contains LR
reglist must not contain Rn if you specify the writeback suffix.”

waveringradiant wrote on Friday, May 19, 2017:

Interesting discussion.

I don’t know if this adds anything to the discussion, but ARM’s own RealView Assembler User’s Guide (http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.kui0100a/armasm_cihcadda.htm) says this:

Restrictions on [LDM and STM] reglist in 32-bit Thumb-2 instructions:

  • In 32-bit Thumb-2 instructions:
  • the sp cannot be in the list
  • the pc cannot be in the list in an STM instruction
  • the pc and lr cannot both be in the list in an LDM instruction
  • there must be two or more registers in the list. (emphasis mine)

richard_damon wrote on Saturday, May 20, 2017:

I see a comment:

If you write an STM or LDM instruction with only one register in reglist, the assembler automatically substitutes the equivalent STR or LDR instruction. Be aware of this when comparing disassembly listings with source code.
You can use the --diag_warning 1645 assembler command-line option to check when an instruction substitution occurs.

Could they default that warning on?

rtel wrote on Saturday, May 20, 2017:

I just scanned through for all occurrences of the instruction and come
across statements like this:

“If the list contains more than one register, the instruction is
assembled to encoding T1 or T2. If the
list contains exactly one register, the instruction is assembled to
encoding T1 or T3.”

but later…

“Encoding T2 does not support a list containing only one register. If an
STM instruction with just one
register in the list is assembled to Thumb and encoding T1 is not
available, it is assembled to
the equivalent STR ,[]{,#4} instruction.
The SP and PC cannot be in the list.
Encoding T2 is not available for instructions with the base register in
the list and ! specified, and the
use of such instructions is deprecated. If the base register is not the
lowest-numbered register in the
list, such an instruction stores an UNKNOWN value for the base register.”

This seems to back up your assertion - the instruction is just changed
to an equivalent.

gvaleur1 wrote on Monday, May 22, 2017:

Hi guys thank you for the ideas i have tried to replace the instructions with the respective LDR and STR instructions but it goes directly into a hardfault, so we have decided to stay with the STMDB and LDMIA instructions and ignore the warning for now.

Looking at the assembly generated with the Green Hills compiler it looks like it is leaving in the STMDB and LDMIA commands.

If any of you have the assembly from keil i would love to see what it does to this instruction, i will try with GCC myself later today, and report back here with the code it generates.

Best regards
Gustav

rtel wrote on Monday, May 22, 2017:

GCC outputs:

0x000058F8 F84D3D04 STR r3,[sp,#-0x04]!
In any case I think it preferable to push two registers as in fact that
would result in an 8-byte stack alignment inside vTaskSwitchContext() -
in case future compiler versions object to something in that function
with only a four byte alignment.

gvaleur1 wrote on Monday, May 22, 2017:

So your suggestion is to change to:
" stmdb sp!, {r3-r4} \n"
and
" ldmia sp!, {r3-r4} \n"

i can see in GCC
" ldmia sp!, {r3-r4} \n"
is changed to
pop {r3, r4}

but this should not be a problem and i will check what Green Hills does when i am back at work tommorow.

rtel wrote on Monday, May 22, 2017:

Yes - I’ve just made the same change in the mainline - but not tested it
yet.

gvaleur1 wrote on Monday, May 22, 2017:

i did a quick test on a STM32f4 and it sems to run fine